So the idea for this updated Protocol definition is that instead of a string for each method on the protocol, the constructor takes
const Collections = new Protocol({ //if the value of the protocol method is NO_DEFAULT, that means it will not fall through, and since //there is not default, it must be implemented for the type, and will error if called for unknown types each:Protocol.NO_DEFAULT,
//if the protocol method is FALL_THROUGH, that means that there is no default, but if the method is called on an
//unknown type, it will try falling back to the object
map:Protocol.FALL_THROUGH,
//this is the default for pluck - it only relies on map, so default works. No fallthrough will happen here
//if fallthrough is desired, you have to code it into the default manually
pluck(key) {
// can expect receiver to implement full protocol including map
return this::map(value => value[key]);
},
//same with shuffle
shuffle(obj) {
var rand;
var index = 0;
var shuffled = [];
// again, using other parts of the protocol lets this be generic
this::each(function(value) {
rand = random(index++);
shuffled[index - 1] = shuffled[rand];
shuffled[rand] = value;
});
return shuffled;
};
});
This new form obviates the need for a way to alter defaults after definition, and allows for a pretty clear way of dictating fallback behavior. I'm open to ideas for the API, but I think something along these lines could work well.