[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

A little Quiz

Dominik Bathon

6/6/2005 4:45:00 PM

First of all, this is no attempt to rival with James' nice Ruby Quiz ;-)

I came up with a nice new(?) use for method_missing today.
Now it is your job to figure out what you can do with it.
(My hope is that someone will find nice uses for this, that I didn't think
of)

So here is the code:

class Array
def method_missing(meth, *args, &block)
rmeth = (meth.to_s =~ /\A_x_(.*)/ ? $1.to_sym : meth)
if block
if empty?
[]
else
mm_block_rec(rmeth, 0, res=[], [], *args, &block)
res
end
else
res=[]
each_with_index { |el, i|
res << el.send(rmeth, *(args.collect { |el|
(Array === el) ? el[i] : el
}))
}
res
end
end

private

def mm_block_rec(rmeth, i, res, bargs, *args, &block)
myargs=args.collect { |el| (Array === el) ? el[i] : el }
res[i] = self[i].send(rmeth, *myargs) { |*ba|
bargs[i]=(ba.size==1 ? ba.first : ba)
if i==size-1
block.call(*bargs)
else
mm_block_rec(rmeth, i+1, res, bargs, *args, &block)
end
}
end
end


And some questions:

What does it do?

What can it be used for?

Has this been done before? (I couldn't find anything.)

Do you like it?


Dominik


23 Answers

james_b

6/6/2005 5:32:00 PM

0

Dominik Bathon wrote:
> First of all, this is no attempt to rival with James' nice Ruby Quiz ;-)
>
> I came up with a nice new(?) use for method_missing today.
> Now it is your job to figure out what you can do with it.
> (My hope is that someone will find nice uses for this, that I didn't
> think of)
>

Interesting.

>
> And some questions:
>
> What does it do?
>
> What can it be used for?
>
> Has this been done before? (I couldn't find anything.)


Reminds me of some code I wrote a few years ago when I was poking into
method-oriented programming.

Rather than have
receiver.message( args )

I wanted to reverse things and do
message( args )->[ list_of_receivers ]


I hacked on Symbol and the result was that I could loop over a set of
objects, or use a proc to conditionally send the message to objects in
ObjectSpace (i.e., "I know what I want to do, I just don't know who to
do it to"). The results were then collected and returned as an array.

The call looked something like

:message.>>( obj_set_or_criteria_proc ) { args }

I never found a really practical application for this. Conceivably, one
could close all open file handles, or shut down lingering socket
connections, or save user sessions if the session was x minutes old, or
whatever.

It was mostly a "Gee, I wonder if ..." sort of thing, and the best
scenario I could think of was if I had an app that might need a global
shutdown, so one might want to dispatch a common set of messages across
a range of unknown objects before ending.

I never released the code, being unhappy with the syntax. But I still
like the idea of casting a message out into object space and reeling
back the results.


BTW, I tried out your code, with a trivial example:

p %w{ This is some text }.size

Ah, but, of course, method_missing never gets called, so I did not get
what I wanted.

This works, though:

p %w{ This is some text }.upcase

So there is the issue of trying to distribute a method across the list
when that method is also implemented by Array



James

--

http://www.ru... - The Ruby Documentation Site
http://www.r... - News, Articles, and Listings for Ruby & XML
http://www.rub... - The Ruby Store for Ruby Stuff
http://www.jame... - Playing with Better Toys


Dominik Bathon

6/6/2005 6:44:00 PM

0

On Mon, 06 Jun 2005 19:32:05 +0200, James Britt <james_b@neurogami.com>
wrote:

> BTW, I tried out your code, with a trivial example:
>
> p %w{ This is some text }.size
>
> Ah, but, of course, method_missing never gets called, so I did not get
> what I wanted.

Hint: _x_ ;-)

Dominik


James Gray

6/7/2005 1:45:00 AM

0

On Jun 6, 2005, at 11:44 AM, Dominik Bathon wrote:

> First of all, this is no attempt to rival with James' nice Ruby
> Quiz ;-)

Then you definitely should have sent it in as next week's quiz. ;)

James Edward Gray II



Logan Capaldo

6/7/2005 5:07:00 PM

0

On 6/6/05, James Britt <james_b@neurogami.com> wrote:
> Dominik Bathon wrote:
> > First of all, this is no attempt to rival with James' nice Ruby Quiz ;-)
> >
> > I came up with a nice new(?) use for method_missing today.
> > Now it is your job to figure out what you can do with it.
> > (My hope is that someone will find nice uses for this, that I didn't
> > think of)
> >
>
> Interesting.
>
> >
> > And some questions:
> >
> > What does it do?
> >
> > What can it be used for?
> >
> > Has this been done before? (I couldn't find anything.)
>
>
> Reminds me of some code I wrote a few years ago when I was poking into
> method-oriented programming.
>
> Rather than have
> receiver.message( args )
>
> I wanted to reverse things and do
> message( args )->[ list_of_receivers ]
>
>
> I hacked on Symbol and the result was that I could loop over a set of
> objects, or use a proc to conditionally send the message to objects in
> ObjectSpace (i.e., "I know what I want to do, I just don't know who to
> do it to"). The results were then collected and returned as an array.
>
> The call looked something like
>
> :message.>>( obj_set_or_criteria_proc ) { args }
>
> I never found a really practical application for this. Conceivably, one
> could close all open file handles, or shut down lingering socket
> connections, or save user sessions if the session was x minutes old, or
> whatever.
>
> It was mostly a "Gee, I wonder if ..." sort of thing, and the best
> scenario I could think of was if I had an app that might need a global
> shutdown, so one might want to dispatch a common set of messages across
> a range of unknown objects before ending.
>
> I never released the code, being unhappy with the syntax. But I still
> like the idea of casting a message out into object space and reeling
> back the results.
>
>
> BTW, I tried out your code, with a trivial example:
>
> p %w{ This is some text }.size
>
> Ah, but, of course, method_missing never gets called, so I did not get
> what I wanted.
>
> This works, though:
>
> p %w{ This is some text }.upcase
>
> So there is the issue of trying to distribute a method across the list
> when that method is also implemented by Array
>
>
>
> James
>
> --
>
> http://www.ru... - The Ruby Documentation Site
> http://www.r... - News, Articles, and Listings for Ruby & XML
> http://www.rub... - The Ruby Store for Ruby Stuff
> http://www.jame... - Playing with Better Toys
>
>

I've thought sometimes that this would be a good shortcut:

module Enumerable
alias __original__map__ map
def map(*args, &block)
if args.length > 1
__original__map__ { |obj| args.inject(obj) {
|o, meth_sym|

o.send(meth_sym) }
}
else
__original__map__(&block)
end
end
end

so we have [ ' hello ', ' world', ' ! '].map(:upcase, :strip)

Doesn't give you anything over the block syntax, but it is slightly less typing.


Dominik Bathon

6/8/2005 11:25:00 PM

0

Obviously no one really likes to decipher undocumented code... (I should
have known after the "Code Cleaning"-Quiz ;-)
Well, so let me tell you what it does:

As James Britt already figured out, it lets you call one method on all
elements of an Array. If no block is given this works like collect.
Instead of

[-1, -2, -3].collect { |x| x.abs }
=> [1, 2, 3]

you can just write

[-1, -2, -3].abs
=> [1, 2, 3]

Since #abs is not part of the Array interface, method_missing is
triggered. But it does more than collect, it even works on nested Arrays:

[[-1,-2],[-3,4],-2,5].abs
=> [[1, 2], [3, 4], 2, 5]

If you try a method that is part of Array's interface, method_missing
obviously won't be called:

%w[abc de fghi].size
=> 3

But there is a trick (maybe hack):

%w[abc de fghi]._x_size
=> [3, 2, 4]

The optional "_x_" is automatically stripped. But this also has a
downside, it doesn't work with nested arrays, but on the other hand you
can choose an explicit depth:

[[[1,2,3], "iuhiu"], ["iu", [4,5,6]]]._x__x_size
=> [[3, 5], [2, 3]]

But methods also can get arguments, so how are they handled? Some examples:

%w[abc de fgh ijk].ljust(5)
=> ["abc ", "de ", "fgh ", "ijk "]

%w[abc de fgh ijk].ljust((4..8).to_a)
=> ["abc ", "de ", "fgh ", "ijk "]

%w[abc de fgh ijk].ljust(5, %w[1 2 3 4])
=> ["abc11", "de222", "fgh33", "ijk44"]

%w[abc de fgh ijk].ljust([5, 3, 5, 6], %w[1 2 3 4])
=> ["abc11", "de2", "fgh33", "ijk444"]

I think you can get the idea.

But all this was just the beginning ;-)

My motivation to write this actually was to be able to say

[3, 3].times { |x, y|
p [x, y]
}

instead of

3.times { |x|
3.times { |y|
p [x, y]
}
}

Well, now I can. And of course you can combine this with the above:

[1,2].upto(4) { |*a| p a }
output:
[1, 2]
[1, 3]
[1, 4]
[2, 2]
[2, 3]
[2, 4]
[3, 2]
[3, 3]
[3, 4]
[4, 2]
[4, 3]
[4, 4]

[1,2].upto([2, 3]) { |*a| p a }
output:
[1, 2]
[1, 3]
[2, 2]
[2, 3]

[%w[a b c], [1, 2, 3]]._x_each { |*a| p a }
output:
["a", 1]
["a", 2]
["a", 3]
["b", 1]
["b", 2]
["b", 3]
["c", 1]
["c", 2]
["c", 3]

If multiple arguments would be yielded to the blocks, they are grouped by
arrays:

[%w[a b c], 1..3]._x_each_with_index { |*a| p a }
output:
[["a", 0], [1, 0]]
[["a", 0], [2, 1]]
[["a", 0], [3, 2]]
[["b", 1], [1, 0]]
[["b", 1], [2, 1]]
[["b", 1], [3, 2]]
[["c", 2], [1, 0]]
[["c", 2], [2, 1]]
[["c", 2], [3, 2]]

Because I wanted the multidimensional iteration, it doesn't work nice with
things like collect:

[%w[a b], 1..2]._x_collect { |*a| a }
=> [[[["a", 1], ["a", 2]], [["b", 1], ["b", 2]]], [["b", 1], ["b", 2]]]

Maybe I should add another special prefix ( ;-) ) so that it works more
like the non block version. Maybe like this:

[%w[a b], 1..2]._y_collect { |*a| a+a }
=> [["aa", "bb"], [2, 4]]

Or maybe use _i_ for the multidimensional iteration and _x_ for the rest...


I also thougt about adding it to Enumerable, but I think it doesn't make
to much sense for other Enumerables (like Ranges) and if you really need
it you can always use #to_a.

I realize there are lots of inconsistences in this concept, but I really
like it generally. So, what do you think?

Dominik


Dave Burt

6/9/2005 11:28:00 AM

0

"Dominik Bathon" <dbatml@gmx.de> wrote:
>
> <snip>
>
> I realize there are lots of inconsistences in this concept, but I really
> like it generally. So, what do you think?
>
> <snip backwards>
>
> [3, 3].times { |x, y|
> p [x, y]
> }

That is awesome.



Brian Schröder

6/9/2005 8:11:00 PM

0

> [snip]
> [3, 3].times { |x, y|
> p [x, y]
> }
>
> instead of
>
> 3.times { |x|
> 3.times { |y|
> p [x, y]
> }
> }
>
> [snip]
> I realize there are lots of inconsistences in this concept, but I really
> like it generally. So, what do you think?
>

I like that second version better, because its clearer. It makes clear
in which order you are iterating. I'd even prefer something including
0 and 2 (upto, each, for) to make clear what the boundaries are.

regards,

Brian


> Dominik
>
>


--
http://ruby.brian-sch...

Stringed instrument chords: http://chordlist.brian-sch...


B J Foster

7/30/2008 11:04:00 AM

0

RichTravsky wrote:
> B J Foster wrote:
>> http://ap.google.com/article/ALeqM5jVKZ-iJGNjECkaAR26jqQ8_maC0...
>
> Is he breathing? Good enough.
>
> RT

Isn't dementia just an advanced form of denial?

The loudmoron seems to have some form of dementia as well, as does
Irving - first he denies the holocaust, then he denies that he denied it:
http://news.bbc.co.uk/2/hi/europe/4...

WhiteWolf! <rayh<spam>@iol.ie>

7/30/2008 2:41:00 PM

0

On Tue, 29 Jul 2008 20:28:02 -0600, RichTravsky <traRvEsky@hotmMOVEail.com>
wrote:

>B J Foster wrote:
>>
>> http://ap.google.com/article/ALeqM5jVKZ-iJGNjECkaAR26jqQ8_maC0...
>
>Is he breathing? Good enough.
>
>RT

Attitutes like that make you no better then the suspected "nazi"... But I bet
your too blind to see it...

Ray


---------------------------------------------------------------
We have our task, and God knows it is a hard one -- the salvage
of a shipwrecked world. - Lothrop Stoddard
---------------------------------------------------------------

B J Foster

7/30/2008 10:10:00 PM

0

Whitewolf <rayh<spam>@iol.ie> wrote:
> On Tue, 29 Jul 2008 20:28:02 -0600, RichTravsky <traRvEsky@hotmMOVEail.com>
> wrote:
>
>> B J Foster wrote:
>>> http://ap.google.com/article/ALeqM5jVKZ-iJGNjECkaAR26jqQ8_maC0...
>> Is he breathing? Good enough.
>>
>> RT
>
> Attitutes like that make you no better then the suspected "nazi"... But I bet
> your too blind to see it...
>
> Ray
>

Using 'dementia' as a reason to avoid standing trial is IOW, his tiny
nazi brain being unable to deal with the implications of his crimes.

Are you suggesting that there are some compassionate grounds for
avoiding trial? LOL, be serious


>
> ---------------------------------------------------------------
> We have our task, and God knows it is a hard one -- the salvage
> of a shipwrecked world. - Lothrop Stoddard
> ---------------------------------------------------------------