Skip to content

Instantly share code, notes, and snippets.

@steenhansen
Created November 29, 2020 06:37
Show Gist options
  • Save steenhansen/76e1608b7e2f836562604f3915909007 to your computer and use it in GitHub Desktop.
Save steenhansen/76e1608b7e2f836562604f3915909007 to your computer and use it in GitHub Desktop.
{
const Tuple = function(_expected_types) {
const expected_types = [...arguments];
const isNull = a_value => (a_value === undefined || a_value === null);
const anyNull = (found_null, the_value) => (found_null || isNull(the_value));
const showNulls = the_value => isNull(the_value) ? 'NULL' : the_value.toString();
const constructorName = a_value => Object.getPrototypeOf(a_value).constructor.name;
const scalarType = a_value => a_value.charAt(0).toUpperCase() + a_value.slice(1);
const tupleType = a_value => typeof a_value == 'object' ? objectType(a_value) : scalarType(typeof a_value);
const objectType = a_value => Array.isArray(a_value) ? 'Array' :
constructorName(a_value) == 'Date' ? 'Date' :
constructorName(a_value) == '_Tuple' ? 'Tuple' : 'Object';
const lengthCheck = init_values => {
const init_length = init_values.length;
const expected_length = expected_types.length;
if (init_length !== expected_length) {
throw new TypeError(`Parameter count, ${init_length} does not match constructor ${expected_length}`); } }
const nullCheck = init_values => {
const any_null = init_values.reduce(anyNull, false);
if (any_null) {
const show_nulls = init_values.map(showNulls).join(', ')
throw new ReferenceError(`Null value found in (${show_nulls})`); } }
const typeCheck = init_values =>
init_values.map(function(a_value, tuple_index) {
const expected_type = expected_types[tuple_index].name;
const actual_type = tupleType(a_value);
if(actual_type !== expected_type) {
throw new TypeError(`${expected_type} expected in position ${tuple_index+1} but got ${actual_type}`); } });
const doChecks = init_values => {
lengthCheck(init_values);
nullCheck(init_values);
typeCheck(init_values);
return init_values; }
const freezeValues = init_values => {
let freeze_values = [];
init_values.map(function(a_value, tuple_index) {
freeze_values[tuple_index] = Object.freeze(a_value);
});
return Object.freeze(freeze_values); }
const _Tuple = function(_init_values) {
const init_values = doChecks([...arguments])
const frozen_values = freezeValues(init_values);
_Tuple.prototype.values = () => frozen_values;
};
return _Tuple;
};
const afunc = param => param;
const StringStringDate = Tuple(String, String, Date);
const name_tuple = new StringStringDate('Gunga', 'Din', new Date());
const FuncStringTupleObjectArraySymbol = Tuple(Function, String, Tuple, Object, Array, Symbol);
const big_tuple = new FuncStringTupleObjectArraySymbol(afunc, 'Vertigo', name_tuple, {a:'a'}, [1,2,3], Symbol('a-symbol') );
let [my_func, my_movie, my_name, my_obj, my_arr, my_symbol] = big_tuple.values();
console.log('my_func, my_movie, my_name, my_obj, my_arr, my_symbol == ', my_func, my_movie, my_name, my_obj, my_arr, my_symbol);
const [my_first, my_last, my_now] = my_name.values();
console.log(`${my_first} ${my_last} : ${my_now}`);
// let fail_1 = big_tuple.values().push(99);
// let fail_2 = my_arr.push('14');
// let fail_3 = new StringStringDate('Gunga', null);
// let fail_4 = new StringStringDate('Gunga');
// let fail_5 = new StringStringDate('Gunga', 14);
let my_big = big_tuple.values();
console.log('my_big == ', my_big);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment