Comments (22)
I'm a bit confused as to how we propose to compile it. I think that jnicklaus' proposal created the "self" variable the first time that an @Property was mentioned. That won't work if the @Property is first mentioned within an inner function.
It might make more sense, instead of having a special way to refer to this, to have a shorthand for binding a function to the current context (a-la Prototype and Underscore's bind and bindAll functions). I often have cause to define a function and bind it on the spot.
from coffeescript.
what would the longhand JS look like ?
from coffeescript.
Something like:
(function() {
return original_func.apply(bound_obj, arguments);
})
from coffeescript.
ah so something like
new_func: original_func <= bound_obj
or you could call it on the spot
(click <= this)( => $(this).move())
from coffeescript.
In the ECMAScript 4 notes you took, they take this a step farther, and make this
behave like any other lexically scoped variable. I'm not quite sure what the semantics of that would be, because you have cases like this one:
car: {
drive: =>
this.wheels.each() wheel => # this should be 'car'
this.power(wheel) # this should still be 'car'
wheel.position: =>
this.pos + car.pos # this should be 'wheel'
}
This isn't a problem in Ruby, because a method is not the same thing as a Block/Proc, a method's self
is the object it's called on, a block's self
is the lexical self
where the block was defined. JavaScript has no such distinction. Defining a method is the same as defining a block, and where we might be able to distinguish between functions that are assigned as properties, versus functions that are passed into method calls, it falls apart if you assign a function to a temporary variable, and then pass it into a call.
from coffeescript.
yes it's clear that it's not directly straight forward which 'this' we're talking about. Only thing that springs to mind would be attaching 'self' to the named function (which is always in temporary scope) ala:
car: { drive: => this.wheels.each() wheel => # this should be 'car' drive.this.power(wheel) # this refers to wheel, but drive.this refers to car wheel.position: => this.pos + car.pos # this refers to wheel }
from coffeescript.
As you mentioned above, I think a special way to call a function with the context set to this
would be useful. Not sure what the syntax would look like, here's some ideas:
method-->(x) method!(x) method:(x)
would compile as either
(function() { return method.apply(this, arguments); })(x) or method.call(this,x)
from coffeescript.
The first option is probably the most flexible. I.e.
myfunc* (function() { return myfunc.apply(this, arguments)}) myfunc*(1,2,3) (function() { return myfunc.apply(this, arguments)})(1,2,3)
from coffeescript.
Nice ideas for syntax -- however, we don't want to bind to this
at call time, we wan't to bind to this
lexically, at the point where the inner function is defined, before it gets passed into some other function and loses its sense of identity. So, perhaps something like this:
square: x => x * x
square: x ==> x * x
Compiles to:
square = function square(x) {
return x * x;
};
__a = this;
__b = function(x) {
return x * x;
};
square = function square() {
return __b.apply(__a, arguments);
};
from coffeescript.
Ah. It would be useful to be able to bind functions at runtime also, how about:
square: x => x*x # normal square function square2: *square # new square function that's bound to the current context *square(5) # calling a function, bound to the current scope
to
var __self = this; square = function square(x) { return x * x }; square2 = (function () { return square.apply(__self, arguments); }) (function() { return square.apply(__self, arguments); })(5)
from coffeescript.
There's a hiccup in our proposed implementations of binding ... they're multiline statements, meaning that you'd need to wrap them in a closure in order to use them as part of an expression -- and wrapping them in a closure makes their __self = this;
assignment refer to the incorrect this
.
We could do something along these lines:
square = (function(self) {
var __a;
__a = function(x) {
return x * x;
};
return (function square() { return __a.apply(self, arguments); });
})(this);
It's getting p-r-e-t-t-y ugly.
from coffeescript.
Can we not do something like:
When we come across a binding like *my_func
, which means "give me back a function like my_func, but bound to the current value of 'this' ", we push a variable __self to the top of the scope and set it to this
. Then I think the code I suggested should work as is ?
Otherwise I think I'm missing the point somewhere ........
from coffeescript.
(responding to the email here)
Yeah, you're right. The initialization of __self
can be pushed up to the top of the current scope, maintaining the function declaration as an expression. It's not a problem.
I think that your proposed implementation will work beautifully. I'm still not sold on the syntax through. We need some kind of symbol that looks like it means "bind", or perhaps we should just appropriate "bind" as a keyword. The last thing is -- should you be able to pass in an object to bind to, or is binding always done with the current value of "this"?
from coffeescript.
Hmm, a symbol that looks like it means bind... a tough one. Perhaps use &
as it looks a bit like a knot !
&my_func(a,b,c) context&my_func(a,b,c)
Any idea how we might use 'bind' as a keyword ?
from coffeescript.
Haskell's syntax for a different kind of bind is >>=
from coffeescript.
How about ^
(bind to scope) as it seems to point to to current scope.
from coffeescript.
I was just thinking that maybe the bind should fit in with a curry type function with more variables, so the syntax might look like:
create<this> # this is bound to the current value of this create<this: scope> # a function bound to another scope create<x,y> # binding x,y to their current values. create<x:a,y:b> # binding x,y to their current values.
==>
function(_this){ return function() { create.apply(_this, arguments) } }(this) function(_this){ return function() { create.apply(_this, arguments) } }(scope) function(_this, x,y){ return function() { create.apply(_this, x, y) } }(this, x,y)
from coffeescript.
Okay, bound function declarations are now on master. I'm using the long arrow ==>
to signal a function that's bound to the current value of this
. Weepy: I don't think that you ever need a way to bind a function to the current this
as you call it, because that's what already happens when you assign a function to a local variable and call it. Likewise, this proposal leave out currying syntax, because it's not to often needed.
Here's the common-case example of binding a jQuery handler function, and wanting to access properties of this
:
view: {
this.name: "Robert"
this.initialize: =>
$('#robert').bind('click') event ==>
$(event.target).text(this.name)
}
Compiles into this:
var view;
view = {
name: "Robert",
initialize: function initialize() {
var __a;
var __this = this;
return $('#robert').bind('click', (function() {
__a = function(event) {
return $(event.target).text(this.name);
};
return (function() {
return __a.apply(__this, arguments);
});
})());
}
};
It's a little long -- but I can't think of a way to make it shorter. We need to cache the compiled function in the __a
local variable here to make it run fast.
Closing the ticket. Write back if you have a better implementation, and we'll reopen it.
from coffeescript.
How would you use this syntax with a pre-existing function ? Seems a shame to leave that out.
Can you example be written like so :
(function(__a) { return (function() { return __a.apply(__this, arguments); }); })(function(event) { return $(event.target).text(this.name); }))
In which case it would work with a prexisting function (with a different syntax).
from coffeescript.
It's certainly possible to bind pre-existing functions to an object, I just think that it's something better handled by libraries like Underscore or Prototype. We don't have a nice syntax for it, it's not all that common, and the generated code would be quite long compared to _.bind
or Function#bind
.
The reason why the above arguments don't apply equally to the long arrow, is that it's extremely common to want iterator or callback functions bound to the current this
. You have to do it all the time. Here's an article about it:
http://alternateidea.com/blog/articles/2007/7/18/javascript-scope-and-binding
His example (in CoffeeScript, with Prototype):
this.abilities.each((ability =>
this.executeAbility(ability)
).bind(this))
And using the long arrow:
this.abilities.each() ability ==>
this.executeAbility(ability)
If you come up with a really nice syntax for binding pre-existing functions, we can certainly add it.
from coffeescript.
You wanted a syntax for pre-existing functions, how about:
fn: x => x*x y: =fn=> similar to y: x ==> x*x
from coffeescript.
It seems to me that while it can be useful to bind a pre-existing function, the common case would be to create a 'forwarding' function to bind a method to its current receiver, rather than binding a free function to an arbitrary object. In this case, The current fat-arrow/property-shortcut/argument-splat syntaxes already conspire to make this scenario fairly concise and readable without its own particular syntax, eg:
nodeWrapper.addEvent 'click', => @handleClick(arguments...)
from coffeescript.
Related Issues (20)
- Unnecessary `splice` ref added for Array destructuring with rest element not in last position HOT 4
- Bug: Re-ordered nested non-end BindingRestElement doesn't get transpiled HOT 1
- CoffeeScript is fantastic, please donβt give it up HOT 1
- How to imitate `let` behavior in loops? HOT 5
- Proposal: Alternative file extension HOT 1
- Bug: Excessive variable and shallow copy for leading or middle rest parameter
- Proposal: Introduce `let` statement. HOT 6
- Proposal: Document Existential Operator Assignment
- Site issue: code blocks twitch on hover HOT 2
- Proposal: cake command should support ES6 modules HOT 2
- Need help understanding class member meanings HOT 1
- CLI `npm` `scripts` and input `.coffee` file/s as last argument conflicting with `--watch` HOT 2
- Bug: wrong code is transpiled for function call without parentheses HOT 2
- Proposal: Add end word to close method or class HOT 2
- Bug: Invalid indentation allowed after `do`
- Bug: Remove checkShebangLine multi arguments check HOT 1
- feature_request(html): backend CoffeeScript compilation inside HTML files HOT 3
- Bug: yield cannot be used in do -> expressions reliably? HOT 5
- [not an issue] An embeddable playground for CoffeeScript HOT 1
- Please help HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from coffeescript.