[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

super with block

Lou Zell

7/31/2008 9:07:00 AM

Hi all,

I'm looking for a bit of help. I can't seem to get the block to "pass
through" to the parent class. I figured without an '&' in the parameter
list there would be no conversion to proc but maybe that is not the
case.

class Nstring < String
def gsub!(*args)
super
end
end

This works as I expected:

s = Nstring.new("hi")
s.gsub!(/(hi)/,'\1')
=> "hi"

But this, not so much:

s.gsub!(/(hi)/) {$1}
=> ""

Thanks,
Lou
--
Posted via http://www.ruby-....

16 Answers

Jesús Gabriel y Galán

7/31/2008 9:56:00 AM

0

On Thu, Jul 31, 2008 at 11:06 AM, Lou Zell <lzell11@gmail.com> wrote:
> Hi all,
>
> I'm looking for a bit of help. I can't seem to get the block to "pass
> through" to the parent class. I figured without an '&' in the parameter
> list there would be no conversion to proc but maybe that is not the
> case.
>
> class Nstring < String
> def gsub!(*args)
> super
> end
> end
>
> This works as I expected:
>
> s = Nstring.new("hi")
> s.gsub!(/(hi)/,'\1')
> => "hi"
>
> But this, not so much:
>
> s.gsub!(/(hi)/) {$1}
> => ""
>

Hi,

This worked for me:

irb(main):023:0> class NString < String
irb(main):024:1> def gsub!(*args, &blk)
irb(main):025:2> super(*args, &blk)
irb(main):026:2> end
irb(main):027:1> end
=> nil
irb(main):028:0> s = NString.new("hi")
=> "hi"
irb(main):029:0> s.gsub!(/(hi)/){$1}
=> "hi"

Hope this helps,

Jesus.

Lou Zell

7/31/2008 5:11:00 PM

0

> Hi,
>
> This worked for me:
>
> irb(main):023:0> class NString < String
> irb(main):024:1> def gsub!(*args, &blk)
> irb(main):025:2> super(*args, &blk)
> irb(main):026:2> end
> irb(main):027:1> end
> => nil
> irb(main):028:0> s = NString.new("hi")
> => "hi"
> irb(main):029:0> s.gsub!(/(hi)/){$1}
> => "hi"
>
> Hope this helps,
>
> Jesus.


Hi Jesus, thank you for your response. Unfortunately, I could not
replicate your results:


>> class NString < String
>> def gsub!(*args, &blk)
>> super(*args, &blk)
>> end
>> end
=> nil
>> s = NString.new("hi")
=> "hi"
>> s.gsub!(/(hi)/){$1}
=> ""


Perhaps it is my version of ruby?
~$ ruby -v
ruby 1.8.6 (2008-03-03 patchlevel 114) [universal-darwin9.0]


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

Mikael Høilund

7/31/2008 5:28:00 PM

0


On Jul 31, 2008, at 19:10, Lou Zell wrote:
>
>>> class NString < String
>>> def gsub!(*args, &blk)
>>> super(*args, &blk)
>>> end
>>> end
> =3D> nil
>>> s =3D NString.new("hi")
> =3D> "hi"
>>> s.gsub!(/(hi)/){$1}
> =3D> ""


Looks like this is a problem with using $1 inside the block. Replacing =20=

{$1} with {|m| m} makes it work.

However, a different issue I now remember running into a long time ago =20=

is that `super` is pretty quirky regarding blocks:

Calling it as just `super` will pass the block.
`super(*args, &block)` will as well, obviously.
`super(*args)` will too!

The only way to avoid passing the block to super is `super(*args, =20
&nil)`, however ugly that might be.

All of this is tested in 1.8.6, and is probably the same in 1.9.


--=20
Mikael H=F8ilund
http://ho...


Robert Dober

7/31/2008 5:38:00 PM

0

On Thu, Jul 31, 2008 at 7:10 PM, Lou Zell <lzell11@gmail.com> wrote:
>> Hi,
>>
>> This worked for me:
>>
>> irb(main):023:0> class NString < String
>> irb(main):024:1> def gsub!(*args, &blk)
>> irb(main):025:2> super(*args, &blk)
>> irb(main):026:2> end
>> irb(main):027:1> end
>> => nil
>> irb(main):028:0> s = NString.new("hi")
>> => "hi"
>> irb(main):029:0> s.gsub!(/(hi)/){$1}
>> => "hi"
>>
>> Hope this helps,
>>
>> Jesus.
>
>
> Hi Jesus, thank you for your response. Unfortunately, I could not
> replicate your results:
>
>
>>> class NString < String
>>> def gsub!(*args, &blk)
>>> super(*args, &blk)
>>> end
>>> end
> => nil
your problem has nothing to do with passing the block along in gsub!
>>> s = NString.new("hi")
guess what s is here?
If you guessed "", you guessed correctly
> => "hi"
>>> s.gsub!(/(hi)/){$1}
> => ""
normal given that s was ""

Probably subclassing is not what you want, but it can be accomplished of course

>
>
> Perhaps it is my version of ruby?
> ~$ ruby -v
> ruby 1.8.6 (2008-03-03 patchlevel 114) [universal-darwin9.0]
>
>
> Lou
> --
> Posted via http://www.ruby-....
>
>

Here is the final solution
class NString < String
def initialize str
replace str
end
def gsub! *args
super( *args, &Proc::new ) # that is just to show you yet another
way to do this but passing &blk is better
end
end

n = Nstring::new( "123")
p n
p n.gsub!(/.../){ |m| m.reverse } # $1 is not set as somebody did
point out already

HTH
Robert


--
http://ruby-smalltalk.blo...

There's no one thing that's true. It's all true.
--
Ernest Hemingway

Lou Zell

7/31/2008 5:39:00 PM

0

Mikael, I can deal with that, I'll swap out the $'s with block params.
Thanks for the workaround!

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

Robert Dober

7/31/2008 5:40:00 PM

0

ERRATUM

use
replace str[0..-1] or
replace str.dup

instead of
replace str

bad mistake of my part sorry.

Robert

Lou Zell

7/31/2008 5:48:00 PM

0

> your problem has nothing to do with passing the block along in gsub!
>>>> s = NString.new("hi")
> guess what s is here?
> If you guessed "", you guessed correctly

Wait, why would s be empty? I can use Nstring.new just like String.new

>> class Nstring < String
>> end
=> nil
>> n = Nstring.new("hi")
=> "hi"
>> puts n
hi


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

Robert Dober

7/31/2008 5:53:00 PM

0

>> If you guessed "", you guessed correctly
>
> Wait, why would s be empty? I can use Nstring.new just like String.new
>
>>> class Nstring < String
>>> end
> => nil
>>> n = Nstring.new("hi")
> => "hi"
>>> puts n
you are right I am wrong, no idea what I did OMG.
Seems your only problem was the $1 in the block
Sorry for the noise
R.

Gregory Brown

7/31/2008 5:53:00 PM

0

On Thu, Jul 31, 2008 at 1:47 PM, Lou Zell <lzell11@gmail.com> wrote:
>> your problem has nothing to do with passing the block along in gsub!
>>>>> s = NString.new("hi")
>> guess what s is here?
>> If you guessed "", you guessed correctly
>
> Wait, why would s be empty? I can use Nstring.new just like String.new
>
>>> class Nstring < String
>>> end
> => nil
>>> n = Nstring.new("hi")
> => "hi"
>>> puts n
> hi

Same here:

seltzer:~ sandal$ ruby -v
ruby 1.8.6 (2008-06-20 patchlevel 230) [i686-darwin8.11.1]
seltzer:~ sandal$ irb
>> class NString < String
>> end
=> nil
>> n = NString.new("hi")
=> "hi"
>> puts n
hi

That having been said, I generally avoid sub-classing core Ruby
objects because I think some of them use optimizations that cause
internal C methods to be called rather than the methods of a subclass,
resulting in strange behaviour. That having been said, I don't know
that I've ever seen it in practice. Does anyone have an example of
this, or am I just being paranoid?

-greg

Lou Zell

7/31/2008 8:51:00 PM

0

Lou Zell wrote:
> Mikael, I can deal with that, I'll swap out the $'s with block params.
> Thanks for the workaround!
>
> Lou

Actually, this did not work the way I expected. It is fine for a case
like this:
str = "match1"
gsub!(/(match1)/) {|m| m}

But not this:
str = "match1match2"
gsub!(/(match1)(match2)/) {|m1,m2| m1 + m2}

Where I am really looking for:
str = "match1match2"
gsub!(/(match1)(match2)/) { $1 + $2}


So let me ask this instead: How do I pass a block from one method to
another without invoking the block?

For instance, let's say I want to create a method nsub! that behaves
EXACTLY like gsub!

class String
def nsub!(*args)
gsub!(args[0]) {yield}
end
end

This will not work, say I do this:

s = String.new("whatever")
s.nsub!(/(what)/) {$1}

The yield in the body of nsub! invokes the block {$1}, but in this
context $1 is nil, so it is like I am calling

gsub!(args[0]) {nil}

Which is obviously not what I want. I would like to pass the original
code block:

gsub!(args[0]) {$1}


Any ideas?

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