I can't find out how to make a function that calls another function at the end.
I want to be able to do something like this:
book.save (err) ->
MyFunc param1, param2, (callbackParam) ->
# some code using callbackParam
MyFunc = (param1, param2) ->
# some other code that defines callbackParam
?.call(callbackParam)
What has to be called and how does it receive the data?
If you want to call MyFunc as:
MyFunc param1, param2, some_function
Then it should look like this:
MyFunc = (param1, param2, callback) ->
# some code that defines callbackParam
callback callbackParam
And if you want to make the callback optional:
MyFunc = (param1, param2, callback) ->
# some code that defines callbackParam
callback? callbackParam
And if you want to supply a specific # (AKA this), then you'd use call or apply just like in JavaScript:
MyFunc = (param1, param2, callback) ->
# some code that defines callbackParam
callback?.call your_this_object, callbackParam
The (callbackParam) -> ... stuff is just a function literal that acts like any other parameter, there's no special block handling like in Ruby (your tags suggest that Ruby blocks are the source of your confusion).
Related
Suppose I have the following code example in Scala:
def myfunc = {
println("hello")
10
}
val myParam = myfunc
When this code runs, myfunc is executed, meaning that the console will print "hello" and myfunc will return the value of 10.
Let's say that I want myParam to hold the function myfunc without invoking it. How can I do it?
Scala differentiates between methods and functions
With def you define a method and with val a function.
Functions can be assigned to a variable without Parentheses myfunc and are called with Parentheses myfunc()
There is a short conversion syntax to assign a method as a function to a variable
mymethod(_) //use as many underscores as arguments.
However it does not work for zero arguments.
For zero arguments the only option is
def mymethod = {
println("hello")
10
}
val myfunc = () => mymethod
See How to use functions as variables (values) in Scala (but please note that the m _-syntax, mentioned in the blog post, will be deprecated in the future).
Given there is a side-effect in myFunc method
def myfunc = {
println("hello") <== side-effect here
10
}
tradition is to anyways hint at that with parenthesis ()
def myfunc() = {
println("hello")
10
}
which has the added bonus of being less confusing regarding eta expansion.
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.
For code reuse purpose I want to capture some logic in a single function and have it called in other modules
Here is the function definition
// Module A
define (require) ->
doSomething(a, b, c) ->
"#{a}?#{b}&#{c}"
And here is how the funciton doSomething is used
// Module B
define(require) ->
a = require 'A'
...
class Bee
constructor: ->
#val = a.doSomething(1, 2, 3)
However in the browser, I got this error message
Uncaught ReferenceError: doSomething is not defined
What is the proper way to export/import a free function in coffeescript?
This:
define (require) ->
doSomething(a, b, c) ->
"#{a}?#{b}&#{c}"
isn't a function definition. That is really this in disguise:
define (require) ->
return doSomething(a, b, c)( -> "#{a}?#{b}&#{c}")
so your module is trying to call the doSomething function and then call what it returns as another function which takes a third function as an argument. Then whatever doSomething(...)(...) returns is sent back from the module.
So when you say this:
a = require 'A'
you're getting "who knows what" in a and that thing doesn't have a doSomething property so a.doSomething(1,2,3) gives you a ReferenceError.
I think you want to wrap your function in an object in your module:
define (require) ->
doSomething: (a, b, c) ->
"#{a}?#{b}&#{c}"
Alternatively, you could just return the function:
define (require) ->
(a, b, c) ->
"#{a}?#{b}&#{c}"
and then use it like this:
doSomething = require 'A'
doSomething(1, 2, 3)
I have following Currying function declaration:
def logString(count: Int)(fun:() => Unit) {
for (n <- 1 to count) { fun }
}
I call this function in this way:
logString(3) { () => print("I") }
The result is nothing - just no output.
Then I just add brackets after "fun" function invocation, inside the body of Currying function declaration:
def logString(count: Int)(fun:() => Unit) {
for (n <- 1 to count) { fun() }
}
The result becomes what is expected:
III
Is this some Scala bug, or there is some rule that I missed when learning Scala?
I know that there is rule that when you declare function like this:
def myFun = 1
we can not invoke it with brackets - the compilation fails.
But having different results when invoking a function with and without brackets seems more like a bug.
Am I right or I miss something about Scala?
Look at the type of fun, it's fun: () => Unit. You can think of that as meaning that when you call it with (), you get Unit in return. Without explicitly calling it, fun refers to the function as a value, not the result of calling it. This is the essence of the concept of higher-order functions.
If it had type fun: => Unit, simply mentioning fun would cause it to be executed, in which case there would be no way to refer the function as a value.
When you have such a declaration
val x = 10
this is a value definition. The value x can be an integer like in this case,
but it can also be a function.
val y = () => println("i'm a function")
However either way, if you call it without parenthesis nothing will happen.
scala> val x = 10
x: Int = 10
scala> val y = () => println("i'm a function")
y: () => Unit = <function0>
scala> x
res0: Int = 10
scala> y
res1: () => Unit = <function0>
When you have a function definition like this:
def z() = println("i'm a function def")
Then you can omit parenthisis and call it without it.
scala> def z() = println("i'm a function def")
z: ()Unit
scala> z
i'm a function def
In your case fun is like a value definition (it's a value parameter).
What happens is that, when Scala evaluates your for expression it will just do nothing with fun.
Just the same as if you did y vs y() from the example above.
I just wanted to share the information summarized by me based on the very helpful answers answers above and some additional research. Might be would be helpful for someone else also.
Functions can be declared in two ways in Scala:
- "call-by-name" - they are represented in the byte code as normal Java functions in a straightforward way.
- "call-by-value" - from Scala's abstract point of view they are stored in variables. Actually in the Byte code they are stored in classes implementing Single Abstract Method interfaces (SAM) and passed around as method parameters or as normal variables.
When we invoke a "call-by-name" function that does not take parameters it is always executed no matter how we call it with or without brackets.
So now myFunction and myFunction() is just the same.
When we invoke a "call-by-value" function that does not take parameters we have two cases:
- when we do not have brackets after it - myFunction - we just refer to the variable pointing to the function without executing function itself.
- when we have brackets - myFunction() - we actually call (execute) the function.
Different ways to declare function:
def myFunction = 5 * 5
This is call-by-name function. Declared this way no brackets allowed when calling it. So calling myFunction() will not compile. Call it this way: myFunction
def myFunction() = 5 * 5
This is call-by-name function. Can call the function with and without brackets - the effect is the same. So myFunction and myFunction() is just the same.
def myFunction = () => 5 * 5
This is call-by-value function (even when declared as def not val) . When calling it with brackets - myFunction() - function is executed, when calling it without brackets - myFunction - function is NOT executed - just val holding it is being mentioned.
Similarly if we declare function as other function's parameter:
def enclosingFunc(myFunction: => Void)
This is call-by-name function. Inside enclosing function it will be executed only if called without brackets - myFunction. With brackets - myFunction() - will not compile.
In this case enclosingFunc could be called this way:
enclosingFunc(n = 1; n +=1)
def enclosingFunc(myFunction: () => Int)
This is call-by-value function. It matters how we invoke it in the body of enclosing function. If invoke it without brackets - myFunction - it will NOT be executed, but we just refer to the object holing it. If invoke it with brackets - myFunction() - it will be called and executed.
In this case enclosingFunc could be called only in this way:
enclosingFunc( () => n = 1; n +=1)
In the first example the function fun doesn't isn't invoked, it juts sort of sits there. Adding the parenthesis cause the passed-in function to be evaluated.
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