And it's a bit overdone in (older) JS (libraries).
And it's a bit overdone in (older) JS (libraries).
In JS:
someObj.someMethod(function(something) {
something
});
Compare to ruby with the block arg: someObj.someMethod do |something|
something
end
That `do` is a special syntactic thing avaialble for passing a single inline-defined closure arg. (You can pass one held in a reference instead of inline-defined, but it actually takes an extra somewhat obtuse step -- the syntax is optomized for inline-defined).This "affordance" says "Yes, we make it really easy to do this, the stdlib does it a lot, please consider doing it all the time in your own code", which goes along with some of what the OP is discussing. Why we write `collection.each {|something| something}` (the braces are an alternate way to pass a block) instead of `for something in collection do...`
def get_widget
with_lock do
return @widget # returns from the method call
end
end
def update_interesting_gadget
@gadgets.each do |g|
g.with_lock do
if g.is_theone?
g.update
break # breaks the enclosing each's while loop
end
end
end someObj.someMethod(something => something);- they have special control flow that interacts with the method call or surrounding function. ie. calling `break` in `something` can early return from `someMethod`, or calling `return` will return from the function containing the `someMethod` call (blocks use `next` to return from them)
- due to using separate syntax / being a separate language construct, there is far better ergonomics in the presence of vargs or default values
Take this contrived example for instance:
def some_method(a = 42)
b = yield
puts "Hey #{a} #{b}"
end
some_method do
break
end
In JS you would have to something horrible like this: const breakSomeMethod = {}; // Could alternatively use an exception
function someMethod(one, two) {
var f, a;
if (typeof one == 'function') {
f = one;
a = 42;
} else {
a = one;
f = two;
}
var b = f();
if (b === breakSomeMethod) {
return;
}
console.log(`Hey ${a} ${b}`)
}
someMethod(() => breakSomeMethod); myList.foreach { x => doTheThingToTheThingEvery(x, 100 millis) }
Of course it's sometimes a bit too much. It starts out cute [1] and handy [2][3][4], then [5] ... [6] :)[0] https://docs.scala-lang.org/tour/basics.html#blocks
[1] https://scastie.scala-lang.org/tpfgE80WTc6QQaHslraJag
[2] https://www.playframework.com/documentation/2.8.x/ScalaActio...
[3] https://stackoverflow.com/q/50370202/44166
[5] https://www.playframework.com/documentation/2.8.x/ScalaActio...
[6] https://miro.medium.com/max/784/1*EMiSTuRIxUPCzWOgLkiXoA.jpe...
val a = { val x = 2; x + 1 }
the syntax you are describing is just a function-valued block.