FWIW, I have been using prototype-based programming in SC for about 14 years now.
Prototype object oriented programming uses generalized objects, which can then be cloned and extended. Using fruit as an example, a “fruit” object would represent the properties and functionality of fruit in general. A “banana” object would be cloned from the “fruit” object and general properties specific to bananas would be appended. Each individual “banana” object would be cloned from the generic “banana” object. Compare to the class-based paradigm, where a “fruit” class would be extended by a “banana” class.
ddwPrototype quark: Proto class – The basic concept of a prototype
ddwChucklib quark: PR class – Global storage for prototypes that are to be used like classes (that is, prototypes stored in the PR collection are not to be modified for specific uses, but only copied/cloned)
Protos are a bit slower than standard classes (they use SC environments – environment variable lookup is slower than local variable access – and method calls have an extra layer of dispatch through doesNotUnderstand
). In practice, for my work, this has never been a major problem.
(
~operator = Proto {
~a = 2;
~b = 3;
~op = '+';
~prep = { |a, b, op|
if(a.notNil) { ~a = a };
if(b.notNil) { ~b = b };
if(op.notNil) { ~op = op };
currentEnvironment // i.e. 'self' -- must return this!
};
~calc = { ~a.perform(~op, ~b) };
};
// inheritance
~mul = ~operator.clone {
~op = '*';
};
)
~mul.copy.prep(5, 7).calc
-> 35
It’s possible to build large systems this way – almost all of my live coding dialect (ddwChucklib-livecode quark) is implemented in prototypes. This means, if I find a bug in a generator, I can change the code, reexecute the definition, and rerun the pattern-set statement that used the generator, and check the results immediately – no library recompilation.
E.g., here’s an abstract syntax tree, all in prototypes: https://github.com/jamshark70/ddwChucklib-livecode/blob/master/parsenodes.scd
hjh