[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

instance_eval, regexp with block : losing $1

Vincent L.

6/3/2008 9:10:00 PM

To build a wiki-like engine (or DSL) with dynamically generated
methods, I do the following :

class Base
def self.match(name, regexp, &block)
define_method(name) do |text|
text.gsub!(regexp) do
puts "$1 in match method : #{$1}"
#block.call
instance_eval(&block)
end
end
end
end

class Foo < Base
match :g, /(.)g$/i do
puts "$1 in passed block : #{$1}" #Unfortunately $1 is lost !
'ggg' #so only hardcoded values :-(
end
end

f = Foo.new
f.g('bla') #bla
f.g('doing') #doiggg ; problem is I cannot use $1 in block

After some research I found these 2 links
http://eigenclass.org/hiki/binding.of_caller+...
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-t...
(BTW I am trying to avoid any third-party libraries)

But I don't manage to get these to work...
I need to get $1, $2, etc. special values
in the block I pass in Base subclasses.
How can I do that ?

Thanks,

Vincent
--
Posted via http://www.ruby-....

4 Answers

Roger Pack

6/4/2008 12:43:00 AM

0


> f.g('doing') #doiggg ; problem is I cannot use $1 in block
# maybe pass it as a parameter or save it away to some global variable
or 'per thread' variable.
-R
--
Posted via http://www.ruby-....

Vincent L.

6/4/2008 10:08:00 AM

0

I finally managed to get it to work :

class Base
def self.match(name, regexp, &block)
define_method(name) do |text|
puts "#{text}"
text.gsub!(regexp) do
#hack to restore magical $~ (and so $1, $2, etc.) in block
eval('lambda{|x| $~ = x}', block).call($~)
block.call #or instance_eval(&block)
end
puts "=> #{text}"
end
end
end

class Foo < Base
match :g, /(.)g$/i do
$1.upcase + '_ggg'
end
end

f = Foo.new
f.g('bla')
f.g('doing')
--
Posted via http://www.ruby-....

Vincent L.

6/4/2008 10:57:00 AM

0

Vincent L. wrote:
> I finally managed to get it to work :
>
> class Base
> def self.match(name, regexp, &block)
> define_method(name) do |text|
> puts "#{text}"
> text.gsub!(regexp) do
> #hack to restore magical $~ (and so $1, $2, etc.) in block
> eval('lambda{|x| $~ = x}', block).call($~)
> block.call #or instance_eval(&block)

instance_eval(&block) works definitely better here.

--
Posted via http://www.ruby-....

Charles Oliver Nutter

6/4/2008 2:14:00 PM

0

Vincent L. wrote:
> class Foo < Base
> match :g, /(.)g$/i do
> puts "$1 in passed block : #{$1}" #Unfortunately $1 is lost !
> 'ggg' #so only hardcoded values :-(
> end
> end
...
> But I don't manage to get these to work...
> I need to get $1, $2, etc. special values
> in the block I pass in Base subclasses.
> How can I do that ?

The backref and numbered group globals are tied to the containing
method/class body. So here, where you have a match call with a block
inside a class body, the capture would be the one that lives in that
body. That's part of the problem with relying on these special variables
and the side effect of e.g. gsub: you can't implement the same behavior
in Ruby because certain core methods like gsub have "special" side
effects impossible to emulate.

- Charlie