I'm trying to create a Ruby method that:
1. accepts as input a proc which accepts two arguments and
2. returns as output a proc which takes one argument (the other argument being passed in with the first proc.)
Code below. Everything I've read about how Ruby handles functional scope indicates that I should be able to return a proc.call as a variable, and I don't understand why I'm getting an "unexpected return" error (reproduced below the code)
(I'm obviously a beginning Rubyist...my experience has mostly been in JavaScript, where the mechanics of doing this sort of thing are, I think, much more intuitive.)
--
def partial (proc1, val1)
return Proc.new {|val2| return proc1.call(val1,val2)}
end
adder = Proc.new {|a,b| a + b}
sum_five = partial(adder,5)
sum_five.call(10) # -- expecting 15
# unexpected return
# (repl):13:in `block in partial'
# (repl):20:in `<main>'
In Ruby, procs and lambdas treat return differently.
Procs are designed to work within other Ruby control structures, so in that context a return is from the control structure. Lambdas are much more like stand-alone methods, so return returns from the lambda. You get an error because the proc has no context to return from.
Try this:
def partial (proc1, val1)
return lambda {|val2| return proc1.call(val1,val2)}
end
adder = Proc.new {|a,b| a + b}
sum_five = partial(adder,5)
puts sum_five.call(10) # -- expecting 15
Shorter/cleaner ruby syntax:
def composer(proc1, val1)
-> (val2) { proc1.call(val1, val2) }
end
adder = -> (a,b) { a + b }
sum_five = composer(adder, 5)
sum_five.call(10)
Although I don't understand it's name, Ruby already has a method, Proc#curry, that does this:
adder = Proc.new {|a,b| a + b}
sum_five = adder.curry.call(5)
sum_five.call(10) # => 15
sum_five.call(2) # => 7
just watch out, because curry takes an optional argument, which is the number of arguments it should expect before calling the initial proc, so if you pass it the argument you want as the "default" it'll work weird:
adder = Proc.new {|a,b| a + b}
sum_five = adder.curry(5) # NOTE: This is incorrect
sum_five.call(1) # => returns a Proc
sum_five[1][2][3][4][5] # => 3 (the first 2 arguments got passed, the rest ignored)
Related
I'm trying to learn Ruby. I want to pass an arbitrary function and an arbitrary list of arguments and keyword arguments into another function.
for example, I have this arbitrary function below
def dummy_func(a, b)
return a+b
end
And I have this wrapper function
def wrapper(func, *args, **kwargs)
func(args, kwargs))
end
I want it so I can pass my arguments in any of the following ways and still return the correct answer
wrapper(dummy_func, a=1, b=2)
wrapper(dummy_func, 1, b=2)
wrapper(dummy_func, a=1, b=2)
wrapper(dummy_func, 1, 2)
Is this possible in Ruby? What would be an idiomatic way of approaching it?
The idiomatic way is to instead yield to a block.
def dummy_func(a, b, key:)
return a+b+key
end
def wrapper
puts yield
end
a = 4
b = 5
c = 6
wrapper do
dummy_func(a ,b, key: c)
end
Since the block is closure it can see all the same variables that the call to wrapper can. Now there's no need to pass wrapper's arguments through.
If you really want to make your wrapper, you can do some introspection to determine what arguments the wrapped function takes.
def dummy_func(a, b=23, key: 42)
return a+b+key
end
def no_keys(a, b=23)
return a+b
end
def wrapper(func, *array, **hash)
method = self.method(func)
takes_array = method.parameters.any? { |p| [:req, :opt, :rest].include?(p[0]) }
takes_hash = method.parameters.any? { |p| [:keyreq, :key, :keyrest].include?(p[0]) }
if takes_array && takes_hash
self.send(func, *array, **hash)
elsif takes_array
self.send(func, *array)
elsif takes_hash
self.send(func, **hash)
else
self.send(func)
end
end
a = 4
b = 5
c = 6
puts wrapper(:dummy_func, a, b, key:c)
puts wrapper(:no_keys, a, b)
But this is quite a bit more complex and less flexible than yielding to a block. This also limits you to "functions" which are really methods on the main object (there are no function references in Ruby). That's why they're called with self.send. Blocks require no assumptions about what is being wrapped.
The closest you can get is keyword arguments:
https://www.justinweiss.com/articles/fun-with-keyword-arguments/
def hello_message(greeting, time_of_day, first_name:, last_name:)
"#{greeting} #{time_of_day}, #{first_name} #{last_name}!"
end
args = ["Morning"]
keyword_args = {last_name: "Weiss"}
hello_message("Good", *args, first_name: "Justin", **keyword_args)
=> "Good Morning, Justin Weiss!"
Example: LinkedList printing method.
For this object, you will find a printing method using block, proc, and lambda.
It is not clear to me what the advantages/disadvantages are (if any).
Thank you
What is a LinkedList?
A LinkedList is a node that has a specific value attached to it (which is sometimes called a payload), and a link to another node (or nil if there is no next item).
class LinkedListNode
attr_accessor :value, :next_node
def initialize(value, next_node = nil)
#value = value
#next_node = next_node
end
def method_print_values(list_node)
if list_node
print "#{list_node.value} --> "
method_print_values(list_node.next_node)
else
print "nil\n"
return
end
end
end
node1 = LinkedListNode.new(37)
node2 = LinkedListNode.new(99, node1)
node3 = LinkedListNode.new(12, node2)
#printing the linked list through a method defined within the scope of the class
node3.method_print_values(node3)
#---------------------------- Defining the printing method through a BLOCK
def block_print_value(list_node, &block)
if list_node
yield list_node
block_print_value(list_node.next_node, &block)
else
print "nil\n"
return
end
end
block_print_value(node3) { |list_node| print "#{list_node.value} --> " }
#---------------------------- Defining the printing method through a PROC
def proc_print_value(list_node, callback)
if list_node
callback.call(list_node) #this line invokes the print function defined below
proc_print_value(list_node.next_node, callback)
else
print "nil\n"
end
end
proc_print_value(node3, Proc.new {|list_node| print "#{list_node.value} --> "})
#---------------------------- Defining the printing method through a LAMBDA
def lambda_print_value(list_node, callback)
if list_node
callback.call(list_node) #this line invokes the print function defined below
lambda_print_value(list_node.next_node, callback)
else
print "nil\n"
end
end
lambda_print_value(node3, lambda {|list_node| print "#{list_node.value} --> "})
#---------------------------- Defining the printing method outside the class
def print_values(list_node)
if list_node
print "#{list_node.value} --> "
print_values(list_node.next_node)
else
print "nil\n"
return
end
end
print_values(node3)
Examples display how to use different things to do the same. So, there is no principal difference between them in this context:
my_proc = Proc.new { |list_node| print "#{list_node.value} --> " }
node3.block_print_values(node3, &my_proc)
node3.proc_print_value(node3, my_proc)
node3.lambda_print_value(node3, my_proc)
Also, there is possible to define a method by using any of them:
define_method(:my_method, p, &proc { puts p })
my_method 'hello' #=> hello
define_method(:my_method, p, &-> { puts p })
my_method 'hello' #=> hello
But Proc, Lambda, block are not the same. Firstly, need a bit more display how to works magic &. The great article can help with that:
&object is evaluated in the following way:
if object is a block, it converts the block into a simple proc.
if object is a Proc, it converts the object into a block while preserving the lambda? status of the object.
if object is not a Proc, it first calls #to_proc on the object and then converts it into a block.
But this does not show the differences between them. So, now let go to the ruby source:
Proc objects are blocks of code that have been bound to a set of local variables. Once bound, the code may be called in different contexts and still access those variables.
And
+lambda+, +proc+ and Proc.new preserve the tricks of a Proc object given by & argument.
lambda(&lambda {}).lambda? #=> true
proc(&lambda {}).lambda? #=> true
Proc.new(&lambda {}).lambda? #=> true
lambda(&proc {}).lambda? #=> false
proc(&proc {}).lambda? #=> false
Proc.new(&proc {}).lambda? #=> false
Proc created as:
VALUE block = proc_new(klass, FALSE);
rb_obj_call_init(block, argc, argv);
return block;
When lambda:
return proc_new(rb_cProc, TRUE);
Both are Proc. In this case, the difference is just in TRUE or FALSE. TRUE, FALSE - check the number of parameters passed when called.
So, lambda is like more strict Proc:
is_proc = !proc->is_lambda;
Summary of Lambda vs Proc:
Lambdas check the number of arguments, while procs do not.
Return within the proc would exit the method from where it is called.
Return within a lambda would exit it from the lambda and the method would continue executing.
Lambdas are closer to a method.
Blocks: They are called closures in other languages, it is a way of grouping code/statements. In ruby single line blocks are written in {} and multi-line blocks are represented using do..end.
Block is not an object and can not be saved in a variable. Lambda and Proc are both an object.
So, let do small code test based on this answer:
# ruby 2.5.1
user system total real
0.016815 0.000000 0.016815 ( 0.016823)
0.023170 0.000001 0.023171 ( 0.023186)
0.117713 0.000000 0.117713 ( 0.117775)
0.217361 0.000000 0.217361 ( 0.217388)
This shows that using block.call is almost 2x slower than using yield.
Thanks, #engineersmnky, for good references in comments.
Proc is an object wrapper over block. Lambda basically is a proc with different behavior.
AFAIK pure blocks are more rational to use compared to procs.
def f
yield 123
end
Should be faster than
def g(&block)
block.call(123)
end
But proc can be passed on further.
I guess you should find some articles with performance comparison on the toppic
IMO, your block_print_value method is poorly designed/named, which makes it impossible to answer your question directly. From the name of the method, we would expect that the method "prints" something, but the only printing is the border condition, which does a
print "nil\n"
So, while I would strongly vote against using this way to print the tree, it doesn't mean that the whole idea of using a block for the printing problem is bad.
Since your problem looks like a programming assignment, I don't post a whole solution, but give a hint:
Replace your block_print_value by a, say block_visit_value, which does the same like your current method, but doesn't do any printing. Instead, the "else" part could also invoke the block to let it do the printing.
I'm sure that you will see afterwards the advantage of this method. If not, come back here for a discussion.
At a high level, procs are methods that can be stored inside variables like so:
full_name = Proc.new { |first,last| first + " " + last }
I can call this in two ways, using the bracket syntax followed by the arguments I want to pass to it or use the call method to run the proc and pass in arguments inside of parentheses like so:
p full_name.call("Daniel","Cortes")
What I did with the first line above is create a new instance of Proc and assigned it to a variable called full_name. Procs can take a code block as a parameter so I passed it two different arguments, arguments go inside the pipes.
I can also make it print my name five times:
full_name = Proc.new { |first| first * 5 }
The block I was referring to is called a closure in other programming languages. Blocks allow you to group statements together and encapsulate behavior. You can create blocks with curly braces or do...end syntax.
Why use Procs?
The answer is Procs give you more flexibility than methods. With Procs you can store an entire set of processes inside a variable and then call the variable anywhere else in your program.
Similar to Procs, Lambdas allow you to store functions inside a variable and call the method from other parts of the program. So really the same code I had above can be used like so:
full_name = lambda { |first,last| first + " " + last }
p full_name["daniel","cortes"]
So what is the difference between the two?
There are two key differences in addition to syntax. Please note that the differences are subtle, even to the point that you may never even notice them while programming.
The first key difference is that Lambdas count the arguments you pass to them whereas Procs do not. For example:
full_name = lambda { |first,last| first + " " + last }
p full_name.call("Daniel","Cortes")
The code above works, however, if I pass it another argument:
p full_name.call("Daniel","Abram","Cortes")
The application throws an error saying that I am passing in the wrong number of arguments.
However, with Procs it will not throw an error. It simply looks at the first two arguments and ignores anything after that.
Secondly, Lambdas and Procs have different behavior when it comes to returning values from methods, for example:
def my_method
x = lambda { return }
x.call
p "Text within method"
end
If I run this method, it prints out Text within method. However, if we try the same exact implementation with a Proc:
def my_method
x = Proc.new { return }
x.call
p "Text within method"
end
This will return a nil value.
Why did this occur?
When the Proc saw the word return it exited out of the entire method and returned a nil value. However, in the case of the Lambda, it processed the remaining part of the method.
There are many examples how to pass Ruby block as an argument, but these solutions pass the block itself.
I need a solution that takes some variable, executes an inline code block passing this variable as a parameter for the block, and the return value as an argument to the calling method. Something like:
a = 555
b = a.some_method { |value|
#Do some stuff with value
return result
}
or
a = 555
b = some_method(a) { |value|
#Do some stuff with value
return result
}
I could imagine a custom function:
class Object
def some_method(&block)
block.call(self)
end
end
or
def some_method(arg, &block)
block.call(arg)
end
but are there standard means present?
I think, you are looking for instance_eval.
Evaluates a string containing Ruby source code, or the given block, within the context of the receiver (obj). In order to set the context, the variable self is set to obj while the code is executing, giving the code access to obj’s instance variables. In the version of instance_eval that takes a String, the optional second and third parameters supply a filename and starting line number that are used when reporting compilation errors.
a = 55
a.instance_eval do |obj|
# some operation on the object and stored it to the
# variable and then returned it back
result = obj / 5 # last stament, and value of this expression will be
# returned which is 11
end # => 11
This is exactly how #Arup Rakshit commented. Use tap
def compute(x)
x + 1
end
compute(3).tap do |val|
logger.info(val)
end # => 4
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.
Let's say I have a function
def odd_or_even n
if n%2 == 0
return :even
else
return :odd
end
end
And I had a simple enumerable array
simple = [1,2,3,4,5]
And I ran it through map, with my function, using a do-end block:
simple.map do
|n| odd_or_even(n)
end
# => [:odd,:even,:odd,:even,:odd]
How could I do this without, say, defining the function in the first place? For example,
# does not work
simple.map do |n|
if n%2 == 0
return :even
else
return :odd
end
end
# Desired result:
# => [:odd,:even,:odd,:even,:odd]
is not valid ruby, and the compiler gets mad at me for even thinking about it. But how would I implement an equivalent sort of thing, that works?
edit
In reality, the solution to my problem matters to me a lot less than the motivation/reasoning behind it, to help me understand more how ruby blocks work :)
You're so close. Just remove the returns and you're golden.
This is because the block passed to map is a proc (i.e. created with Proc.new), and not a lambda. A return within a proc doesn't just jump out of the proc- it jumps out of the method that executed (i.e. called call on) the proc. A return within a lambda, on the other hand, jumps out of only the lambda.
The proc method returns a lambda in Ruby 1.8, and a Proc in Ruby 1.9. It's probably best to just not use this method and be explicit with which construct you want to use.
I'm guessing you were either in IRB or a plain ruby script when you were trying this out.
a = Proc.new { return }
a.call # fails. Nothing to return from.
def foobar
a = Proc.new { return }
a.call
puts 'hello' # not reached. The return within the proc causes execution to jump out of the foobar method.
end
foobar # succeeds, but does not print 'hello'. The return within the proc jumps out of the foobar method.
b = lambda { return }
b.call # succeeds. The return only returns from the lambda itself.
def bazquux
b = lambda { return }
b.call
puts 'hello' # this is reached. The lambda only returned from itself.
end
bazquux # succeeds, and prints 'hello'
The lesson to learn from this is to use implicit returns unless you can't, I guess.
I suspect this may be a duplicate question, but to give a value out of a block, use next
simple.map do |n|
if n%2 == 0
next :even
else
next :odd
end
end
Shortest variant using Andrew's answer:
simple.map { |n| next :even if n % 2 == 0; :odd }