Forum: Ruby Symbol#to_proc is just so beautiful

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
5da4c52f43677f395aff5bde775593c2?d=identicon&s=25 Daniel Schierbeck (dasch)
on 2006-04-19 18:30
(Received via mailing list)
When is this ever getting into Ruby Core?

   class Symbol
     def to_proc
       proc{|obj| obj.send(self) }
     end
   end

Consider this:

   class Numeric
     def positive?
       self > 0
     end
   end

   [1, 2, 3].all? &:positive?  => true
   [-1, 2, 3].all? &:positive? => false

It's just so damn beautiful!


Daniel
E0ed615bd6632dd23165e045e3c1df09?d=identicon&s=25 Florian GroÃ? (Guest)
on 2006-04-19 21:05
(Received via mailing list)
Daniel Schierbeck schrieb:

>   class Numeric
>     def positive?
>       self > 0
>     end
>   end
>
>   [1, 2, 3].all? &:positive?  => true
>   [-1, 2, 3].all? &:positive? => false
>
> It's just so damn beautiful!

If you use this definition instead:

class Symbol
   def to_proc()
     lambda { |obj, *args| obj.send(self, *args) }
   end
end

You can also do this:

(1 .. 5).inject(&:+) # => 15
(1 .. 5).inject(&:*) # => 120
5da4c52f43677f395aff5bde775593c2?d=identicon&s=25 Daniel Schierbeck (dasch)
on 2006-04-19 21:58
(Received via mailing list)
Florian Groß wrote:
> If you use this definition instead:
>
> class Symbol
>   def to_proc()
>     lambda { |obj, *args| obj.send(self, *args) }
>   end
> end
 >
> You can also do this:
>
> (1 .. 5).inject(&:+) # => 15
> (1 .. 5).inject(&:*) # => 120

Sweeeeet! Oh man, I love this language!
5da4c52f43677f395aff5bde775593c2?d=identicon&s=25 Daniel Schierbeck (dasch)
on 2006-04-19 22:07
(Received via mailing list)
Florian Groß wrote:
>   (1 .. 5).inject(&:+) # => 15
>   (1 .. 5).inject(&:*) # => 120

This has got to be the most obfuscated way to write 2 * 3:

   [2, 3].inject(&:*)  => 6


Daniel
Cff9eed5d8099e4c2d34eae663aae87e?d=identicon&s=25 Jacob Fugal (Guest)
on 2006-04-19 23:34
(Received via mailing list)
On 4/19/06, Daniel Schierbeck <daniel.schierbeck@gmail.com> wrote:
>    [2, 3].inject(&:*)  => 6

Is it just me, or does that look like an ASCII singing Elvis? Maybe
that's how he died, injecting to many [2, 3] shots...

Jacob Fugal
695abc793d51f62f781ef035c232f826?d=identicon&s=25 John Johnson (Guest)
on 2006-04-20 01:10
(Received via mailing list)
On 19-Apr-2006, at 15:03, Florian Groß wrote:

>   end
> end
>
> You can also do this:
>
> (1 .. 5).inject(&:+) # => 15
> (1 .. 5).inject(&:*) # => 120

IIIEEEeee, it's Perl, it's Perl!  :-)

I don't see anything wrong with:

[1, 2, 3].all? { |n| n > 0 }

It's a lot more legible than getting into all the Snoopy talk (@#$%).

Regards,
   JJ
---
Help everyone. If you can't do that, then at least be nice.
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 Joel VanderWerf (Guest)
on 2006-04-20 01:50
(Received via mailing list)
John Johnson wrote:
> It's a lot more legible than getting into all the Snoopy talk (@#$%).

This is way OT, but I can't actually remember Snoopy ever swearing. Yet
it gets mentioned frequently (even in the pick-axe). Has the ruby
community collectively hallucinated it? Or did ruby programmers grow up
in a parallel universe with R rated daily comics?
25e11a00a89683f7e01e425a1a6e305c?d=identicon&s=25 Wilson Bilkovich (Guest)
on 2006-04-20 01:59
(Received via mailing list)
On 4/19/06, Joel VanderWerf <vjoel@path.berkeley.edu> wrote:
> John Johnson wrote:
> > It's a lot more legible than getting into all the Snoopy talk (@#$%).
>
> This is way OT, but I can't actually remember Snoopy ever swearing. Yet
> it gets mentioned frequently (even in the pick-axe). Has the ruby
> community collectively hallucinated it? Or did ruby programmers grow up
> in a parallel universe with R rated daily comics?
>

That's how Snoopy's speech was depicted in the cartoons (not the comic
strips).
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 Joel VanderWerf (Guest)
on 2006-04-20 02:14
(Received via mailing list)
Wilson Bilkovich wrote:
>
Ah... the parallel universe of television ;)

Thanks for clearing that up for me.
5b3304fb2126c4744507c116b0f47850?d=identicon&s=25 Omer Raviv (omerraviv)
on 2006-06-30 10:12
John Johnson wrote:


> IIIEEEeee, it's Perl, it's Perl!  :-)
>
> I don't see anything wrong with:
>
> [1, 2, 3].all? { |n| n > 0 }
>
> It's a lot more legible than getting into all the Snoopy talk (@#$%).

I agree that it's fine, but:

a) It can be expressed with a shorter code snippet (less line noise),
therefore making it easy to do method-chaining.

b) I implicitly understand that it is an array of numbers, so the idea
of "a number" repeats itself three times (you had to write 'n' twice).

a better example might be:
all_people.select { |person| person.retired? }
The subject of this operation is expressed twice more than it ought to
be.

Therefore,

[1,2,3].all?(:>, 0)
and
all_people.select(:retired?)

is also, IMHO, a good choice.
45196398e9685000d195ec626d477f0e?d=identicon&s=25 unknown (Guest)
on 2006-06-30 11:34
(Received via mailing list)
Perhaps instead of

   all_people.select(&:retired?)

select could return a functor --in this case an enumerator:

   all_people.select.retired?

And in fact I believe this functionality is in 1.9 already. It works
with all enumeratable methods and methods of classes that serve the
same purpose. I think it could be further generalized though for any
method accepting a block. For:

  def foo(&blk)

then

  foo.bar

translates into

  foo { |x| x.bar }

(It may require the ability to sepcify manditory blocks though, like I
brought up in another recent thread)

T.
45196398e9685000d195ec626d477f0e?d=identicon&s=25 unknown (Guest)
on 2006-07-01 09:56
(Received via mailing list)
transfire@gmail.com wrote:
>
>   def foo(&blk)
>
> then
>
>   foo.bar
>
> translates into
>
>   foo { |x| x.bar }

No one though this was interesing?

T.
0ec4920185b657a03edf01fff96b4e9b?d=identicon&s=25 Yukihiro Matsumoto (Guest)
on 2006-07-01 11:18
(Received via mailing list)
Hi,

In message "Re: Symbol#to_proc is just so beautiful"
    on Sat, 1 Jul 2006 16:56:15 +0900, transfire@gmail.com writes:

|No one though this was interesing?

Interesting but too radical.  I'm afraid that it's too hard to imagine

|>   foo { |x| x.bar }

when I see

|>   foo.bar

							matz.
E1d641bfe4071a5413bac781f06d3fd1?d=identicon&s=25 Sean O'halpin (sean)
on 2006-07-01 13:56
(Received via mailing list)
Hi,

I don't want to rain on anyone's parade, but this technique is fairly
inefficient compared to using normal blocks.

Consider this:

class Symbol
  def to_proc
    proc{|obj| obj.send(self) }
  end
end

class Numeric
  def positive?
    self > 0
  end
end

def symbol_to_proc
  (1..1000).all? &:positive?
end
def use_block
  (1..1000).all? {|x| x.positive?}
end

require 'benchmark'
include Benchmark

n = 1000
bm(20) {|x|
  x.report("symbol_to_proc") { n.times { symbol_to_proc }}
  x.report("use_block") { n.times { use_block }}
  }
__END__
                          user     system      total        real
symbol_to_proc        2.031000   0.000000   2.031000 (  2.063000)
use_block             1.219000   0.000000   1.219000 (  1.266000)

Of course, that may change if Symbol#to_proc makes it into core.

Regards,
Sean
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2006-07-01 14:14
(Received via mailing list)
Hi --

On Fri, 30 Jun 2006, Omer Raviv wrote:

> John Johnson wrote:
>
>
>> IIIEEEeee, it's Perl, it's Perl!  :-)
>>
>> I don't see anything wrong with:
>>
>> [1, 2, 3].all? { |n| n > 0 }
>>
>> It's a lot more legible than getting into all the Snoopy talk (@#$%).

I agree.  I don't see the problem with it.

> I agree that it's fine, but:
>
> a) It can be expressed with a shorter code snippet (less line noise),
> therefore making it easy to do method-chaining.

"&:>" and such, I would argue, are shorter but have *more* line noise
than the equivalent explicit blocks.

> [1,2,3].all?(:>, 0)
> and
> all_people.select(:retired?)

I always think of these things partly in terms of explanation.  In
order to explain all_people.select(:retired?), one would either have
to present :retired? as a "magic" way of filtering for retiredness, or
explain that it's actually {|p| p.retired? } in disguise.  Somehow it
doesn't work as, so to speak, a primary, transparent technique.

"Why is there a colon?"  Because it's a symbol.  "So a symbol invokes
the method of that name?"  No.

And so on....


David

--
David A. Black (dblack@wobblini.net)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

See what the readers are saying about "Ruby for Rails"!
http://www.rubypowerandlight.com/quotes
45196398e9685000d195ec626d477f0e?d=identicon&s=25 unknown (Guest)
on 2006-07-01 17:35
(Received via mailing list)
Yukihiro Matsumoto wrote:
>
> when I see
>
> |>   foo.bar

I can see that on first econounter the idea, certainly. And I think the
same is true when enumerable method returns an enumerator. It's
something that requires getting usedto. I'm more accustom to it myself
becuase I have used "Functor pattern" enough. If I may suggest, at
least make a note to reconsider it in the future. I think as the
enumerator functionality becomes more common, this will not seem so
radical.

And actually if you look at it less abstract terms it doesn't seem
quite as radical either:

  [1,2,3].collect.to_s

  ["A3","B2","C1"].sort_by[1,1]

  'pretty little ponies'.gsub(/[^aeiou]/).upcase

T.
0ec4920185b657a03edf01fff96b4e9b?d=identicon&s=25 Yukihiro Matsumoto (Guest)
on 2006-07-01 17:48
(Received via mailing list)
Hi,

In message "Re: Symbol#to_proc is just so beautiful"
    on Sun, 2 Jul 2006 00:34:22 +0900, transfire@gmail.com writes:

|And actually if you look at it less abstract terms it doesn't seem
|quite as radical either:
|
|  [1,2,3].collect.to_s

This means 'print([1,2,3].collect)' would not work, since it calls
to_s for string conversion, but to_s gives it an array of strings.
In any case, I feel like it requires special notation (for partial
evaluation), even if we really need it.

							matz.
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2006-07-01 17:51
(Received via mailing list)
Hi --

On Sun, 2 Jul 2006, transfire@gmail.com wrote:

>>
>> |>   foo { |x| x.bar }
>>
>> when I see
>>
>> |>   foo.bar
>
> I can see that on first econounter the idea, certainly. And I think the
> same is true when enumerable method returns an enumerator.

Definitely.  I find this:

   array.map.upcase

(if I'm getting the magic enumerator thing right) pretty obscure.  I
mean, the words on the screen more or less describe what's happening,
but the dot syntax feels to me like it's being pushed beyond the
limits of usefulness.


David

--
David A. Black (dblack@wobblini.net)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

See what the readers are saying about "Ruby for Rails"!
http://www.rubypowerandlight.com/quotes
45196398e9685000d195ec626d477f0e?d=identicon&s=25 unknown (Guest)
on 2006-07-01 18:06
(Received via mailing list)
Yukihiro Matsumoto wrote:
> This means 'print([1,2,3].collect)' would not work, since it calls
> to_s for string conversion, but to_s gives it an array of strings.

Why should it? If the block is manditory then it won't work anyway.
This is what I was saying about this notation needing a way to specify
manditory blocks in order to work. It cannot apply to optional blocks.
(Which reminds me I got bit by optional blocks yesterday when I forgt
to put .each :/)

> In any case, I feel like it requires special notation (for partial
> evaluation), even if we really need it.

Well, "need" is pretty relative. It's more a question of want I think.
How much do we want a consice notation like this? After all a special
notation might ruin it's readiabilty, which is it's main advantage.

Anyhow, it's certainly not pressing. But I have a hunch the idiom will
gain more acceptance over time.

Thanks,
T.
0ec4920185b657a03edf01fff96b4e9b?d=identicon&s=25 Yukihiro Matsumoto (Guest)
on 2006-07-01 18:33
(Received via mailing list)
Hi,

In message "Re: Symbol#to_proc is just so beautiful"
    on Sun, 2 Jul 2006 01:05:42 +0900, transfire@gmail.com writes:

|> |  [1,2,3].collect.to_s
|>
|> This means 'print([1,2,3].collect)' would not work, since it calls
|> to_s for string conversion, but to_s gives it an array of strings.
|
|Why should it? If the block is manditory then it won't work anyway.
|This is what I was saying about this notation needing a way to specify
|manditory blocks in order to work. It cannot apply to optional blocks.
|(Which reminds me I got bit by optional blocks yesterday when I forgt
|to put .each :/)
|
|> In any case, I feel like it requires special notation (for partial
|> evaluation), even if we really need it.
|
|Well, "need" is pretty relative. It's more a question of want I think.
|How much do we want a consice notation like this? After all a special
|notation might ruin it's readiabilty, which is it's main advantage.

"need" is pretty relative indeed.  And I'm a big fan of concise
notation in general.  But still I don't think this is a good idea
(without special notation).  Iterating method calls (like to_s in
above example), should be distinguishable from usual method calls,
because they are different, they act different, their implementations
are different.

Besides that you need to have knowledge of whether #collect requires
mandatory block or not to tell how obj.collect.to_s works.  Note that
#collect may or may not have mandatory block depends on its receiver.

							matz.
45196398e9685000d195ec626d477f0e?d=identicon&s=25 unknown (Guest)
on 2006-07-01 19:13
(Received via mailing list)
Yukihiro Matsumoto wrote:

> "need" is pretty relative indeed.  And I'm a big fan of concise
> notation in general.  But still I don't think this is a good idea
> (without special notation).  Iterating method calls (like to_s in
> above example), should be distinguishable from usual method calls,
> because they are different, they act different, their implementations
> are different.
>
> Besides that you need to have knowledge of whether #collect requires
> mandatory block or not to tell how obj.collect.to_s works.  Note that
> #collect may or may not have mandatory block depends on its receiver.

Okay. Though we should consider that it can already be done, and
similar code is already being done in limited cases. Just as an example
here's how collect could be defined.

  alias :old_collect, :collect
  def collect( &yld )
    if yld
      old_collect( &yld )
    else
      Functor.new { |op, x| x.__send__(op) }
    end
  end

But even so, say a special notaion were the best option. What kind of
notations do we have left? Everything starts to seem so perlish. I
don't know. Maybe '->' could play a role here?

T.
This topic is locked and can not be replied to.