4 ms·
It's the norm in Scala too. And it's a bit overdone in (older) JS (libraries).
by pas 5y ago
It's the norm in Scala too.
And it's a bit overdone in (older) JS (libraries).
- jrochkind1 5y agoI don't know scala, but the notable thing about ruby vs JS is how ruby provides _syntactic_ support for passing an inline-defined function. 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...`
- hnov 5y agoI think the crucial difference is that a block can control the flow of the enclosing frame, somewhat analogously to python context managers. For example 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
- joelbluminator 5y agoSo Anonymous Ruby blocks act like (or are) Procs (which return from the parent method), not like lambdas, would you say that?
- Brybry 5y agoIn modern JS wouldn't you use an arrow function? someObj.someMethod(something => something);
- didroe 5y agoThe main advantages of Ruby blocks over that approach are: - 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);
- pas 5y agoIn Scala it's called blocks [0], and if a function/method expects one you can provide it inline, eg: 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 https://docs.scala-lang.org/tour/basics.html#blocks [1] https://scastie.scala-lang.org/tpfgE80WTc6QQaHslraJag https://scastie.scala-lang.org/tpfgE80WTc6QQaHslraJag [2] https://www.playframework.com/documentation/2.8.x/ScalaActions#Building-an-Action https://www.playframework.com/documentation/2.8.x/ScalaActio... [3] https://stackoverflow.com/q/50370202/44166 https://stackoverflow.com/q/50370202/44166 [5] https://www.playframework.com/documentation/2.8.x/ScalaActionsComposition#More-complicated-actions https://www.playframework.com/documentation/2.8.x/ScalaActio... [6] https://miro.medium.com/max/784/1*EMiSTuRIxUPCzWOgLkiXoA.jpeg https://miro.medium.com/max/784/1*EMiSTuRIxUPCzWOgLkiXoA.jpe...
- melolife 5y agoScala doesn't really have a name for this, it simply permits you to provide a block in lieu of a parenthesized argument list. Given that blocks are expressions: val a = { val x = 2; x + 1 } the syntax you are describing is just a function-valued block.