2 ms·
Separating out blocks this way is pretty meaningless. Blocks are a syntactical construct that can be optimized a certain way, and is in MRI. You can obtain a v
by vidarh 1y ago
Separating out blocks this way is pretty meaningless. Blocks are a syntactical construct that can be optimized a certain way, and is in MRI.
You can obtain a value of a block by naming it, and when you do, what you obtain is a proc.
A Ruby implementation could if it chooses make any block a proc, because you shouldn't be able to tell the difference without extensive contortions (e.g. you could iterate over ObjectSpace and show that a block causes the creation - or not - of an object of the Proc class). And in-fact my (woefully buggy and incomplete) Ruby compiler prototype does just that.
- jez 1y agoI think this is the important point. Something I've mentioned about blocks in Ruby before: if you’re prototyping a new interpreted language and don’t want to have to build a JIT that can optimize code, but still want some semblance of good performance, the block approach Ruby picks can be pretty useful. Ruby doesn’t haven to allocate a full-on, garbage-collected, closure object every time a function accepts a block: it only has to do this if the block gets stored to a variable. If the block is only ever yield’d to, the allocation can be skipped. And when your language’s primary looping mechanism is done with blocks, the difference adds up: xs.each do |ys| # with normal closures and no fancy JIT, # the VM has to allocate a closure once per loop: ys.each do |y| end end Ruby was able to get away with its closure-heavy standard library APIs without a JIT for almost 3 decades because of the affordances that blocks provide over procs/lambdas.
- drnewman 1y agoThat's insightful