How can I use CoffeeScript's "do" with properties of "this"? - coffeescript

CoffeeScript has the handy do statement to preserve variables in a closure. But how do I preserve properties of this with do? That always seems to fail.
Example: in a class method I want to attach an event handler to an HTML element using jQuery. The handler should call another method of the same class with a parameter. Now if I write:
foo = getBar()
$('div').click -> #handler foo
this will obviously not work, because the function will be executed in a different context that doesn't have a method named handler. However, if I use do and I write this:
foo = getBar()
do (#handler, foo) ->
$('div').click -> #handler foo
that will also fail, since #handler translates to this.handler which does not make it through the closure. What's an elegant way to solve this?

Try using a fat arrow (equals sign)
foo = getBar()
$('div').click => #handler foo
Or, get a reference to handler before your callback.
cbHandler = #handler
foo = getBar()
$('div').click -> cbHandler foo

Related

How can I combine this context with invokeFunction in Nashorn?

I am trying to call a function in Javascript from Java/Nashorn (in Scala, but that's not material to the question).
// JS
var foo = function(calculator){ // calculator is a Scala object
return this.num * calculator.calcMult();
}
The context on the Scala side is like this:
case class Thing(
num: Int,
stuff: String
)
case class Worker() { // Scala object to bind to calculator
def calMult() = { 3 } // presumably some complex computation here
}
I start by getting foo into the JS environment:
jsengine.eval("""var foo = function(calculator){return this.num * calculator.calcMult();}"""
To use this I need two things to be available: 1) 'this' context to be populated with my Thing object, and 2) the ability to pass a Java/Scala object to my JS function (to call calcMulti later). (If needed I can easily JSON-serialize Thing.)
How can I do both and successfully call foo() from Scala?
This may not be the only or cleanest solution, but it does work.
Turns out javascript has the ability to bind a given 'this' context to a function, which creates a "bound function" that has your 'this' visible within it. Then you use invoke() as you normally would on the bound function.
val inv = javascript.asInstanceOf[Invocable]
val myThis: String = // JSON serialized Map of stuff you want accessible in the js function
val bindFn = "bind_" + fnName
javascript.eval(bindFn + s" = $fnName.bind(" + myThis + ")")
inv.invokeFunction(bindFn, args: _*)
If you passed myThis into the binding to include {"x":"foo"} then when invoked, any access within your function to this.x will resolve to "foo" as you'd expect.

Bindings for functions with options parameter

It is common practice in JavaScript to have a function that takes in an options parameter, like so:
function foo({ bar1, bar2, bar3 }) {}
foo({ bar1: 5, bar2: 3 })
In Reason/OCaml, one would prefer to use labelled arguments for these functions:
let foo = (~bar1, ~bar2, ~bar) => {}
foo(~bar1=5, ~bar2=3, ())
Now, I know there is this way of creating Reason/Bucklescript bindings for functions like these:
type barObj;
[#bs.obj] external makeBarObj : (
~bar1: int=?,
~bar2: int=?,
~bar3: int=?,
unit
) => barObj = "";
external foo : barObj => t = "foo";
foo(makeBarObj(~bar1=5, ~bar2=3, ());
Is there, however, a simpler way of writing bindings for such functions? My problem with this approach is that it gets quite "long" when calling a function that takes in an options object, especially if it is a polymorphic argument, e.g.:
foo(`BarObj(makebarObj(~bar1=5, ~bar2=3, ())));
You can construct the object directly instead of using a separate function:
[#bs.val] external foo : Js.t({..}) => t = "";
let foo = (~bar1=?, ~bar2=?, ~bar3=?, unit) =>
foo({
"bar1": Js.Nullable.from_opt(bar1),
"bar2": Js.Nullable.from_opt(bar2),
"bar3": Js.Nullable.from_opt(bar3)
});
Which can be called with just
foo(~bar1=5, ~bar2=3, ());
But beware that this isn't exactly equivalent to what [#bs.obj] produces since properties being undefined are not always interpreted as not being defined.
If you need to pass it wrapped in a variant, you could have the object construction function wrap it. You can also usually define a set of functions instead:
fooWithString("bar");
fooWithOptions(~bar1=5, ~bar2=3, ());
Another hypothesis seems to be this one:
[#bs.obj]
external makeBarObj : (~bar1: string=?, ~bar2: int=?, ~bar3: string=?, unit) => barObj =
"";
[#bs.val] external foo : barObj => t = "foo";
let foo = (~bar1=?, ~bar2=?, ~bar3=?) => foo(makeBarObj(~bar1?, ~bar2?, ~bar3?, ()));
And then this way, the client of the API can simply call:
foo(~bar1=5, ~bar2=3, ())
It's basically the same thing as the solution presented in the question, but this hides the object conversion code in the library so that the client doesn't need to worry about it.

Why are auxilary constructors forced to call the main constructor in Scala?

... and supply it with all necessary arguments even if they where not required for the auxiliary constructor. (Source: http://joelabrahamsson.com/learning-scala-part-four-classes-and-constructors/) This is not the case in Java. What is the reasoning behind that?
In Scala, the primary constructor's parameters are available anywhere inside the class (among other reasons, so you don't have to repeat Java's this.x = x; this.y = y; this.z = z;). If the parameter isn't used, it has no reason to be a parameter in the first place, so consider only the case where it is used. So if you could avoid supplying these parameters, and then got to the place where they are used, what should happen?
The compiler could use default values (null/0/false/etc), which is very likely not what the user wants. Or throw an exception, turning a compilation error into a runtime error, which is the opposite of what we want.
Easy: if a parameter is not required, don't add it to the main constructor.
In java, all constructors also execute the code in the body of the class:
public class Foo {
String x = mkX();
public Foo() { System.out.println("THIS"); }
public static String mkX() { System.out.println("THAT"); return "";}
}
new Foo(); // prints THAT, then THIS
The requirement in scala is actually more relaxed: your main constructor is allowed to have arguments.

Why doesn't the fat arrow bind to this when I pipe my method definition thru an intermediary function?

I have the following code that declares a method which is advised by an intermediary
function before the function result is assigned to a prototype slot.
class A
somemethod: advise => #dosomething()
Why does the fat arrow does not bind to the instance in this case?
Simple answer
When an intermediary is put between the prototype slot name and function
definition you break the syntactic pattern that makes the CS emit the
binding code in the constructor
class A
foo: (paramlist) =>
bar: ()=>
baz: =>
all these method definitions emit this code in the generated Javascript constructor
function A() {
this.foo = __bind(this.foo, this);
this.bar = __bind(this.bar, this);
this.baz = __bind(this.baz, this);
}
If you put something in between you break that syntactic pattern by which the
Coffeescript compiler can recognize that pattern and generated the necessary code.
class A
helpWhereIsMyMethod: processTheFollowing => #doSomething()
In this case no bind calls in the constructor are generated
More complex Answer
When you define a prototype slot (name) and immediately assign a (anonymous) function
to it you have effectively created a handle by which you can later access that function
and "process" it or call it (most of the cases).
If you pipe your function into another function (the intermediary) before binding the result
to a prototype slot you create effectively an anonymous function that you can't access later.
So the Coffeescript compiler doesn't know how to emit the bind code in the constructor
because during object creation time the access to the anonymous function is not given anymore.
Also the intermediary function could generate code of its own and emit this new code to be bound to the prototype slot.

Coffeescript classes and scope and fat and thin arrows

In a fat arrowed function of a coffeescript class, how can I access the scope of the class as well as the function?
Example:
class Example
foo: ->
$('.element').each => # or ->
#bar($(this)) # I want to access 'bar' as well as the jquery element
bar: (element) ->
element.hide()
So in this example, if I use a => then the # refers to the this of the class but the 'this' is then wrong, whereas if I use a -> for the each, then the 'this' is correctly scoped but but then how do I reference the class function bar?
Thanks!
While mak is right, he fails to point out that in coffee script you rarely need jQuery's each method, which as you noticed, punches your execution context in the face without your permission.
class Example
foo: ->
for element in $('.element')
#bar $(element)
bar: (element) ->
element.hide()
Coffee script's looping features support the concept of each without any actual custom library code at all. And they also do not generate a new scope or context meaning you dont need a fat arrow of any kind.
That's because in CoffeeScript # is an alias for this i.e. when you compile your .coffee to .js # will be replaced with this.
If Example::bar is ugly, I don't think there are 'prettier' solutions.
You can store a reference to this before calling .each:
class Example
foo: ->
self = #
$('.element').each ->
self.bar($(this)) # or self.bar($(#))
bar: (element) ->
element.hide()
After checking different solution. Here something appear for me as the most complete sample with each and click :
class MainApp
self = []
constructor: ->
self = #
toDoOnClick: (event) ->
self.bar($(event.target)) #hide the clicked object
bar: (element) ->
element.hide()
sampleMethod:->
$(".myDiv").click (e) -> self.toDoOnClick(e)
$('.element').each ->
self.bar($(this))