While looking through ActiveSupport source code I've noticed that sometimes eval is used in places where define_method is enough.
Example: ActiveSupport: Module.delegate
I consider define_method more clean and safe way of doing things.
What is the benefits of eval over define_method?
Perfomance, memory usage, something else?
When you use define_method, the method you're defining can't accept a block.
It’s pretty well known that because of
a deficiency in blocks arguments in
Ruby 1.8 Class#define_method cannot
define methods that take blocks.
def x *args, █ end # => works!
define_method(:x) {|*args,&block| } # => SyntaxError: compile error
The method being defined requires a block:
"def #{prefix}#{method}(*args, &block)" # def customer_name(*args, &block)
So define_method can't be used.
I found this to be a very nice article on the subject: http://blog.grayproductions.net/articles/eval_isnt_quite_pure_evil.
I don't know what the reason in that particular case, but define_method takes a block, which is a closure (carries local variables of the place it was defined), and that can lead to considerably higher memory consumption comparing to plain eval.
Related
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
Looking for a little wisdom from fellow Rubyists. For a while now, I've used the following for convenience in some of my applications, and I'm wondering if there's a language feature I'm just missing:
class Object
def as_block
yield
end
end
There are other uses, but the normal case for me is a conditional assignment that requires a little non-trivial logic. Two obvious ways to do this:
# via a second method:
def foo
#foo ||= set_foo
end
# via conditional logic:
def foo
if #foo
#foo
else
# do complicated stuff
end
end
Both of these approaches seem kind of ugly: in the first case, #set_foo seems extraneous, and the second just looks kind of nasty. So, instead, I like this:
def foo
#foo ||= as_block do
# do complicated stuff
end
end
The problem here (aside from monkey patching Object) is that it's really a dependency (on the monkey patch) that looks like a language feature. That is, something like this really shouldn't be in (say) a Rails initializer---it seems like it should be in a gem, so the dependency can be managed correctly. Then I'm packaging an entire gem to run five lines of code to monkey patch Object...
So, my questions:
1. Anyone else use this, or something like it?
2. Has the Ruby team ever considered including something like this by default? It seems like a really easy way to use blocks as plain old expressions, but it's not there (as far as I know) which makes me wonder if there's some reason for not including it, or...
3. Is there already some better way of doing this that I'm just unaware of?
Thanks!
-E
What you're looking for is begin ... end. This isn't the same thing as a block or Proc, as it's not an object you can pass around or a closure which creates a new scope, but it should serve your purpose just fine:
def foo
#foo ||= begin
# do complicated stuff
end
end
You could use a lambda:
def foo
#foo ||= lambda do
# do complicated stuff
end.call
end
Note that it is important to call the lambda to actually execute the expression, ie
def foo
#foo ||= lambda do
# do complicated stuff
end
end
will return a lambda rather than your evaluated expression.
Given the following module:
module Foo
def self.call
'foo'
end
end
I would of course expect the following to work:
puts Foo.call # outputs "foo"
However, I did not expect this to work:
puts Foo.() # outputs "foo"
Apparently when the method name is left off, Ruby assumes that I want to call the call method. Where is this documented, and why does it behave that way?
Proc#call:
Invokes the block, setting the block’s parameters to the values in params using something close to method calling semantics. Generates a warning if multiple values are passed to a proc that expects just one (previously this silently converted the parameters to an array). Note that prc.() invokes prc.call() with the parameters given. It’s a syntax sugar to hide “call”.
I did some research and found method #() is a syntactic sugar of the method #call..Look at the error as below :
module Foo
def self.bar
12
end
end
Foo.()
#undefined method `call' for Foo:Module (NoMethodError)
As OP defined the #call method in module Foo class,Foo#call is called in an attempt of Foo.().
Here is some more examples :
"ab".method(:size).() # => 2
"ab".method(:size).call # => 2
"ab".() # undefined method `call' for "ab":String (NoMethodError)
See here what Matz said So compromise with object.() syntax introduced in 1.9...
Apparently, as Arup is saying, this is syntactic sugar introduced a while ago, possibly for the single cause of making Proc objects easier to work with. (You don't have to explicitly call them, but can just do prc.() instead).
I also concluded that this is definitely a Ruby 1.9+ feature. If I switch my JRuby to 1.8 mode, I get this instead:
SyntaxError: spam.rb:12: syntax error, unexpected tLPAREN2
So, somewhere in the changelogs for Ruby 1.9 it can probably be found, if someone really wants to dig it out from the caves... :)
In Ruby, procs seem to have access to local variables that were present at the time they were declared, even if they are executed in a different scope:
module Scope1
def self.scope1_method
puts "In scope1_method"
end
end
module Scope2
def self.get_proc
x = 42
Proc.new do
puts x
puts self
scope1_method
end
end
end
Scope1.instance_eval(&Scope2.get_proc)
Output:
42
Scope1
In scope1_method
How and why does this occur?
The Proc.new call creates a closure for the block that it's given. In creating a closure for the block, the block is bound to the original variables in the scope of the Proc.new call.
Why is this done?
It allows Ruby blocks to function as closures. Closures are extremely useful, and the Wikipedia entry (linked above) does an excellent job of explaining some of their applications.
How is this done?
This is done in the Ruby VM (in C code) by copying the Ruby control frame that exists before entering the Proc.new method. The block is then run in the context of this control frame. This effectively copies all of the bindings that are present in this frame. In Ruby 1.8, you can find the code for this in the proc_alloc function in eval.c. In Ruby 1.9, you can find this in the proc_new function in proc.c.
This behavior is by design. In Ruby, blocks, procs, and lambdas are lexical closures. Read this blog post for a short explanation of the differences between Ruby's three flavors of closure.
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.