Difference Between Lambda and -> Operator in Ruby

Difference between lambda and - operator in Ruby

It's preferable, due to readibility reasons, to use new syntax -> (introduced in Ruby 1.9) for single-line blocks and lambda for multi-line blocks. Example:

# single-line
l = ->(a, b) { a + b }
l.call(1, 2)

# multi-line
l = lambda do |a, b|
tmp = a * 3
tmp * b / 2
end
l.call(1, 2)

It seems a community convention established in bbatsov/ruby-style-guide.

So, in your case, would be better:

scope :paid, ->(state) { where(state: state) }

Differences between Proc and Lambda

There are two main differences between lambdas and non-lambda Procs:

  1. Just like methods, lambdas return from themselves, whereas non-lambda Procs return from the enclosing method, just like blocks.
  2. Just like methods, lambdas have strict argument checking, whereas non-lambda Procs have loose argument checking, just like blocks.

Or, in short: lambdas behave like methods, non-lambda Procs behave like blocks.

What you are seeing there is an instance of #2. Try it with a block and a method in addition to a non-lambda Proc and a lambda, and you'll see. (Without this behavior, Hash#each would be a real PITA to use, since it does yield an array with two-elements, but you pretty much always want to treat it as two arguments.)

What do you call the - operator in Ruby?

In Ruby Programming Language ("Methods, Procs, Lambdas, and Closures"), a lambda defined using -> is called lambda literal.

succ = ->(x){ x+1 }
succ.call(2)

The code is equivalent to the following one.

succ = lambda { |x| x + 1 }
succ.call(2)

Informally, I have heard it being called stabby lambda or stabby literal.

Python lambda vs Ruby lambda

Python lambdas versus functions

Python lambdas are fully functional function objects, they simply lack names and documentation (docstrings), and can only return expressions (no statements). So both named functions and lambdas have closures and can be passed around like objects.

Many Python programmers would prefer not to use Python lambdas because of their drawbacks and no plusses other than being able to provide them as arguments directly in function calls as opposed to creating a named function on a different line.

For Python, other than constraints in lamba creation, there is no difference between a function created by a lambda and a function created by a def statement. Both are the same type of object:

>>> def foo(): return None
>>> bar = lambda: None
>>> import dis
>>> dis.dis(foo)
1 0 LOAD_CONST 0 (None)
3 RETURN_VALUE
>>> dis.dis(bar)
1 0 LOAD_CONST 0 (None)
3 RETURN_VALUE

Ruby lambdas for functional programming

Ruby lambdas are, as I understand it, the best practice way to do functional programming by passing around functions, as they provide closures - and they should be called with the .call method. Ruby lambdas can contain complex/multiline expressions.

Conclusion

To compare, both are fully functional, provide lexical scoping (closures), are anonymous, and lack documentation.

To contrast, Python lambdas return a single expression, while Ruby lambdas can contain multiple lines. Python lambdas are expected to be called directly with possible arguments passed within parens, (), while Ruby lambda best practices is to use the .call method.

Based on the tradeoffs and recognized best practices for each domain, one would expect those who program in Ruby to prefer lambdas, especially for functional programming, and those who use Python to prefer named functions.

Calling/applying lambda vs. function call - the syntax in Ruby is different. Why?

Because in Ruby, methods are not lambdas (like, for example, in JavaScript).

Methods always belong to objects, can be inherited (by sub-classing or mixins), can be overwritten in an object's eigenclass and can be given a block (which is a lambda). They have their own scope for variables. Example method definition:

a = :some_variable
def some_method
# do something, but not possible to access local variable a
end

# call with:
some_method

However lambdas/procs are plain closures, maybe stored in a variable - nothing else:

a = :some_variable
some_lambda = lambda{
# do something, access local variable a if you want to
}

# call with:
some_lambda[]

Ruby combines both approaches with a powerful syntax, for example, passing blocks:

def some_method_with_block(a)
# do something, call given block (which is a lambda) with:
yield(a) ? 42 : 21
end

# example call:
some_method_with_block(1) do |x|
x.odd?
end #=> 42

In Ruby, can you use the lambda or or Proc call method to invoke an iterator?

Here is the way to do it

iterator = -> (name, &block) { block.call name }
iterator.call(4) { |who| puts "It works now #{who} :)" }

P.S. Note i use a shortcut here for a lambda, -> called stabby lambda

Restrictons of Python compared to Ruby: lambda's

I don't think you're really asking about lambdas, but inline functions.

This is genuinely one of Python's seriously annoying limitations: you can't define a function (a real function, not just an expression) inline; you have to give it a name. This is very frustrating, since every other modern scripting language does this and it's often very painful to have to move functions out-of-line. It's also frustrating because I have a feeling Python bytecode can represent this trivially--it's just the language syntax that can't.

Javascript:

responses = {
"resp1": {
"start": function() { ... },
"stop": function() { ... },
},
"resp2": {
"start": function() { ... },
"stop": function() { ... },
},
...
}
responses["resp1"]["start"]();

Lua:

responses = {
resp1 = {
start = function() ... end;
end = function() ... end;
};
...
}
responses.resp1.start();

Ruby:

responses = {
"resp1" => {
"start" => lambda { },
"stop" => lambda { },
},
}
responses["resp1"]["start"].call

Python:

def resp1_start():
pass
def resp1_stop():
pass
responses = {
"resp1": {
"start": resp1_start,
"stop": resp1_stop,
},
}
responses["resp1"]["start"]()

Note that JavaScript and Lua don't have lambdas: they have no reason to exist, since inline functions cover them in a much more natural and general way.

I'd probably rate this as the single most annoying day-to-day Python limitation.

Comparing two lambdas/Procs in Ruby

While the lambda is effectively equivalent, each call to LambdaFunctions.LambdaFunction1 returns a new instance of the lambda. It would make sense for procs to be equivalent only by identity, not by value, since it would be virtually impossible to determine programmatic equivalence.

What I mean is, if procs could be determined to be equivalent based on what they did, then lambda { 3 } and lambda { 1 + 2 } would be equivalent. With lambdas any more complicated than that, to determine equivalence would basically require a solution to the halting problem.

To determine equivalent identity (per the comment), refer to Object#equal?:

Unlike ==, the equal? method should never be overridden by subclasses: it is used to determine object identity (that is, a.equal?(b) iff a is the same object as b).

If you really need a and b to be the same object, then you need to return the same lambda every time; this means you need to assign the lambda to an instance variable in the LambdaFunctions class, for instance, and return that.

ruby-1.9.1-p378 > class LambdaFunctions
ruby-1.9.1-p378 ?> @func1 = lambda { |t| t ** 2 }
ruby-1.9.1-p378 ?> def self.LambdaFunction1
ruby-1.9.1-p378 ?> @func1
ruby-1.9.1-p378 ?> end
ruby-1.9.1-p378 ?> end
=> nil
ruby-1.9.1-p378 > a = LambdaFunctions.LambdaFunction1
=> #<Proc:0x0000010099e370@(irb):10 (lambda)>
ruby-1.9.1-p378 > b = LambdaFunctions.LambdaFunction1 # same address as a
=> #<Proc:0x0000010099e370@(irb):10 (lambda)>
ruby-1.9.1-p378 > a == b
=> true


Related Topics



Leave a reply



Submit