4 ms·
Exactly: foo.bar() has dynamic behavior based on the runtime type of foo. Why shouldn't foo.bar(baz) similarly be able to distinguish the runtime type of baz an
by twoodfin 11y ago
Exactly: foo.bar() has dynamic behavior based on the runtime type of foo. Why shouldn't foo.bar(baz) similarly be able to distinguish the runtime type of baz and pick the 'right' overload?
Would it be more surprising to Java newbies if it did work that way?
- kazinator 11y agoBut then, what is the point of foo being associated with the class of bar? Multiple dispatch screams for the abolishment of methods as properties of objects, in favor of generic functions. Youc an still have the syntactic sugar obj.foo(arg), but it basically just translates to foo(obj, arg) where foo is a generic function not associated with foo's class in any way, and obj and arg have equal status. This generic function is what has methods.
- kazinator 11y agoBut then, what is the point of foo being associated with the class of bar? Multiple dispatch screams for the abolishment of methods as properties of objects, in favor of generic functions. Youc an still have the syntactic sugar obj.foo(arg), but it basically just translates to foo(obj, arg) where foo is a generic function not associated with foo's class in any way, and obj and arg have equal status. This generic function is what has methods. Say we implemented "funky" numbers, and would like to implement multiplication of funky and real. When funky is the left argument we get funky.mult(real). If real is no the left, we get real.mult(funky). These functions do the same thing (the multiplication is commutative), yet ... they have to live in separate classes? It is nonsensical. Under generic functions, we just have mult(real, funky) and mult(funky, real) which are methods of the generic mult(whatever, whatever). They both belong to the one generic function: that is the more reasonable organization.
- andrioni 11y agoThat's the way Julia does multiple dispatch, and it works well.
- StefanKarpinski 11y ago> But then, what is the point of foo being associated with the class of bar? One benefit is that the name `bar` is looked up in `foo`'s namespace, which means that it doesn't have to be in the current global namespace. This is a mixed blessing, but it's sometimes what you want.
- kazinator 11y agoThat's an interesting point and basically leads us to "member generic functions". An object has some static slot which is a function, and treated as a method: it can be called obj.meth(args, ...). But, this method is also a generic function. A generic function is a function; an object can have a function, and so an object can have a generic function.
- wtbob 11y agoYou're quite right, but does it make sense to conflate objects and namespaces that way? Might it not make more sense to separate the concerns?
- akavi 11y agoIt might, but it also might be more typing/visual noise for little benefit.
- kazinator 11y agoObject must have name spaces by definition, because they are collections of named properties. These name spaces do not have to be conflated with program lexical scopes, whereby if you are a piece of code such and such a "blessed" function, you "see" the name space of the class as if it were lexical variable bindings. You definitely don't want crud like different scopes in the program which are all working with exactly the same object, and want to access slot S, but they all refer to a different S because they are associated with a different place in the inheritance hierarchy, and that hierarchy contains unrelated slots named S at different levels. A given object must just have one S.
- akavi 11y agoPrivate state, no? class Bar def foo(baz :: Baz) ... end end def foo(bar :: Bar, baz :: Baz) ... end could be in this hypothetical language that the former would be allowed to access private member variables on bar = Bar.new, while the latter wouldn't. The questions then are: a) Is private state something we want? b) Could private state access control be implemented in a different way (Lexically? Package level? Additional annotation?)
- kazinator 11y ago> Could private state access control be implemented in a different way The idea of friend functions of a class could be adapted from C++. It could work dynamically like this. Firstly, given obj.slot or obj.fun(); if the type of obj is not known in the given scope, then these accesses are disallowed unless slot and fun are public. Secondly, a class can be (dyamically) associated with a (dynamically extensible) list of friend generic functions. When a new method is being compiled for a generic function, the compiler uses the class information about the argument (which specializes it) to check the friend list of that class. Then inside the friend method, obj.slot and obj.fun() are allowed even if slot and fun are private. (Friendship of compiled code couldn't be revoked; once a method is processed by at least the expanding code walker, if not compiled, then it cannot lose access even if the generic function is removed from the friend list of that class.) Firstly, obj.member could be disallowed if