Understanding { } and block_given


#1

Hello,

I have the following:

class DSL
def DSL.load filename
dsl = new
dsl.instance_eval(File.read(filename))
dsl
end
def to sym,*args,&block
if block_given?
b=class << self;self;end
b.instance_eval {
define_method(sym,*args,&block)
}
end
end
def method_missing sym,*args
“#{sym}”
end
alias :say puts
end

foo=DSL.load(“sample.dsl”)

sample.dsl:

to smile do
say “:)”
end
to be_polite {
say “thank you”
}
smile
be_polite

The resulting output is:

moonwolf@trantor:~/ruby/dsl/todo$ ./dsl.rb
:slight_smile:
moonwolf@trantor:~/ruby/dsl/todo$

be_polite and indeed, anything enclosded in {} doesn’t seem to be
eval-ed as
blocks. Why is this?

Jayanth


#2

This is definitely not a block_given thing.

block is coming through as a NilClass it seems.

puts block.class yields NilClass. The strange bit is that when I do it
outside of instance_eval with just a define_method under irb, it works
as
expected. I am lost.

Anyone?

Jayanth


#3

Le 08 mai à 11:42, Srijayanth S. a écrit :

[Note: parts of this message were removed to make it a legal post.]

This is definitely not a block_given thing.

It’s an operator precedence thing. {} binds at a higher precedence than
do/end, meaning that, in the absence of parentheses, in one case, it’s
the first function that takes the block and in the other, it’s the
second one.

For instance :

def test ; (block_given? ? ‘block’ : ‘no block’) ; end
=> nil

puts test do end
no block
=> nil

puts test { }
block

In the first case, it’s puts who gets the block (and discards it). In
the second case, it’s my function. Compare to :

puts(test) do end
no block
=> nil

puts(test) {}
no block
=> nil

puts(test do end)
block
=> nil

puts(test {})
block

Fred