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 Proc
s:
- Just like methods, lambdas return from themselves, whereas non-lambda
Proc
s return from the enclosing method, just like blocks. - Just like methods, lambdas have strict argument checking, whereas non-lambda
Proc
s have loose argument checking, just like blocks.
Or, in short: lambdas behave like methods, non-lambda Proc
s 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
==
, theequal?
method should never be overridden by subclasses: it is used to determine object identity (that is,a.equal?(b)
iffa
is the same object asb
).
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
Why Does Ruby Builder::Xmlmarkup Add Inspect Tag to Xml
How to Override [] Brackets in Ruby
Is It Ever Necessary to Use 'Chomp' Before Using 'To_I' or 'To_F'
Capistrano and API Keys in Env Variables
How to Get Http Headers Before Downloading with Ruby's Openuri
Undefined Method (Nomethoderror) Ruby
How to Do String Comparison in Ruby
How to Print Stdout Immediately
Automatically Open a File as Binary with Ruby
Ruby String Split with Terminal Strings Empty
Ruby: Could Not Find a Temporary Directory
Skip/Disable Force_Ssl for Particular Controller in Rails
How to Split Routes.Rb into Smaller Files
In Ruby, How to Get Instance Variables in a Hash Instead of an Array