简体   繁体   中英

ruby blocks not first-class

From a language design perspective, why aren't ruby blocks first-class?

Similarly, I think blocks should actually be lambdas, thereby getting rid of the need for cumbersome syntax such as proc {...}.call or &proc or lambda or Proc.new. This would get rid of the need for yield too.

From a language design perspective, why aren't ruby blocks first-class?

Mostly for performance reasons, in as far as I'm aware. Consider:

def test_yield
  yield
end

def test_block &block
  block.call
end

la = lambda {}

def test_lambda l
  l.call
end

Then, benchmark with an empty block for the first two, vs the third with a new la per call or with the same la , and note how much faster the yield goes in each case. The reason is, the explicit &block variable creates a Proc object, as does lambda, while merely yielding doesn't.

A side-effect (which I've actually found uses for, to recursively pipe passed blocks through the use of a proc object), is you cannot yield in a proc or lambda outside some kind of enclosing scope:

foo = proc { yield if block_given? }
foo.call { puts 'not shown' }

def bar
  baz = proc { yield if block_given? }
  baz.call
end

bar { puts 'should show' }

This is because, as I've come to understand it (I lost a lot of hair due to this, until it ticked), block_given? is sent to main when foo calls it, and to bar rather that baz when it gets evaluated in bar.

lambda and proc (and block) have different semantics. Procs/blocks have non-local returns and are less picky about arity; lambdas are more method-like in their behaviour. In my opinion this distinction is useful and procs/blocks/lambdas should NOT be unified as you suggest.

Ruby methods are not functions or first-class citizens because they cannot be passed to other methods as arguments, returned by other methods, or assigned to variables. Ruby procs are first-class, similar to JavaScript's first-class functions

The following code demonstrates how Ruby methods cannot be stored in variables or returned from methods and therefore do not meet the 'first-class' criteria:

class Dog
  def speak
    'ruff'
  end
end

fido = Dog.new
# Ruby methods cannot be stored in variables
# Methods are executed and variables only store values
x = fido.speak
# x stores the method's return value, not the method itself
x # => 'ruff'

# Methods cannot return other methods
# Methods can only return values from other methods
def hi
  Dog.new.speak
end
# hi returns the method's return value, not the method itself
hi # => 'ruff'

a programming language is said to have first-class functions if it treats functions as first-class citizens. Specifically, this means the language supports passing functions as arguments to other functions, returning them as the values from other functions, and assigning them to variables or storing them in data structures.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM