I named a lambda lamb:
lamb = lambda { |name| "hello #{name}"}
lamb.call("Steve") # => "hello Steve"
Since I gave the function a name, it is no longer anonymous. Why do we call it anonymous?
As pointed out already, whether you assign the lambda to a variable or not does not really change the fact that the lambda itself is not named. Look at the difference between how a method object behaves vs a lambda:
def test; end
mt = method(:test)
#=> #<Method: Object#test>
mt.arity
#=> 0
mt.name
#=> :test
l = -> {}
l.arity
#=> 0
l.name
NoMethodError: undefined method `name' for #<Proc:0x007faef08319f8#(irb):13 (lambda)>
As you can see, for a method the name is an inherent part of the method object, for a lambda it is not. What the lambda expression returns is an anonymous function that you then assign to a variable. This is not really different from assigning sum = 1 + 2, where the expression on the right has no inherent connection to the name its assigned to. This is also illustrated by the fact that it's perfectly possible to call a lambda without giving it a name first:
x = 1
->{x+1}.()
#=> 2
Lambdas/procs are only anonymous if they're unnamed, e.g.:
# anonymous lambda
[1,2,3].map(&lambda {|x| x * x})
# named lambda
square = lambda {|x| x * x}
[1,2,3].map(&square)
The lambda in your example is anonymous. "lamb" is not the name of your lambda, it is the name of a local variable whose value is an anonymous lambda method.
The variable does not name the lambda any more than x = 42 results in a named number.
Contrast this with methods in a class. They are named as part of adding them to a class or module.
Related
I would like to dynamically create method_missing on an object, while still allowing it to accept blocks. At the same time, I need to use a closure in the dynamically created method_missing. Here's the problem:
To create the closure, I need to use define_singleton_method to create method_missing, passing it a block to create the closure.
Blocks cannot themselves accept blocks, so the newly created method_missing can't accept a block.
Simple demo, for clarification only (ie, I care about solving the general case, not this specific problem):
close_over_me = "99"
o = Object.new
o.define_singleton_method(:method_missing) do |*all_args|
meth, *args = all_args
"The args passed to #{meth}: #{args}. Special code: #{close_over_me}"
end
p o.hi(42) #=> "The args passed to hi: [42]. Special code: 99"
Now let's say I wanted to pass in a block, which changed the special code somehow, eg, by doubling it. That is, I'd like to write:
p o.hi(42) {|x| 2*x}
Keep in mind I want to achieve all of the following:
It will work with any method name.
method_missing must create a closure when it's dynamically defined. Hence cannot do def o.method_missing...
It must work with any number of arguments, and we don't know the number of arguments in advance. The arguments could be of any type.
Is there any metaprogramming magic that can achieve all these at once?
With the define_method family of methods, the parameter list of the block passed to define_method becomes the parameter list of the method defined by define_method, so all you need to do to take a block parameter is to add a block parameter to the block's parameter list:
close_over_me = "99"
o = Object.new
o.define_singleton_method(:method_missing) do |meth, *args, &blk|
blk ||= -> x { x }
"The args passed to #{meth}: #{args}. Special code: #{blk.(close_over_me)}"
end
p o.hi(42) {|x| x*2 } #=> "The args passed to hi: [42]. Special code: 9999"
Though it is definitely possible:
close_over_me = "99"
o = Object.new
o.define_singleton_method(:method_missing) do |*all_args, &cb|
meth, *args = all_args
yielded = cb.call(13) if cb
"Args #{meth}: #{args}. Code: #{close_over_me}. Yielded: #{yielded}."
end
p o.hi(42)
#=> "The args passed to hi: [42]. Special code: 99. Block yielded:."
p o.hi(42) { |x| 2 * x }
#=> "The args passed to hi: [42]. Special code: 99, Block yielded: 26."
I can not get how it is supposed to work with any amount of arguments, since inside the singleton we should call it explicitly.
It seems to me you are misdesigning things.
Here is modified code - you can expect a block along with all_args.
Block presence has to be validated before issuing a call to it.
Also note that since close_over_me is a string, so doubling it by multiplying by 2 results in "9999".
close_over_me = "99"
o = Object.new
o.define_singleton_method(:method_missing) do |*all_args, &block|
meth, *args = all_args
"The args passed to #{meth}: #{args}. Special code: #{block ? block.call(close_over_me) : close_over_me}"
end
p o.hi(42) {|x| x * 2}
#=> "The args passed to hi: [42]. Special code: 9999"
p o.hi(42)
#=> "The args passed to hi: [42]. Special code: 99"
I'm trying to understand lambda calculus with procs and ruby. Here is some code:
puts -> x { -> y {x.call(y) } }
# => #<Proc:0x2a3beb0#C:/first-ruby.rb:1 (lambda)>
puts -> x { x + 2}.call(1)
# => 3
What does -> signify in above example? Is the call method passing the value to the caller, so in the first example, value y is passed to y and in the second example, 1 is passed to x? In the second example, why is 1 evaluated to x?
This is a shortcut for the pure lambda expression:
lmbd = -> arg{ something to do with arg } # With ->{} notation
lmbd = lambda { |arg| something to do with arg } # Standard notation
In your first example you invoke puts method with Proc(lambda) object, and that's why you see #<Proc:0x2a3beb0#C:/first-ruby.rb:1 (lambda)> in the output.
In the second example you invoke puts with lmbd.call(1) method, i.e. puts outputs the result of lambda calculation.
So, if you have lmbd variable which is lambda object, you can pass it like any argument and then get it's result by invoke lmbd.call():
lmbd = -> greeting{ puts "#{greeting}, lambda-expression!" }
def say_hello l, text
l.call(text)
end
say_hello lmbd, "Aloha" # => Aloha, lambda-expression!
What does -> signify in above example?
-> is part of the literal syntax for lambdas, just like, say, ' is part of the literal syntax for strings.
Is the .call method just passing the value from to caller,
The call method is the method, which, well, calls (or executes) the lambda. The arguments to the call method are bound to the parameters of the lambda.
so in first example value y is passed to y and in second example 1 is passed to x.
No, in the first example, y is passed to the outer lambda and bound to its x parameter. In the second example, 1 is passed to the lambda and bound to its x parameter.
In second example why how is 1 evaluated to x?
1 does not evalute to x. 1 is an immediate value, and in Ruby, immediate values always evaluate to themselves. 1 will always evaluate to 1, never to x or anything else.
Let's define a function using Ruby lambda.
def plus_two # no args here
->(x) {x + 2} # args go here
end
# assign a value
x = 1
# call it
plus_two.call(x)
# => 3
Your first example is a bit more complex but using this idea you should be able to come up with functional methods.
I'm studying Scala and functional programming is based upon these substitution principles.
Try doing some recursion using these.
It's like calling functions of functions n times.
What would be the base case then?
As for the Lambda Calculus https://github.com/mackorone/lambda/blob/master/intro.pdf
Try to keep things simple and show the steps rather than trying to figure out what a one liner is doing. Yes they are nice but if you can't read it you can't understand it.
Here's something I was just recently working on:
require 'date'
num = DateTime.now.to_time.utc.to_datetime.ajd - 2451545.0
#t = num / 36525.0
# the terms in reverse order form for the array
#l0_a = [1.0/-19880000.0,
1.0/-152990.0,
1.0/499310.0,
0.0003032028,
36000.76982779,
280.4664567]
# make an enumerator
#l0_e = #l0_a.each
# make a lambda to pass the enumerator to.
def my_lambda
->(x) {x.reduce {|acc, el| acc * #t + el} % 360}
end
puts my_lambda.call(#l0_e)
This is mean longitude of the sun formula using enumerator methods and of course a lambda.
Here is validation list and lambda, which validates an object:
valid_specs = ["instrumentalist", "dj", "producer", "songwriter", "teacher"]
validate_obj = lambda do |obj_name, valid|
obj = eval obj_name
p "no such #{obj_name} `#{obj}`" unless valid.include? obj
end
Passing local var to lambda is OK:
spec_id = "tacher"
validate_obj.call("spec_id", valid_specs) #=> no such spec_id `tacher`
But passing block var causes an error:
specs = ["teacher", "songwriter", "producer"]
specs.each do |spec_id|
valid_obj.call("spec_id", valid_specs)
end
#=>:in `eval': undefined local variable or method `spec_id' for main:Object (NameError)
It doesn't seems obvious to me. I'd like to know the reasons for that and how to achieve my goal not to pass var name and var value via two params "spec_id",spec_id.
The lambda doesn’t have a reference to it because the it doesn’t have access to the scope in which it was called (unless that scope happens to be the same as the one it was defined in, as it is in the first case, which is just a side-effect).
The only way to give it access is to pass the binding of the calling scope and call eval on it:
f = ->(name) { eval name }
'foo'.tap { |x| f.('x') } #=> #<NameError: undefined local variable or method `x' for main:Object>
f = ->(binding, name) { binding.eval name }
'foo'.tap { |x| f.(binding, 'x') } #=> "foo"
The only other way is, as you say, to explicitly pass both the variable name and value as two parameters.
You are essentially trying to do this:
myfunc = lambda {puts eval("word"), eval("x")}
words = ["teacher", "songwriter", "producer"]
words.each do |word|
x = 10
myfunc.call
end
But word and x are local variables of the each() block, so the lambda block can't see them. Blocks can see their enclosing scope--but they can't see inside other scopes contained in their enclosing scope. This works:
myfunc = lambda {puts eval("word"), eval("x")}
word = "hello"
x = 10
myfunc.call
--output:--
hello
10
Here is a more interesting version:
func1 = lambda {puts eval "x"}
func2 = lambda {puts x}
x = "hello"
func1.call
func2.call
--output:--
hello
1.rb:23:in `block in <main>': undefined local variable or method `x' for main:Object (NameError)
from 1.rb:27:in `call'
from 1.rb:27:in `<main>'
It looks like the binding for eval() is "bigger" than the closure for the second block: the binding for eval() is the whole enclosing scope outside the block; but the closure formed by the second block only closes over variables that were in the enclosing scope at the time the block was created.
That seems to make sense in light of this example:
b = binding
myfunc = lambda {puts eval("word", b), eval("x", b)}
word = "hello"
x = 10
myfunc.call
--output:--
hello
10
So when you write:
myfunc = lambda {puts eval("word"), eval("x")}
word = "hello"
x = 10
myfunc.call
...it's as if the lambda block is closing over an invisible b variable, which eval() uses by default, and then the code essentially does this: b.word = "hello"; b.x = 10. That works the same way here:
word = nil
x = nil
myfunc = lambda {puts word, x}
word = "hello"
x = 10
myfunc.call
--output:--
hello
10
In other words, a block closes over variables--not values, and the variables that a block closes over can be altered by code that comes after the block.
Does anyone know another ways to pass var name and var value via one param?
There are many ruby objects that can hold more than one piece of data: arrays, hashes, Structs, instances of custom classes, etc.
valid_specs = ["instrumentalist", "dj", "producer", "songwriter", "teacher"]
validate_obj = lambda do |data|
obj_name = data.var_name
obj = eval obj_name, data.binding
p "no such #{obj_name} `#{obj}`" unless valid_specs.include? obj
end
MyData = Struct.new(:var_name, :binding)
specs = ["teacher", "sweeper", "producer"]
specs.each do |spec_id|
mydata = MyData.new("spec_id", binding)
validate_obj.call(mydata)
end
--output:--
"no such spec_id `sweeper`"
But that code can also be written more simply like this:
valid_specs = ["instrumentalist", "dj", "producer", "songwriter", "teacher"]
validate_obj = lambda do |spec_id|
p "no such spec_id `#{spec_id}`" unless valid_specs.include? spec_id
end
specs = ["teacher", "sweeper", "producer"]
specs.each do |spec_id|
validate_obj.call(spec_id)
end
This question already has answers here:
How to dynamically create a local variable?
(4 answers)
Closed 7 years ago.
I'm interested in dynamically setting local variables in Ruby. Not creating methods, constants, or instance variables.
So something like:
args[:a] = 1
args.each_pair do |k,v|
Object.make_instance_var k,v
end
puts a
> 1
I want locally variables specifically because the method in question lives in a model and I dont want to pollute the global or object space.
As an additional information for future readers, starting from ruby 2.1.0 you can using binding.local_variable_get and binding.local_variable_set:
def foo
a = 1
b = binding
b.local_variable_set(:a, 2) # set existing local variable `a'
b.local_variable_set(:c, 3) # create new local variable `c'
# `c' exists only in binding.
b.local_variable_get(:a) #=> 2
b.local_variable_get(:c) #=> 3
p a #=> 2
p c #=> NameError
end
As stated in the doc, it is a similar behavior to
binding.eval("#{symbol} = #{obj}")
binding.eval("#{symbol}")
The problem here is that the block inside each_pair has a different scope. Any local variables assigned therein will only be accessible therein. For instance, this:
args = {}
args[:a] = 1
args[:b] = 2
args.each_pair do |k,v|
key = k.to_s
eval('key = v')
eval('puts key')
end
puts a
Produces this:
1
2
undefined local variable or method `a' for main:Object (NameError)
In order to get around this, you could create a local hash, assign keys to this hash, and access them there, like so:
args = {}
args[:a] = 1
args[:b] = 2
localHash = {}
args.each_pair do |k,v|
key = k.to_s
localHash[key] = v
end
puts localHash['a']
puts localHash['b']
Of course, in this example, it's merely copying the original hash with strings for keys. I'm assuming that the actual use-case, though, is more complex.
interesting, you can change a local variable but you cannot set it:
def test
x=3
eval('x=7;')
puts x
end
test =>
7
def test
eval('x=7;')
puts x
end
test =>
NameError: undefined local variable or method `x' for main:Object
This is the only reason why Dorkus Prime's code works.
I suggest you use the hash (but keep reading for other alternatives).
Why?
Allowing arbitrary named arguments makes for extremely unstable code.
Let's say you have a method foo that you want to accept these theoretical named arguments.
Scenarios:
The called method (foo) needs to call a private method (let's call it bar) that takes no arguments. If you pass an argument to foo that you wanted to be stored in local variable bar, it will mask the bar method. The workaround is to have explicit parentheses when calling bar.
Let's say foo's code assigns a local variable. But then the caller decides to pass in an arg with the same name as that local variable. The assign will clobber the argument.
Basically, a method's caller must never be able to alter the logic of the method.
Alternatives
An alternate middle ground involves OpenStruct. It's less typing than using a hash.
require 'ostruct'
os = OpenStruct.new(:a => 1, :b => 2)
os.a # => 1
os.a = 2 # settable
os.foo # => nil
Note that OpenStruct allows you access non-existent members - it'll return nil. If you want a stricter version, use Struct instead.
This creates an anonymous class, then instantiates the class.
h = {:a=>1, :b=>2}
obj = Struct.new(* h.keys).new(* h.values)
obj.a # => 1
obj.a = 2 # settable
obj.foo # NoMethodError
since you don't want constants
args = {}
args[:a] = 1
args[:b] = 2
args.each_pair{|k,v|eval "##{k}=#{v};"}
puts #b
2
you might find this approach interesting ( evaluate the variables in the right context)
fn="b*b"
vars=""
args.each_pair{|k,v|vars+="#{k}=#{v};"}
eval vars + fn
4
In Ruby, is it possible to pass by reference a parameter with value-type semantics (e.g. a Fixnum)?
I'm looking for something similar to C#'s 'ref' keyword.
Example:
def func(x)
x += 1
end
a = 5
func(a) #this should be something like func(ref a)
puts a #should read '6'
Btw. I know I could just use:
a = func(a)
You can accomplish this by explicitly passing in the current binding:
def func(x, bdg)
eval "#{x} += 1", bdg
end
a = 5
func(:a, binding)
puts a # => 6
Ruby doesn't support "pass by reference" at all. Everything is an object and the references to those objects are always passed by value. Actually, in your example you are passing a copy of the reference to the Fixnum Object by value.
The problem with the your code is, that x += 1 doesn't modify the passed Fixnum Object but instead creates a completely new and independent object.
I think, Java programmers would call Fixnum objects immutable.
In Ruby you can't pass parameters by reference. For your example, you would have to return the new value and assign it to the variable a or create a new class that contains the value and pass an instance of this class around. Example:
class Container
attr_accessor :value
def initialize value
#value = value
end
end
def func(x)
x.value += 1
end
a = Container.new(5)
func(a)
puts a.value
You can try following trick:
def func(x)
x[0] += 1
end
a = [5]
func(a) #this should be something like func(ref a)
puts a[0] #should read '6'
http://ruby-doc.org/core-2.1.5/Fixnum.html
Fixnum objects have immediate value. This means that when they are assigned or
passed as parameters, the actual object is passed, rather than a reference to
that object.
Also Ruby is pass by value.
However, it seems that composite objects, like hashes, are passed by reference:
fp = {}
def changeit(par)
par[:abc] = 'cde'
end
changeit(fp)
p fp
gives
{:abc=>"cde"}