Closed devongovett closed 14 years ago
It would be a bit confusing if this were only on classes and not objects, but of course CoffeeScript has no way of detecting when two classes that share the same name are bound to any old object...
Right now classes act a lot like objects, e.g. fields defined outside of a function have no scope (see issue 499). I'd like to see classes be more like classes in other languages, so I give +1 to this proposal.
Edit: Actually, on second thought, how does this work with extends
? And is it possible for the overhead to only be incurred when the feature is used, rather than every function on every class being a wrapper?
from John's post :
Obviously, there's some pretty big caveats when using this: The overloading only works for different numbers of arguments - it doesn't differentiate based on type, argument names, or anything else. (ECMAScript 4/JavaScript 2, however, will have this ability - called Multimethods - I'm quite excited.) All methods will some function call overhead. Thus, you'll want to take that into consideration in high performance situations.
@TrevorBurnham yes, the overhead would only be necessary when the compiler detects that there are two methods of the same name with a different number of arguments. It works with extends the same way it would work if you wrote it using the switch on arguments length (e.g. above) - all versions of the function essentially act as one, so all of them would be copied over.
It's not a bad idea, however I reckon the issue lies when you start defining your classes in several places or simply extend them:
class NewUsers
find: (id) ->
# find new users by id
class NamedUsers extends NewUsers
find: (first, last) ->
# find users by first and last name
(new NamedUsers).find(10) # should be by first: 10 and not by id: 10
One solution would be to iterate over the properties of the parent prototype and if two functions have the same name -- merge them into one (unexpected behaviour). It gets complicated when you start having methods with the same signature in several child classes or when you use super
to call a parent method which is overloaded.
I think this should be implemented with some library, but not within the core language.
@evilpie I disagree. I think that the reason people don't take advantage of method overloading very much in JavaScript (using a helper library function) is that the extra code that they have to write in order to use it is too great. I think the only way that people will take advantage of it is if it is part of the language itself (with no extra code for them to write).
I dont think that this feature is really necessary and will be used often. You can already do something simliar by using the unpacking mechanisme. find: (parameters) -> {name, last, id}: if parameters? then paramters else {} if id alert "hey #$id" if name and last alert "hello $name $last" if name alert "hai $name"
@StanAngeloff that's a tricky one! Since those methods are essentially different methods of the same name, I think that when one class extended another class with a method of the same name but a different number of arguments, the two would need to be merged (using Resig's method). This makes the behavior exactly the same as if you had two methods of different names - both would be available on the child class. So if one of the methods was on the superclass and one was on the child class, both would be available on the child class. This makes sense if you think of the methods as they would be if they had different names. Calling super shouldn't work in this case because if the methods had different names, there would be no super method. That's how I think about it anyway. :-)
@evilpie again, I disagree. I would use this feature all the time. While your solution is interesting, there are some problems with it that method overloading would solve. First of all, I now have to pass an object to your method instead of just my arguments, which is ok, but is more typing for the user of my function - not so good for API design. This example is very similar to the one I used (above) with the switch on arguments.length, which I described the downsides of (up there). I think that this feature would get used by a lot of people, especially those trying to write APIs in CoffeeScript.
devongovett: I'm fairly skeptical of how the implementation of this would work, and how flexible it would be. Mind pulling together a patch for master
that we can take a look at?
jashkenas: I'll see what I can do. I haven't ever really done any work on the compiler before, so I'll need to familiarize myself with that before I can produce anything of value. Any suggestions on how to get started?
Ah, well, no worries on integration into the compiler, then. How about just a good test-case example of the situations in which you'd use overloading in coffee, and write out what the JavaScript you'd like it to compile into would look like.
If you really want to do this --and I think it would be a great feature personally, then there are two good approaches.
The first is simply adding something to the language to make parameter switching very easy.
find: (*) ->
(id) ->
...
(first, last) ->
...
The syntax no doubt needs adjustment. But you get the idea. This suffers none of the extends issues. It is simply a syntax sugar to make the parameter switching easy.
The other approach is full-on overloading support, and to do that requires introducing a way to mark methods as "new defs" vs. "re-defs".
class NewUsers
find: (id) ->
...
find: (first, last) ->
...
class NamedUsers extends NewUsers
find: (first, last, middle) ->
...
In this case it would be considered a "re-def" and both definitions would be over-ridden in the superclass. Calling super would of course utilize the method signature. But if we did say,
class NamedUsers extends NewUsers
find: *(first, last, middle) ->
...
Just to make up some notation, then it would add the method as a third possible signature rather than over-ride. Of course if two signatures are identical it over-rides regardless.
This ticket was being left open to provide devongovett an opportunity to prove the idea with a patch -- but it's been a while now, so I'm going to close it as a wontfix
. We can re-open it if someone else has a proposed implementation.
My general opinion about method overloading in dynamically typed languages stands ... it's like pattern-matching dispatch, and can't be done very well in such a static fashion because you don't have types on any of your arguments. Dispatching based solely on the number of arguments is crude at best.
How about this syntax or something similar? https://gist.github.com/1089339 I hope that it doesn't introduce parser conflicts...
if anybody seeks this kind of functionality, have a look at multimethod.js, looks promising.
Was really hoping to be able to do this... Any hope of resurrections?
A useful addition to CoffeeScript's class implementation would be method overloading. This would make working with functions that accept a variable number of arguments much easier. For example:
could be written instead of:
which is much more code, and is more complex. John Resig experimented with Method Overloading, and has a good post on how it can be implemented in JavaScript (very simple, actually). Here is the function.
This method would only need to be run when the CoffeeScript compiler detects that there are two functions with the same name and with a different number of arguments.
Caveats
I think that Method Overloading could be a very useful feature to add to CoffeeScript. It would require no syntax changes whatsoever, it is easy to explain to people, and it is very convenient. What do you think?