Web Images Videos Maps News Shopping Gmail more »
Recently Visited Groups | Help | Sign in
Google Groups Home
A little Quiz
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  8 messages - Collapse all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Dominik Bathon  
View profile  
 More options Jun 6 2005, 12:44 pm
Newsgroups: comp.lang.ruby
From: "Dominik Bathon" <dba...@gmx.de>
Date: Tue, 7 Jun 2005 01:44:39 +0900
Local: Mon, Jun 6 2005 12:44 pm
Subject: A little Quiz
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


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
James Britt  
View profile  
 More options Jun 6 2005, 1:32 pm
Newsgroups: comp.lang.ruby
From: James Britt <jame...@neurogami.com>
Date: Tue, 7 Jun 2005 02:32:05 +0900
Local: Mon, Jun 6 2005 1:32 pm
Subject: Re: A little Quiz

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.ruby-doc.org - The Ruby Documentation Site
http://www.rubyxml.com  - News, Articles, and Listings for Ruby & XML
http://www.rubystuff.com - The Ruby Store for Ruby Stuff
http://www.jamesbritt.com  - Playing with Better Toys


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Dominik Bathon  
View profile  
 More options Jun 6 2005, 2:44 pm
Newsgroups: comp.lang.ruby
From: "Dominik Bathon" <dba...@gmx.de>
Date: Tue, 7 Jun 2005 03:44:23 +0900
Local: Mon, Jun 6 2005 2:44 pm
Subject: Re: A little Quiz
On Mon, 06 Jun 2005 19:32:05 +0200, James Britt <jame...@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


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
James Edward Gray II  
View profile  
 More options Jun 6 2005, 9:45 pm
Newsgroups: comp.lang.ruby
From: James Edward Gray II <ja...@grayproductions.net>
Date: Tue, 7 Jun 2005 10:45:07 +0900
Local: Mon, Jun 6 2005 9:45 pm
Subject: Re: A little Quiz
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


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Logan Capaldo  
View profile  
 More options Jun 7 2005, 1:06 pm
Newsgroups: comp.lang.ruby
From: Logan Capaldo <logancapa...@gmail.com>
Date: Wed, 8 Jun 2005 02:06:52 +0900
Local: Tues, Jun 7 2005 1:06 pm
Subject: Re: A little Quiz
On 6/6/05, James Britt <jame...@neurogami.com> wrote:

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.


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Discussion subject changed to "A little Quiz (Solution)" by Dominik Bathon
Dominik Bathon  
View profile  
 More options Jun 8 2005, 7:24 pm
Newsgroups: comp.lang.ruby
From: "Dominik Bathon" <dba...@gmx.de>
Date: Thu, 9 Jun 2005 08:24:45 +0900
Local: Wed, Jun 8 2005 7:24 pm
Subject: Re: A little Quiz (Solution)
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


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Dave Burt  
View profile  
 More options Jun 9 2005, 7:28 am
Newsgroups: comp.lang.ruby
From: "Dave Burt" <d...@burt.id.au>
Date: Thu, 09 Jun 2005 11:28:28 GMT
Local: Thurs, Jun 9 2005 7:28 am
Subject: Re: A little Quiz (Solution)

"Dominik Bathon" <dba...@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.

    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Brian Schröder  
View profile  
 More options Jun 9 2005, 4:11 pm
Newsgroups: comp.lang.ruby
From: Brian Schröder <ruby.br...@gmail.com>
Date: Fri, 10 Jun 2005 05:11:07 +0900
Local: Thurs, Jun 9 2005 4:11 pm
Subject: Re: A little Quiz (Solution)

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-schroeder.de/

Stringed instrument chords: http://chordlist.brian-schroeder.de/


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2009 Google