Convert yield to proc

How do you guys convert yield to block ?

I were hoping to that #mode2 could get same behavier as #mode,
however self is out of control.

ruby a.rb
#<ModeInfo:0x8123634 @tabsize=4>
a.rb:18: undefined method tabsize' for main:Object (NoMethodError) from a.rb:17:in mode2’
from a.rb:11:in instance_eval' from a.rb:7:in instance_eval’
from a.rb:7:in mode' from a.rb:12:in mode2’
from a.rb:17
expand -t2 a.rb
class ModeInfo
def initialize; @tabsize = 8 end
def tabsize(value); @tabsize = value end
end
def mode(&block)
m = ModeInfo.new
m.instance_eval(&block)
p m
end
def mode2
block = lambda{yield} # attempt to convert yield 2 block
mode(&block)
end
mode do
tabsize 4
end
mode2 do
tabsize 5 # BOOM
end

···


Simon Strandgaard

How do you guys convert yield to block ?

I were hoping to that #mode2 could get same behavier as #mode,
however self is out of control.

Figured it out … Proc.new … ??? feels awkward

ruby a.rb
#<ModeInfo:0x8123634 @tabsize=4>
#<ModeInfo:0x8123440 @tabsize=5>
expand -t2 a.rb
class ModeInfo
def initialize; @tabsize = 8 end
def tabsize(value); @tabsize = value end
end
def mode(&block)
m = ModeInfo.new
m.instance_eval(&block)
p m
end
def mode2
mode(&Proc.new)
end
mode do
tabsize 4
end
mode2 do
tabsize 5
end

···

On Sun, 18 Apr 2004 04:21:50 +0200, Simon Strandgaard wrote:


Simon Strandgaard

“Simon Strandgaard” neoneye@adslhome.dk schrieb im Newsbeitrag
news:pan.2004.04.18.01.36.57.303713@adslhome.dk…

···

On Sun, 18 Apr 2004 04:21:50 +0200, Simon Strandgaard wrote:

How do you guys convert yield to block ?

I were hoping to that #mode2 could get same behavier as #mode,
however self is out of control.

Figured it out … Proc.new … ??? feels awkward

ruby a.rb
#<ModeInfo:0x8123634 @tabsize=4>
#<ModeInfo:0x8123440 @tabsize=5>
expand -t2 a.rb
class ModeInfo
def initialize; @tabsize = 8 end
def tabsize(value); @tabsize = value end
end
def mode(&block)
m = ModeInfo.new
m.instance_eval(&block)
p m
end
def mode2
mode(&Proc.new)
end
mode do
tabsize 4
end
mode2 do
tabsize 5
end

But what do you need that for? This isn’t a real world example, is it?

Just curious…

robert

I must admit, I don’t understand what you’re doing exactly either…

How is your code different from:

def mode2(&blk)
mode(&blk)
end

Or for that matter, how is:

mode2 do
# stuff
end

different from:

mode do
#stuff
end

  • Dan

[snip]

But what do you need that for? This isn’t a real world example, is it?

Just curious…

Its a tiny example of a configuration system for AEditor,
where you can have different modes, for instance:
define a ruby mode, where certain key gets bound with
RI, rdoc. Where syntax hiliting gets configured.
Much inspired by Rake.

An example dotfile for AEditor:

expand -t2 dotfile.rb

AEditor preferences for Simon Strandgaard

mode :global do
tabsize 4
#panel_format {|i| “#{i.y},#{i.xcell}-#{i.xchar}”}
end

mode :ruby => :global do
tabsize 2
#on_execute_project {|i| “ruby -v main.rb”}
#on_execute_buffer {|i| “ruby -v #{i.filename}”} # record errors, so we can jump to them
#on_execute_tests “ruby test_all.rb”
#on_execute_builddoc {|i| “rdoc #{i.filename}”}
#on_help_context { |place| “ri place” }
#on_debug_step “gdb”
#mode_selftest do
# check that ruby is working
# check rdoc is present
# check ri is prsent
#end
end
file_suffix %w(rb rbx) => :ruby

mode :rake => :ruby do

TODO: extract tasks, rules, files.. show choices

#on_execute_buffer {|i| dialog(‘all’, ‘run’, ‘upload’, ‘validate’)}
end
file_match %w(rakefile rakefile.rb) => :ruby

mode :c => :global do
end
file_suffix ‘c’ => :c

mode :cpp => :c do
end
file_suffix %w(cpp cc) => :cpp

mode :xml => :global do
#on_execute_buffer {|i| “xsltproc --validate #{i.filename}”}
end
file_suffix %w(xml xhtml) => :xml

theme :morning do
end

theme :night do
end

The code for parsing it located here
http://rubyforge.org/cgi-bin/viewcvs/cgi/viewcvs.cgi/projects/experimental/preferences/?cvsroot=aeditor

Its a proof of concept.. Any suggestions?
How would you like preferences to be ?

···

On Mon, 19 Apr 2004 12:00:04 +0200, Robert Klemme wrote:


Simon Strandgaard

I must admit, I don’t understand what you’re doing exactly either…

How is your code different from:

def mode2(&blk)
mode(&blk)
end

My code can take an optional block. Your above code
must be supplied a block.

Or for that matter, how is:

mode2 do
# stuff
end

different from:

mode do
#stuff
end

No difference there.

However being able to not supply a block is what interest me

mode2 # OK

mode # BOOM

HTH,

···

On Mon, 19 Apr 2004 20:23:20 +0900, Dan Doel wrote:


Simon Strandgaard

What do you call an optional block ?

svg% cat b.rb
#!/usr/bin/ruby
class ModeInfo
   def initialize; @tabsize = 8 end
   def tabsize(value); @tabsize = value end
end

def mode(&block)
   m = ModeInfo.new
   m.instance_eval(&block)
   p m
end

def mode2
   mode(&Proc.new)
end

mode2
svg%

svg% b.rb
./b.rb:14:in `new': tried to create Proc object without a block (ArgumentError)
        from ./b.rb:14:in `mode2'
        from ./b.rb:17
svg%

Guy Decoux

···

On Mon, 19 Apr 2004 20:23:20 +0900, Dan Doel wrote:

I must admit, I don't understand what you're doing exactly either...

How is your code different from:

def mode2(&blk)
mode(&blk)
end

My code can take an optional block. Your above code
must be supplied a block.

My code can take an optional block. Your above code
must be supplied a block.

What do you call an optional block ?

I was hoping that I had made a method which could take
an optional block… ala

def m
if block_given?
yield
end
end

I wanted to convert that yield into a block, which I could
pass further around (as a block).

[snip]

mode2
svg%

svg% b.rb
/b.rb:14:in new': tried to create Proc object without a block (ArgumentError) from ./b.rb:14:in mode2’
from ./b.rb:17
svg%

Bommer… your right. I thought I was on to something.

Any idea how to do this?

···

On Mon, 19 Apr 2004 20:42:58 +0900, ts wrote:


Simon Strandgaard

Any idea how to do this?

Do what ? Call a method with a block which do nothing ???

Guy Decoux

Bommer… your right. I thought I was on to something.

Any idea how to do this?

Just realized that my knowledge about &block is flawed!

ruby a.rb
before
after
before
middle
after
expand -t2 a.rb
def m(&block)
puts “before”
if block_given?
block.call
end
puts “after”
end

m

m do
puts “middle”
end

Thanks for correcting me… I have thought until now,
that the &block was indicating the a block must be
supplied. However I just realized that this is not
the case, which is a pleasant surprise.

Thanks every one.

BTW: Now the conversion problem is wiped away :wink:

···

On Mon, 19 Apr 2004 13:51:00 +0200, Simon Strandgaard wrote:

On Mon, 19 Apr 2004 20:42:58 +0900, ts wrote:


Simon Strandgaard

My code can take an optional block. Your above code
must be supplied a block.

What do you call an optional block ?

I was hoping that I had made a method which could take
an optional block… ala

def m
if block_given?
yield
end
end

I wanted to convert that yield into a block, which I could
pass further around (as a block).

Any idea how to do this?


Simon Strandgaard

Ok, so an &-parameter accepts an optional block, but aside from that,
doesn’t this convert the block to a proc? I’m not quite sure because of the
other thread going on shows that scoping rules about proces and lambdas are
convoluted, and I don’t quite understand how they work.

proc do yield end

It seems that it works, look:

def mypr; if block_given?; then proc do yield; end; else proc do puts
“default”; end; end; end; p= mypr do puts “hi”; end; 5.times(&p); q= mypr;
5.times(&q);

ambrus

···

On Mon, Apr 19, 2004 at 07:59:07PM +0900, Simon Strandgaard wrote:

On Mon, 19 Apr 2004 20:42:58 +0900, ts wrote:

Solved. My cognitive skills must be broken somehow, I has
never occured to me that &block was optional.

However, yes that what I asked for

mode2 do
# block supplied
end

mode2 # no block supplied

···

On Mon, 19 Apr 2004 21:01:18 +0900, ts wrote:

Any idea how to do this?

Do what ? Call a method with a block which do nothing ???

Guy Decoux


Simon Strandgaard

“Simon Strandgaard” neoneye@adslhome.dk schrieb im Newsbeitrag
news:pan.2004.04.19.11.00.15.63416@adslhome.dk…

Bommer.. your right. I thought I was on to something.

Any idea how to do this?

Just realized that my knowledge about &block is flawed!

ruby a.rb
before
after
before
middle
after
expand -t2 a.rb
def m(&block)
puts “before”
if block_given?
block.call
end
puts “after”
end

m

m do
puts “middle”
end

Even simpler:

def foo(&bl)
bl.call(whatever) if bl
end

def bar(&bl)
foo(&bl)
end

or

def foo
yield whatever
end

def bar(&bl)
if bl
foo &bl
else
foo() {}
end
end

Regards

robert
···

On Mon, 19 Apr 2004 13:51:00 +0200, Simon Strandgaard wrote:

On Mon, 19 Apr 2004 20:42:58 +0900, ts wrote:

def mypr; if block_given?; then proc do yield; end; else proc do puts
"default"; end; end; end; p= mypr do puts "hi"; end; 5.times(&p); q= mypr;
5.times(&q);

Well, try this

def mypr; if block_given?; then proc do yield; end; else proc do
puts "default"; break; end; end; end; p= mypr do puts "hi"; break; end;
5.times(&p); q= mypr; 5.times(&q);

This is not me which have tried to obfuscate the code :-)))

Guy Decoux

The original problem with the code was that he was instance_evaling the
block in #mode. So if no block was passed, he’d end up with something like
the following:

instance_eval do
yield
end

And you can’t yield in a block given to instance eval (not sure I totally
understand why, but I have a gut feeling that you shouldn’t try it :)).

Using an & parameter wraps the given block in a Proc. If no block is given,
it’s nil. If you call yield in a block, it will yield to the block given to
the enclosing method.

Hope this helps.

  • Dan

def mypr; if block_given?; then proc do yield; end; else proc do puts
“default”; end; end; end; p= mypr do puts “hi”; end; 5.times(&p); q= mypr;
5.times(&q);

Well, try this

def mypr; if block_given?; then proc do yield; end; else proc do
puts “default”; break; end; end; end; p= mypr do puts “hi”; break; end;
5.times(&p); q= mypr; 5.times(&q);

This is not me which have tried to obfuscate the code :-)))

Guy Decoux

  1. Sorry for the one-liner.

  2. Only the first break causes a problem:

def mypr; if block_given?; then proc do yield; end; else proc
do puts “default”; end; end; end; p= mypr do puts “hi”; break; end;
5.times(&p); q= mypr; 5.times(&q);

works as expected, that is, the “hi” block breaks out.

  1. The problem with the first break is that it is not in the lexical scope
    of the times loop.

This just shows that ruby has a nice lexical semantics for break, unlike
perl in which the loop control statements act on the innermost dynamically
enclosing block, and if it has a label, it will search for it in the
dynamical scope.

I consider this an advantage. Look. In a perl code like

sub twice (&) {
$0;
$
0;
}

… later …

BACK:
print “before twice:\n”;
twice { print “hello\n”; rand()<0.5 and goto BACK; };

Although you can jump to the label BACK, you must first make sure that the
sub `twice’ (which may be written by someone else) does not have a label
called BACK. Although ruby does not have labeled loop control statements and
gotos, it is still better if the loop control statements work in a lexical
fashion (that is, they will jump only with respect to the visible loop that
is near the jump-control statement in the code), especially because of the
greater role of iterators (as compared to perl).

This is of course only my opinion, you may still think that dynamic control
sturctures are better. And btw, ruby has both: exceptions are dynamic,
callcc and loop control are lexical in this sense.

  1. This has nothing to do with making a proc from the yield-block.

def mypr (&f); if block_given?; then f; else proc do puts “default”; end;
end; end; p= mypr do puts “hi”; break; end; 5.times(&p); q= mypr;
5.times(&q);

works the same and

def mypr (&f); if block_given?; then f; else proc do puts “default”; break;
end; end; end; p= mypr do puts “hi”; break; end; 5.times(&p); q= mypr;
5.times(&q);

fails the same as above.

ambrus

···

On Tue, Apr 20, 2004 at 12:01:44AM +0900, ts wrote:

irb(main):002:0> def foo; “aa”.instance_eval{ yield } end
=> nil
irb(main):003:0> foo{puts “adsda”}
adsda

···

On Tue, Apr 20, 2004 at 05:32:22AM +0900, Dan Doel wrote:

The original problem with the code was that he was instance_evaling the
block in #mode. So if no block was passed, he’d end up with something like
the following:

instance_eval do
yield
end

And you can’t yield in a block given to instance eval (not sure I totally
understand why, but I have a gut feeling that you shouldn’t try it :)).


Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

  • JHM wonders what Joey did to earn “I’d just like to say, for the record,
    that Joey rules.”
    – Seen on #Debian

My bad.

Looked at the original post, and here’s the problem:

class Bar
def foo
#stuff
end
end

def baz1(&blk)
Bar.new.instance_eval &blk
end

def baz2
baz1 &lambda { yield }
end

baz2 { foo }

When you yield to the block for baz2, it tries to call the method foo of a
Bar object, but it’s not actually being instance_evaled, only the { yield }
block is being instance evaled, so you get an undefined method error.

Thanks for correcting me.

  • Dan

1. Only the first break causes a problem:

This is 1.9

svg% cat b.rb
#!./ruby
def x(&b)
   p "before"
   b.call
   p "after"
end

a = Proc.new { p "a"; break }
b = proc { p "b"; break }

x(&a)
x(&b)
svg%

svg% ruby -v b.rb
ruby 1.9.0 (2004-04-16) [i686-linux]
"before"
"a"
"before"
"b"
"after"
svg%

Guy Decoux

In ruby 1.8.1, only the first one (x(&b)) works, the first variant (with
Proc.new) fails with `break from proc-closure (LocalJumpError)'. I don’t
have an 1.9 ruby installed.

I don’t quite understand all this distinction between Proc and proc and the
like. I am now confused. Sorry.

From what loop or iterator does exactly the `break’ break out in the
x(&b) call, in ruby 1.9?

ambrus

···

On Tue, Apr 20, 2004 at 06:49:43PM +0900, ts wrote:

  1. Only the first break causes a problem:

This is 1.9

svg% cat b.rb
#!./ruby
def x(&b)
p “before”
b.call
p “after”
end

a = Proc.new { p “a”; break }
b = proc { p “b”; break }

x(&a)
x(&b)
svg%

svg% ruby -v b.rb
ruby 1.9.0 (2004-04-16) [i686-linux]
“before”
“a”
“before”
“b”
“after”
svg%

Guy Decoux