TyOverby / ares

A Lisp made for easy integration with Rust.
9 stars 1 forks source link

Prototypal inheritance #34

Open TyOverby opened 9 years ago

TyOverby commented 9 years ago

This is obviously a contentious feature to add to any langauge (especially a lisp), but I think that prototypal inheritance is a good way to add code reuse and "inheritance" while not adding complications to the language.

Optional: Method Syntax

Prototypes

When a method is called on a map that does not contain the method name, the next place to look is in the object under 'prototype. If the method is found there, it is called with the outermost object as the first argument (the explicit "this"). If not, that object's prototype is checked, and so on and so forth.

Prototype keyword generator (optional)

Instead of using just 'prototype for accessing the prototype object, we should probably have a single unique symbol generated at runtime and used to set the prototype object.

An example implementation

(define prototype ((lambda () 
    (define proto (gensym))
    (lambda () proto))))

(define myobj {
    'x 1 
    (prototype) { 
        'f (lambda (this) (set this.x 5)) })

(print myobj.x) ; 1
(myobj.f)
(print myobj.x) ; 5
TyOverby commented 9 years ago

CC @bwo

TyOverby commented 9 years ago

If we adopted method syntax (even without prototypal inheritance) it would make things like extending "map" possible.

(define map (lambda (obj f) 
    (switch obj
        list? (map-list obj f)
        option? (map-option obj f)
        truthy? (obj.map f))))

However, if we wanted to use this pattern, we couldn't have fallback, because then the above could infinitely recurse if obj doesn't have a 'map method on it.

Maybe a contains-method? function that could be used to guard against the infinite recursion?

bwo commented 9 years ago

Or a default "not there". I find prototypal inheritance kind of not nice tbh, and don't think we should rush in any particular direction here. I believe racket has a good story for extension (but also, obviously, a lot of work has been put in to it).

On Saturday, October 10, 2015, Ty Overby notifications@github.com wrote:

If we adopted method syntax (even without prototypal inheritance) it would make things like extending "map" possible.

(define map (lambda (obj f) (switch obj list? (map-list obj f) option? (map-option obj f) truthy? (obj.map f))))

However, if we wanted to use this pattern, we couldn't have fallback, because then the above could infinitely recurse if obj doesn't have a 'map method on it.

Maybe a contains-nested? function that could be used to guard against the infinite recursion?

— Reply to this email directly or view it on GitHub https://github.com/TyOverby/ares/issues/34#issuecomment-147149085.

Ben Wolfson "Human kind has used its intelligence to vary the flavour of drinks, which may be sweet, aromatic, fermented or spirit-based. ... Family and social life also offer numerous other occasions to consume drinks for pleasure." [Larousse, "Drink" entry]

bwo commented 9 years ago

(Racket-wise I'm thinking of the stuff described in "Macros that Work Together", which is simple to use but ... not so simple to implement, probably.)

So I think it would be nice, e.g., if we could do this in a way that also lets us define my-type? predicates, and some kind of sensible destructuring operation. The approach outlined here (which is nice) doesn't exclude that but it might force a direction later. Separating out interface + implementor a la clojure, e.g., could also work.

(however, I'm at a conference right now and it's impairing my ability for abstract thought (as in, I'm typing this and simultaneously listening to a speaker).

TyOverby commented 9 years ago

The default not-there is what Lua uses in order to get prototypal inheritance, and it works pretty well for them. The reason I didn't go the lua route is that it feels pretty hacky. That said, I suppose that we could add wrappers around it in order to make it cleaner.

(extend my-obj parent grandparent)

which could use the "not there" default to get prototypal inheritance.

TyOverby commented 9 years ago

What are your thoughts on method syntax? While we're hashing out inheritance stuff, method syntax could be done in the mean-time.