Epiphany: new only *copies* an object, it does not call it. That means it should be fairly easy to make operators objects! Consider: Plus = (*args) { default = { error "No such dispatch" } dispatch = ( String = String.plus Number = Number.plus ) firstkind = {kind {args:0}} if {dispatch.key firstkind} { run { dispatch:firstkind } args } else { default } } So then if you want to add your own type, you do: Plus.dispatch.set MyType MyType.plus Or somesuch. Perhaps: Plus.dispatch:MyType = MyType.plus Colon will need to be pretty clever anyway. For inheritance, you could just copy all the locals over, discarding any commands, perhaps. Well, you can do that a la: Plus = (*args) { locals Plus = { locals Operator } ... } Perhaps this syntax can be equivalent: Plus = (*args) Operator { ... } Allowing that third arg of = to be a Table for multiple inheritance. The the following should work: Operator = (*args) { dispatch = ... default = ... dispatchOperator = (args) { firstkind = {kind {args:0}} if {dispatch.key firstkind} { run { dispatch:firstkind } args } else { run default } } } Plus = (*args) { default = { error "No such dispatch" } dispatch = ( String = String.plus Number = Number.plus ) dispatchOperator args } Another point: classes (prototypes) should be able to not have a constructor, otherwise with the case of: Plus.dispatch:MyType = MyType.plus If MyType were callable, doing this: m = { new MyType } m + "something" Would not work since m would be callable. On the other hand, its argspec could make it decline (+ *args). Perhaps prototypes should work more like in Javascript though? 2006-01-19 15:49:07 Array.prototype.chicken=String; or tags['fred']='chicken'; would make his code blow up 2005-06-15 15:18:06 - Number.prototype.toFixed= new Function('n','return StrS(this,1,n)') 2005-06-02 19:56:18 array.prototype.join=function(sep) { sep.join(this) } So that whenever someone changes Operator, Plus and friends all get changed as well. For that to work we'd probably have to do something like add "prototype" alongside "locals" and add ["prototype"]["locals"] to the path behind locals but in front of globals. # Scoping Though I'm used to Python's globals/locals scoping idea, I think a more considered system might be in order here. Consider triple-nested blocks: ... { first = "first" { # Should first be accessible here? second = "second" # Should that be available to the first block? How about the third? # Even before it's set? (no) { # Should first be available here? Second? third = "third" # Should that be available to first? Second? # Even before it's set? (no) } } } With Python first would be the global space, and second/third the local space. So first is accessible to second, and first and second to third. Third is available to second after it's set, but not first. Essentially what this means is that there is a block between first and second, except for anything that already exists in first. I could allow hybrid static/dynamic typing like in Perl6 by virtue of this: In statically-typed languages such as Java or ML, a variable also has type, meaning that only values of a given class (or set of classes) can be stored in it. In dynamically-typed languages such as Python or Lisp, it is values and not variables which carry type. - http://en.wikipedia.org/wiki/Variable In Pluvo, a variable could have a conditional rather than just a type, which would allow for static duck typing. So in the variables table, instead of being a name: object mapping, it'd be either that or name: (conditional, object) mapping, with the conditional being possibly true or omittable in the normal dynamic typing case. Note that since you can't have a local with the same name as a global (it'd get set in globals then, otherwise), it's a bit silly maintaining two separate tables for it. The scope is a quality of the variable, and it seems as though there is a maximum upwards extent (only) of the variable, so that could be recorded. [[[ Measure the cost of private members via closures: function Point(x, y) { return { getX: function () { return x }, getY: function () { return y } } } for (var i = 0, a = []; i < 1e5; i++) a[i] = new Point(i, i) Over 3x slower and 3x the memory use of function Point1(x, y) { this.x = x this.y = y } ]]] - http://ajaxian.com/downloads/presentations/eich-ajax-experience-2006/ -- Sean B. Palmer, inamidst.com