Simple Currying in Ruby - ruby

I'm trying to do some currying in ruby:
def add(a,b)
return a+b
end
plus = lambda {add}
curry_plus = plus.curry
plus_two = curry_plus[2] #Line 24
puts plus_two[3]
I get the error
func_test.rb:24:in `[]': wrong number of arguments (1 for 0) (ArgumentError)
from func_test.rb:24:in `'
But if I do
plus = lambda {|a,b| a+ b}
It seems to work. But by printing plus after the assigning with lambda both ways return the same type of object. What have I misunderstood?

You're on the right track:
add = ->(a, b) { a + b }
plus_two = add.curry[2]
plus_two[4]
#> 6
plus_two[5]
#> 7
As others have pointed out, the plus lambda you defined doesn't take any arguments and calls the add method with no arguments.

lambda {|a,b| a+ b}
Creates a lambda which takes two arguments and returns the result of calling + on the first, with the second as its arguments.
lambda {add}
Creates a lambda which takes no arguments and calls add without arguments, which is an error of course.
To do what you want, you should do
plus = lambda {|x,y| add(x,y)}
or
plus = method(:add).to_proc

When you write lambda {add}, you're declaring a Proc that takes no arguments and, as its sole action, calls add with no arguments. It doesn't turn add into a Proc. On the other hand, lambda {|a,b| a + b} returns a Proc that takes two arguments and adds them together — since it takes arguments, it's valid to pass arguments to that one.
I think what you want is method(:add).to_proc.curry.

Related

Calling call() on a function in Ruby

I have code as follows:
def sum(a, b)
a + b
end
puts sum.call 2, 3
I get an error like:
wrong number of arguments (given 0, expected 2) (ArgumentError)
How can I call a function?
EDIT
I want to have a function able to call other one with certain arguments. I've written the code like below but the same error is still displayed.
def sum(a, b)
a + b
end
def kall(func, *args)
send(func, *args)
end
puts kall(sum, 2, 3)
In order to invoke the function sum, just delete the .call call:
def sum(a, b)
a + b
end
sum(1, 2)
# => 3
Other way to call the method is doing:
send(:sum, 1, 2)
Which invokes the method sum on the current context/object with the list of arguments (1, 2).
One more way to call a method is:
method(:sum).call(2, 3)
#=> 5
sum is not a function, it is a method. Methods belong to objects, they aren't objects. Ruby is an object-oriented language, which means you can only store objects in variables, only pass objects as arguments (with the slightly odd exception of blocks), only return objects from methods and only send messages to objects.
You cannot send a message to the sum method, because you can only send messages to objects, and methods aren't objects.
And even if it were possible to send messages to methods, there would still be an ambiguity in your code: Ruby allows you to leave out the argument list to a message send if you don't pass any arguments, therefore
sum
is a valid message send and is (somewhat) equivalent (modulo privacy) to
self.sum()
So, even if it were possible to send messages to methods, Ruby would still think that you try to send the sum message without an argument list.
So, since the problem is that we need an object, there are two things we can do. Firstly, we can use an object to begin with.
You used the term "function" in your question. Well, Ruby doesn't have functions, but it has something close to it: Procs. One solution would be to use a Proc instead of a method:
sum = -> (a, b) { a + b }
sum.(2, 3)
#=> 5
The other solution would be to obtain an object for the method. Ruby's Reflection System has a class called Method which responds to call, instances of which are reflective proxies for methods. You can obtain a Method object by sending the Object#method message to an object, e.g.:
sum = method(:sum)
sum.(2, 3)
#=> 5
You don't need to do .call or anything like that. If the function has no parameters, simply just type the name of the function. And if the function does have parameters, just do myFunction(param1, param2).
def hello
puts 'Hello, World!'
end
def output(string)
puts string
end
# Both of these do the same thing:
hello
hello()
# Doing that with stdout won't work though. It expects one argument, string
output('You can do it with parenthesis')
output 'You can also do it without'

Why does this block not run when it is stored in a proc?

I'm learning ruby and trying to get a better understanding of Blocks, Yield, Procs and Methods and I stumbled upon this example on using yield.
def calculation(a, b)
yield(a, b)
end
x = calculation(5,6) do|a,b|
a + b
end
puts "#{x}"
From what I understand Procs are object that holds a pointer to Blocks. And Blocks need a method to work in the first place. Also, from the way yield is used, I assume yield jumps to the block immediately after the method call.
I assume the code runs this way: calculation(5,6) calls the method calculation(). when the yield instruction executes, a and b are passed to the block after calculation(5,6). To experement and get a better understand I tried doing this.
def calculation(a, b)
yield(a, b)
end
ankh = Proc.new do |a,b|
a + b
end
x = calculation(5,6) *ankh
The error says that no block is given to calculation(). But aren't we giving calculation(5,6) the block ankh? Hopefully my question isn't too confusing.
You have a syntax error in the line x = calculation(5,6) *ankh. To pass a method as a block, you use the &-operator.
x = calculation(5,6,&ankh)
First off: what you wrote doesn't make any sense. Think about it: what does
calculation(5, 6) * ankh
mean? Or, more abstractly, what does
foo * bar
mean? Does 2 * 3 really mean "call 2 and pass 3 as a block"?
The error says that no block is given to calculation(). But aren't we giving calculation(5,6) the block ankh?
No, ankh is not a block, it's a Proc. A block is a purely syntactic construct. Most importantly, a block is not an object, so you simply cannot store it in a variable at all. You also cannot pass it as a normal argument to a method, you have to pass it as a separate "special" block argument. Blocks do not exist independent from method calls.
There is, however, a way of "converting" a Proc into a block: the & ampersand unary prefix operator:
x = calculation(5, 6, &ankh)
# => 11
This tells Ruby to take the Proc ankh and turn it into a block. In fact, this mechanism is much more general than that, because you can even pass an object which is not a Proc and Ruby will first call to_proc on that object to allow it to convert itself to a Proc.
For example, Method implements to_proc, so you can pass Methods as blocks:
def ankh(a, b) a + b end
x = calculation(5, 6, &method(:ankh))
# => 11
Also, Symbol implements to_proc:
x = calculation(5, 6, &:+)
# => 11
Lastly, Hash implements to_proc as well.
And, of course, you can write your own objects that implement to_proc:
def (ankh = Object.new).to_proc
-> *args { "I was called with arguments #{args.inspect}!" }
end
x = calculation(5, 6, &ankh)
# => 'I was called with arguments [5, 6]!'

Why did currying in Ruby fail to work in my code?

My got an error message "method_object.rb:8:in `': wrong argument type Fixnum (expected Proc) (TypeError)" when trying to run the following script
def f(x,y=2)
x**y
end
a=method(:f).to_proc
b=a.curry.curry[4]
print 1.upto(5).map(&b)
puts
However, if function f is defined in the following way, everything was OK.
def f(x,y)
x**y
end
Would any one help me with what went wrong with my first code?
Proc#curry
Returns a curried proc. If the optional arity argument is given, it determines the number of arguments. A curried proc receives some arguments. If a sufficient number of arguments are supplied, it passes the supplied arguments to the original proc and returns the result. Otherwise, returns another curried proc that takes the rest of arguments.
Now coming to your code :
def f(x, y=2)
x**y
end
a = method(:f).to_proc
b = a.curry.curry[4]
b.class # => Fixnum
b # => 16
print 1.upto(5).map(&b)
# wrong argument type Fixnum (expected Proc) (TypeError)
Look the documentation now - A curried proc receives some arguments. If a s*ufficient number* of arguments are supplied, it passes the supplied arguments to the original proc and returns the result.
In your code, when you did a.curry, it returns a curried proc. Why? Because your method f has one optional and one required argument, but you didn't provide any. Now you call again a.curry.curry[4], so on the previous curried proc which is still waiting for at-least one argument, this time you gave to it by using curry[4]. Now curried proc object gets called with 4, 2 as arguments, and evaluated to a Fixnum object 8 and assigned to b. b is not a proc object, rather a Fixnum object.
Now, 1.upto(5).map(&b) here - &b means, you are telling convert the proc object assgined to b to a block. But NO, b is not holding proc object, rather Fixnum object 8. So Ruby complains to you.
Here the message comes as wrong argument type Fixnum (expected Proc) (TypeError).
Now coming to your second part of code. Hold on!! :-)
Look below :
def f(x, y)
x**y
end
a = method(:f).to_proc
b = a.curry.curry[4]
b.class # => Proc
b # => #<Proc:0x87fbb6c (lambda)>
print 1.upto(5).map(&b)
# >> [4, 16, 64, 256, 1024]
Now, your method f needs 2 mandatory argument x, y. a.curry, nothing you passed so a curried proc is returned. Again a.curry.curry[4], humm you passed one required argument, which is 4 out of 2. So again a curried proc returned.
Now 1.upto(5).map(&b), same as previous b expects a proc, and you fulfilled its need, as now b is proc object. &b converting it to a block as below :
1.upto(5).map { |num| b.call(num) }
which in turn outputs as - [4, 16, 64, 256, 1024].
Summary
Now suppose you defined a proc as below :
p = Proc.new { |x, y, z = 2| x + y + z }
Now you want to make p as curried proc. So you did p.curry. Remember you didn't pass any arity when called curry. Now point is a curried proc will wait to evaluate and return the result of x + y + z, unless and until, you are giving it all the required arguments it needs to produce it results.
That means p.curry gives you a curried proc object, then if you do p.curry[1] ( mean you are now passing value to x ), again you got a curried proc. Now when you will write p.curry[1][2], all required arguments you passed ( mean you are now passing value to y ), so now x + y + z will be called.
You are using .map, it requires a block of type proc. In your first case b returns 16 as y=2 uses default value 2 for exponent when you are sending single argument using curry. b returning 16 is not a proc object and can not be used with .map.
Curry when used with a proc with sufficient arguments, it executes original proc and returns a result. Which is happening in OP's first case with curried proc passed with 4 as only argument and default y=2 in f(x, y=2) getting used and resulting in 16 as return value. 16 being Fixnum can not be used with enumerator map method.
Curry when used with insufficient arguments return a proc. So in case 2 when f(x, y) is used curried a is passed only single argument resulting in a proc object {|e| 4 ** e} being returned and which gets executed by map method.

Ruby and Lambda calculus

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.

Ruby lambda arguments

This code works as expected (does nothing, even doesn't produce warning/errors):
l = lambda {|i|}
l.call(1)
This code produces warning (warning: multiple values for a block parameter (0 for 1)):
l = lambda {|i|}
l.call
And this code fails with error (ArgumentError: wrong number of arguments (0 for 2)):
l = lambda {|i, y|}
l.call
I thought that lambda requires all argument to be passed.
And from the second example I see that it isn't. Why does it work when only one argument is given, and works as expected (fails with error) with more than one argument?
PS: ruby 1.8.6 (2008-08-11 patchlevel 287) [universal-darwin9.0]
UPDATE: I've checked these samples with ruby 1.9.1p376. And it works as expected - the second example also produces an error. Looks like this is a feature of 1.8 version (or <=1.8)
Lambdas are weird like that, their behavior is different when you have less than two arguments. Check this article for more information.
This script will teach you everything you need to know about closures in Ruby.
# So, what's the final verdict on those 7 closure-like entities?
#
# "return" returns from closure
# True closure? or declaring context...? Arity check?
# --------------- ----------------------------- -------------------
# 1. block (called with yield) N declaring no
# 2. block (&b => f(&b) => yield) N declaring no
# 3. block (&b => b.call) Y except return declaring warn on too few
# 4. Proc.new Y except return declaring warn on too few
# 5. proc <<< alias for lambda in 1.8, Proc.new in 1.9 >>>
# 6. lambda Y closure yes, except arity 1
# 7. method Y closure yes
When a lambda expects arguments and we don't provide them, or we provide the wrong number of arguments, an exception is thrown.
l = lambda { |name| puts "Today we will practice #{name} meditation." }
l.call
ArgumentError: wrong number of arguments (given 0, expected 1)
We can use the arity method to find out the number of expected arguments:
l.arity # Output: => 1
Just like methods, lambdas accept all of the following types of parameters/arguments:
Positional parameters (required and optional)
Single splat parameter (*);
Keyword parameters (required and optional);
Double splat parameter (**);
Explicit block parameter prefixed with ampersand (&).
The following examples illustrate the syntax of a lambda that takes multiple types of arguments.
# Stabby syntax
l = -> (cushion, meditation="kinhin", *room_items, time:, posture: "kekkafuza", **periods, &p) do
p.call
end
# Regular syntax
l = lambda do |cushion, meditation="kinhin", *room_items, time:, posture: "kekkafuza", **periods, &p|
p.call
end
l.call("zafu", "zazen", "zabuton", "incense", time: 40, period1: "morning", period2: "afternoon" ) { puts "Hello from inside the block, which is now a proc." }
Output:
Hello from inside the block, which is now a proc.
Lambdas handle arguments the same way as methods. There is a comprehensive explanation of all the above parameter/argument types in this blog post about methods.

Resources