Skip to content

super.apply(…) does not work as might be expected #3004

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ELLIOTTCABLE opened this issue May 26, 2013 · 16 comments
Closed

super.apply(…) does not work as might be expected #3004

ELLIOTTCABLE opened this issue May 26, 2013 · 16 comments

Comments

@ELLIOTTCABLE
Copy link
Contributor

This seems, to me, very unintuitive:

// super.apply blah
Klass.__super__.constructor.apply(this, arguments).apply(blah);

I'd (hopefully, obviously) expect the following:

// super.apply blah
Klass.__super__.constructor.apply(blah);

Sure, I can do it manually …

// Klass.__super__.constructor.apply blah
Klass.__super__.constructor.apply(blah);

… but still, this seems so unintuitive and ugly.

@vendethiel
Copy link
Collaborator

What you're looking for is super(). See #2354 (and #2638)

@ELLIOTTCABLE
Copy link
Contributor Author

@Nami-Doc that is not at all the case. That still applies the super-implementation to this, which is exactly what I'm trying to avoid. I need to use apply in this context. Does that make sense?

(This is my own fault for using this in my original example code; ammended the issue to make what I'm looking for, more clear. :)

@vendethiel
Copy link
Collaborator

Then I'd say Parent::constuctor.call blah.

@ELLIOTTCABLE
Copy link
Contributor Author

@Nami-Doc still doesn't have bearing on the original issue; and to boot, that's hard-coding the Parent into the body of the function, which the point is to avoid.

Point of this issue is (and please re-open it), that it's unintuitive for super.method() to not be a call to Function#method (whether that's #apply or #call or #toString, or anything else).

@vendethiel
Copy link
Collaborator

This has already been answered in the issue I linked before.

See #2354

@ELLIOTTCABLE
Copy link
Contributor Author

@Nami-Doc … no, it's not.

@jashkenas talks about:

  • this.someOtherMethodOfMine() being invalid because it breaks encapsulation,
  • that super should be a reference to the superclasses' implementation of the current method, not to the superclass itself

… both of which I agree with. The original point, and the one I'm alluding to here, is more clearly made by @michaelficarra:

super should just be a special reference [to the superclass's implementation thereof


The point here is that, with super as a direct reference to the superclasses' implementation, that you could both (intuitively) call it:

// super()
Klass.__super__.constructor.apply(this, arguments)

… as well as calling methods of Function on it (not methods of yourself, as discussed by @jashkenas in #2354):

// super.apply()
Klass.__super__.constructor.apply()
// super.call(foo, bar, baz)
Klass.__super__.constructor.call(foo, bar, baz)

@epidemian
Copy link
Contributor

Yeah, i totally agree with @ELLIOTTCABLE and @michaelficarra in that super should work as a reference to the super-class method instead of as a direct call (use super() instead).

That being said, you can call Function#apply on the super method by using the spread operator (aka splats):

class Foo
  bar: ->
    args = ['hello', 'world']
    # return Foo.__super__.bar.apply(this, args);
    super args...

@vendethiel
Copy link
Collaborator

Also see #2638, which seems to be what you want

@ELLIOTTCABLE
Copy link
Contributor Author

@epidemian that's only applicable if you want to apply the superclass to the current this. In my situation, the relevant object is not the this of the function (the this has been modified/replaced, hence I'm using a variable like that or it to reference the “psuedo-self.”)

@jashkenas
Copy link
Owner

@ELLIOTTCABLE Can you share the actual code from your actual use case here? I'd be curious to see.

@ELLIOTTCABLE
Copy link
Contributor Author

@jashkenas The thought-process that promoted this post is no longer relevant, as I have my construct() handling the super-constructor-application for me; but I feel(?) my observation is still relevant, no? Simply seems intuitive for it to work this way.

The code in question, as it would have looked before the refactor of construct(): https://gist.github.com/elliottcable/5652573

(Unrelated: @jashkenas, I admire your free-spirited nature, and the decision to take the trip you're documenting. Live life to the fullest. <3)

@jashkenas
Copy link
Owner

Simply seems intuitive for it to work this way.

If you're used to Java, perhaps yes. If you're used to Ruby, perhaps no.

I can't think of many use cases where you'd ever want to be calling super (from within a class body, remember), with any context other than the current instance. That's why I'd be interested in a use case. Yours does, indeed, seem like it can be better accomplished in another way.

The (debatable) reason why super should stay the way it is -- is because changing it to a method reference makes the 95% use case of falling back to the parent's implementation while passing along the current arguments look like this every time you write it:

super.apply(this, arguments)

Instead of this:

super

... and thanks for the good cheer. Just walked back from military singing, dancing, and fireworks in the Ulaanbaatar town square.

@ELLIOTTCABLE
Copy link
Contributor Author

Agreed on all points, with one very important caveat:

I was, and this may not have been clear, suggesting that super() be syntactic sugar (I did demonstrate this in one of the compilation examples above) for the special, common case of super.apply(this, arguments). Only if it were not compiled as a call, would it not compile into that.

Does that make a little sense? Of course super() is intuitive for that case; but it's also not intuitive for super (especially when followed by things that expect that to be a reference!) to compile into a call like that. :D

@jashkenas
Copy link
Owner

Not "intuitive" to me, I'm afraid. If I see super(), I see very clearly that zero arguments are being passed to that call.

If I see super highlighted as a keyword in my text editor, then it's possible that I'm delegating to the parent implementation of the current function.

@ELLIOTTCABLE
Copy link
Contributor Author

hm. What about super(arguments)? Or super(…)?

@vendethiel
Copy link
Collaborator

super(arguments) is calling super with only one param. super ... seems okay

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants