"The simplest" way to use a method as a proc in Ruby - ruby

Obviously, method(:method_name).to_proc works but I'm looking for a more concise way to do it - or I will not be doing it even when it's technically the right thing to do.
I'm contemplating a mix-in defining to_proc (just proc would be nicer but some genius made it a private method in Kernel)
module ProcifiedMethods
def to_proc(sym)
method(sym).to_proc
end
end
and then call
to_proc(:method_name)[*args]
but one would think something like that already exists in Ruby core?
My general motivation is to use functional programming concepts interchangeably with OOP. Got a method in some mixin that has no side-effects? Well... use it as a proc! Curry it, compose it, all the other good stuff.
That's the general idea, anyway :)
QUESTION: is there a simpler, battle tested, ideally within-ruby-core way to convert methods to procs? (i.e. a more shorthand alias of method(:method_name).to_proc).

If you're using this proc as method argument, you could use & unary operator, like foo(&method(:method_name))
If method is defined on object, this works too: foo(&obj.method(:method_name))

Firstly, proc does something different from to_proc. to_proc gives you a proc representation of a method. proc creates a proc given a block (or using the block with which the method was invoked if no block is given).
Secondly, method(:name).to_proc is fairly simple. You can define a method that simplifies it a bit, but for what it does - I would say it is very straight forward.
So for the direct question - No, there is no such way.
An argument to be made as for why it has to be slightly more explicit is that unlike with purely functional languages, here the method (and hence the proc) is tied to the instance.
class Foo
attr_accessor :bar
def calculate(baz)
baz * bar
end
end
foo = Foo.new
pro = foo.method(:calculate).to_proc
foo.bar = 7
pro.call(6) # => 42
foo.bar = 9
pro.call(6) # => 54

Stefan gave a good response, a Method behaves like / answers to the same methods as a Proc, so the answer is that the simplest way of using a Method as a Proc is simply using the Method which answers to #call, #[], #curry and all other funny stuff that a Proc has.
This makes a Method useful for standard FP shennanigans. An example:
3.method(:+).curry[3] == 6
If anyone is interested, this is the use case

Related

Ruby anonymous classes as first-class functions

Ruby does not have first class functions; although it has procs and lambdas, these notoriously require significant overhead. (Python has first class functions, apparently without the overhead.)
It occurred me to that first class functions can be simulated with a little more work by using anonymous classes, as follows:
f = Class.new { def self.f; puts 'hi'; end }
def g(fun); fun; end
g(f.f)
# => "hi"
Does anyone know a better way?
In fact, Ruby doesn't have functions at all, only methods. So if you want pass a method to another method, you can
def g(f)
f.call
end
g('123'.method(:to_i))
This is less concise than Python, but it's the price that Ruby has to pay for the ability to omit parentheses in method calls. I think omitting parentheses is one of the things that makes Ruby shine, because this makes implementing DSL in pure Ruby a lot easier.
Ruby has procs and lambdas (both instances of the Proc class), and Methods, all of which approximate first-class functions. Lambdas are the closest to a true first-class function: they check the number of arguments when called and create a new call context such that return just returns from the lambda. In contrast, procs are just reified blocks of code; they don't check their number of arguments, and a return causes the enclosing method to return, not just the proc.
Method objects allow you to store an uncalled method in a variable, complete with implied invocant. There's no syntax for creating an anonymous Method, but you said first-class functions, not anonymous ones. Other than the invocant, they are basically lambdas whose body is that of the referenced method.
I'm not sure what an anonymous class gets you that is better than the above solutions, but it is certainly further away from a true first-class function. It's more like the way we had to approximate them in Java before closures were added to the language.

Procs and Lambdas for what when we have methods

My doubt is pretty much a matter of misunderstanding...
From what I read, a block is a group of code enclosed by {} or do and end.
From my understanding, what a Proc or Lambda does is:
Get this block
Assign the block to a variable
Which means; we don't need to repeat the whole block all the time.
But, what is the difference among a Proc, Lambda and a standard Method? From my understanding, they all work the same way.
There is one crucial difference between Procs (and lambdas) and methods. Procs are objects, methods aren't. And since Ruby is an object-oriented language, where you can only do things with and to objects, that is very important.
So, if you want to pass a piece of code to a method, you need to have an object, and that's what Procs provide.
You can get a proxy object that represents a method via the Object#method method, which will return an instance of the Method class (which duck-types Proc).
Everything in ruby is considered an object. Proc and lambda are fundamentally similar constructs. This topic is highly opinionated as far as usage goes.
The key advantages is that they can be easily passed around into other blocks and the syntax is short and sweet. Consider the following very simple examples:
multiply = Proc.new {|x,y| x*y}
subtract = lambda {|x,y| x-y}
add = ->(x,y) {x+y}
def do_math (opr, *b)
opr.each do |bloc|
puts bloc.call(b[0],b[1])
end
end
do_math([multiply, subtract, add], 10, 5)
# => 50
# => 5
# => 15
puts multiply.call(5,5)
# => 25
puts subtract.call(5,5)
# => 0
puts add.call(5,5)
# => 10
To get a better grasp of what they are, watch this video: An Introduction to Procs, Lambdas and Closures in Ruby
Additionally the documentation has more examples here: http://www.ruby-doc.org/core-2.0.0/Proc.html
I found that this Codecademy section helps with the distinction.

Store and retrieve variables from objects

I want to store and retrieve some variables from object. For example in a
a = "a"
So far I found two possible ways to do it.
Using instance_variable_set and instance_variable_get
a.instance_variable_set(:#x, 10)
a.instance_variable_get(:#x) # => 10
or just using instance_eval
a.instance_eval { #y = 5 }
a.instance_eval { #y } # => 5
The second approach looks shorter and simpler for me, is there anything wrong with my code if I prefer this one?
Speed isn't everything, but... the instance_variable_set method is faster than using instance_eval. Here's a benchmark if you're interested: https://gist.github.com/1268188
Here's another post that gives another good reason for avoiding instance_eval when possible: Alex Kliuchnikau on instance_eval
If there is no good reason (e.g. metaprogramming), you'd better avoid using instance_variable_get(set), coz it will break encapsulation. You can refer to ruby-doc: thereby frustrating the efforts of the class’s author to attempt to provide proper encapsulation.
And the best practice of using instance_eval is to compose DSL style:
assume you have a Engineer class with instance method: program, play and sleep. So,
sb = Engineer.new
sb.program
sb.play
sb.sleep
# is equivalent to
sb.instance_eval do
program
play
sleep
end
In this case, it's shorter :)

Why doesn't ruby support method overloading?

Instead of supporting method overloading Ruby overwrites existing methods. Can anyone explain why the language was designed this way?
"Overloading" is a term that simply doesn't even make sense in Ruby. It is basically a synonym for "static argument-based dispatch", but Ruby doesn't have static dispatch at all. So, the reason why Ruby doesn't support static dispatch based on the arguments, is because it doesn't support static dispatch, period. It doesn't support static dispatch of any kind, whether argument-based or otherwise.
Now, if you are not actually specifically asking about overloading, but maybe about dynamic argument-based dispatch, then the answer is: because Matz didn't implement it. Because nobody else bothered to propose it. Because nobody else bothered to implement it.
In general, dynamic argument-based dispatch in a language with optional arguments and variable-length argument lists, is very hard to get right, and even harder to keep it understandable. Even in languages with static argument-based dispatch and without optional arguments (like Java, for example), it is sometimes almost impossible to tell for a mere mortal, which overload is going to be picked.
In C#, you can actually encode any 3-SAT problem into overload resolution, which means that overload resolution in C# is NP-hard.
Now try that with dynamic dispatch, where you have the additional time dimension to keep in your head.
There are languages which dynamically dispatch based on all arguments of a procedure, as opposed to object-oriented languages, which only dispatch on the "hidden" zeroth self argument. Common Lisp, for example, dispatches on the dynamic types and even the dynamic values of all arguments. Clojure dispatches on an arbitrary function of all arguments (which BTW is extremely cool and extremely powerful).
But I don't know of any OO language with dynamic argument-based dispatch. Martin Odersky said that he might consider adding argument-based dispatch to Scala, but only if he can remove overloading at the same time and be backwards-compatible both with existing Scala code that uses overloading and compatible with Java (he especially mentioned Swing and AWT which play some extremely complex tricks exercising pretty much every nasty dark corner case of Java's rather complex overloading rules). I've had some ideas myself about adding argument-based dispatch to Ruby, but I never could figure out how to do it in a backwards-compatible manner.
Method overloading can be achieved by declaring two methods with the same name and different signatures. These different signatures can be either,
Arguments with different data types, eg: method(int a, int b) vs method(String a, String b)
Variable number of arguments, eg: method(a) vs method(a, b)
We cannot achieve method overloading using the first way because there is no data type declaration in ruby(dynamic typed language). So the only way to define the above method is def(a,b)
With the second option, it might look like we can achieve method overloading, but we can't. Let say I have two methods with different number of arguments,
def method(a); end;
def method(a, b = true); end; # second argument has a default value
method(10)
# Now the method call can match the first one as well as the second one,
# so here is the problem.
So ruby needs to maintain one method in the method look up chain with a unique name.
I presume you are looking for the ability to do this:
def my_method(arg1)
..
end
def my_method(arg1, arg2)
..
end
Ruby supports this in a different way:
def my_method(*args)
if args.length == 1
#method 1
else
#method 2
end
end
A common pattern is also to pass in options as a hash:
def my_method(options)
if options[:arg1] and options[:arg2]
#method 2
elsif options[:arg1]
#method 1
end
end
my_method arg1: 'hello', arg2: 'world'
Method overloading makes sense in a language with static typing, where you can distinguish between different types of arguments
f(1)
f('foo')
f(true)
as well as between different number of arguments
f(1)
f(1, 'foo')
f(1, 'foo', true)
The first distinction does not exist in ruby. Ruby uses dynamic typing or "duck typing". The second distinction can be handled by default arguments or by working with arguments:
def f(n, s = 'foo', flux_compensator = true)
...
end
def f(*args)
case args.size
when
...
when 2
...
when 3
...
end
end
This doesn't answer the question of why ruby doesn't have method overloading, but third-party libraries can provide it.
The contracts.ruby library allows overloading. Example adapted from the tutorial:
class Factorial
include Contracts
Contract 1 => 1
def fact(x)
x
end
Contract Num => Num
def fact(x)
x * fact(x - 1)
end
end
# try it out
Factorial.new.fact(5) # => 120
Note that this is actually more powerful than Java's overloading, because you can specify values to match (e.g. 1), not merely types.
You will see decreased performance using this though; you will have to run benchmarks to decide how much you can tolerate.
I often do the following structure :
def method(param)
case param
when String
method_for_String(param)
when Type1
method_for_Type1(param)
...
else
#default implementation
end
end
This allow the user of the object to use the clean and clear method_name : method
But if he want to optimise execution, he can directly call the correct method.
Also, it makes your test clearers and betters.
there are already great answers on why side of the question. however, if anyone looking for other solutions checkout functional-ruby gem which is inspired by Elixir pattern matching features.
class Foo
include Functional::PatternMatching
## Constructor Over loading
defn(:initialize) { #name = 'baz' }
defn(:initialize, _) {|name| #name = name.to_s }
## Method Overloading
defn(:greet, :male) {
puts "Hello, sir!"
}
defn(:greet, :female) {
puts "Hello, ma'am!"
}
end
foo = Foo.new or Foo.new('Bar')
foo.greet(:male) => "Hello, sir!"
foo.greet(:female) => "Hello, ma'am!"
I came across this nice interview with Yukihiro Matsumoto (aka. "Matz"), the creator of Ruby. Incidentally, he explains his reasoning and intention there. It is a good complement to #nkm's excellent exemplification of the problem. I have highlighted the parts that answer your question on why Ruby was designed that way:
Orthogonal versus Harmonious
Bill Venners: Dave Thomas also claimed that if I ask you to add a
feature that is orthogonal, you won't do it. What you want is
something that's harmonious. What does that mean?
Yukihiro Matsumoto: I believe consistency and orthogonality are tools
of design, not the primary goal in design.
Bill Venners: What does orthogonality mean in this context?
Yukihiro Matsumoto: An example of orthogonality is allowing any
combination of small features or syntax. For example, C++ supports
both default parameter values for functions and overloading of
function names based on parameters. Both are good features to have in
a language, but because they are orthogonal, you can apply both at the
same time. The compiler knows how to apply both at the same time. If
it's ambiguous, the compiler will flag an error. But if I look at the
code, I need to apply the rule with my brain too. I need to guess how
the compiler works. If I'm right, and I'm smart enough, it's no
problem. But if I'm not smart enough, and I'm really not, it causes
confusion. The result will be unexpected for an ordinary person. This
is an example of how orthogonality is bad.
Source: "The Philosophy of Ruby", A Conversation with Yukihiro Matsumoto, Part I
by Bill Venners, September 29, 2003 at: https://www.artima.com/intv/ruby.html
Statically typed languages support method overloading, which involves their binding at compile time. Ruby, on the other hand, is a dynamically typed language and cannot support static binding at all. In languages with optional arguments and variable-length argument lists, it is also difficult to determine which method will be invoked during dynamic argument-based dispatch. Additionally, Ruby is implemented in C, which itself does not support method overloading.

DSL block without argument in ruby

I'm writing a simple dsl in ruby. Few weeks ago I stumbled upon some blog post, which show how to transform code like:
some_method argument do |book|
book.some_method_on_book
book.some_other_method_on_book :with => argument
end
into cleaner code:
some_method argument do
some_method_on_book
some_other_method_on_book :with => argument
end
I can't remember how to do this and I'm not sure about downsides but cleaner syntax is tempting. Does anyone have a clue about this transformation?
def some_method argument, &blk
#...
book.instance_eval &blk
#...
end
UPDATE: However, that omits book but don't let you use the argument. To use it transparently you must transport it someway. I suggest to do it on book itself:
class Book
attr_accessor :argument
end
def some_method argument, &blk
#...
book.argument = argument
book.instance_eval &blk
#...
end
some_method 'argument' do
some_method_on_book
some_other_method_on_book argument
end
Take a look at this article http://www.dan-manges.com/blog/ruby-dsls-instance-eval-with-delegation — there is an overview of the method (specifically stated in the context of its downsides and possible solution to them), plus there're several useful links for further reading.
Basically, it's about using instance_eval to execute the block in the desirable context.
Speaking about downside of this technique:
So what's the problem with it? Well, the problem is that blocks are
generally closures. And you expect them to actually be full closures.
And it's not obvious from the point where you write the block that
that block might not be a full closure. That's what happens when you
use instance_eval: you reset the self of that block into something
else - this means that the block is still a closure over all local
variables outside the block, but NOT for method calls. I don't even
know if constant lookup is changed or not.
Using instance_eval changes the rules for the language in a way that
is not obvious when reading a block. You need to think an extra step
to figure out exactly why a method call that you can lexically see
around the block can actually not be called from inside of the block.
Check out the docile gem. It takes care of all the sharp edges, making this very easy for you.

Resources