Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Ruby (http://www.velocityreviews.com/forums/f66-ruby.html)
-   -   idiom I've not seen before (http://www.velocityreviews.com/forums/t847963-idiom-ive-not-seen-before.html)

Rob Saul 02-07-2008 03:55 AM

idiom I've not seen before
 

I came across this :
elements.sort_by(&:position).each
in something I've taken over. I thought sort_by
took a block. Obviously I'm missing something.
Can anyone shed some light on this trick?

~Rob



Rob Biedenharn 02-07-2008 04:04 AM

Re: idiom I've not seen before
 
On Feb 6, 2008, at 10:55 PM, Rob Saul wrote:
> I came across this :
> elements.sort_by(&:position).each
> in something I've taken over. I thought sort_by
> took a block. Obviously I'm missing something.
> Can anyone shed some light on this trick?
>
> ~Rob



You've found Symbol#to_proc

That line is equivalent to:

elements.sort_by {|e| e.send(:position) }.each

The "something" is a Rails project, isn't it?

== vendor/rails/activesupport/lib/active_support/core_ext/symbol.rb ==
class Symbol
# Turns the symbol into a simple proc, which is especially useful
for enumerations. Examples:
#
# # The same as people.collect { |p| p.name }
# people.collect(&:name)
#
# # The same as people.select { |p| p.manager? }.collect { |p|
p.salary }
# people.select(&:manager?).collect(&:salary)
def to_proc
Proc.new { |*args| args.shift.__send__(self, *args) }
end
end


I don't know how you can send additional arguments however.

-Rob

Rob Biedenharn http://agileconsultingllc.com
Rob@AgileConsultingLLC.com




Jeremy Kemper 02-07-2008 04:06 AM

Re: idiom I've not seen before
 
On 2/6/08, Rob Saul <wyrd@code-gnomemad.org> wrote:
> I came across this :
> elements.sort_by(&:position).each
> in something I've taken over. I thought sort_by
> took a block. Obviously I'm missing something.
> Can anyone shed some light on this trick?


Sure. &:position == :position.to_proc == proc { |element, *args|
element.position(*args) }

So elements.sort_by(&:position) is shorthand for sorting the elements
by position.

jeremy


Rob Saul 02-07-2008 04:14 AM

Re: idiom I've not seen before
 
Jeremy Kemper wrote:
>
> Sure. &:position == :position.to_proc == proc { |element, *args|
> element.position(*args) }
>
> So elements.sort_by(&:position) is shorthand for sorting the elements
> by position.
>
> jeremy


thanks to both Jeremy and Rob for the enlightenment. And
yes, it is a Rails project.




Martin DeMello 02-07-2008 05:04 AM

Re: idiom I've not seen before
 
On Feb 7, 2008 4:14 AM, Rob Saul <wyrd@code-gnomemad.org> wrote:

> thanks to both Jeremy and Rob for the enlightenment. And
> yes, it is a Rails project.


Also, I believe Symbol.to_proc is making it into 1.9

martin


Thomas Wieczorek 02-07-2008 05:13 AM

Re: idiom I've not seen before
 
On Thu, Feb 7, 2008 at 6:04 AM, Martin DeMello <martindemello@gmail.com> wrote:
>
> Also, I believe Symbol.to_proc is making it into 1.9
>


Yes, it is in.
Raganwald has a good blog entry about it, he also mentions
String#to_proc:
http://weblog.raganwald.com/2007/11/...boltoproc.html


Ryan Davis 02-07-2008 05:16 AM

Re: idiom I've not seen before
 

On Feb 6, 2008, at 20:04 , Rob Biedenharn wrote:

> You've found Symbol#to_proc
>
> That line is equivalent to:
>
> elements.sort_by {|e| e.send(:position) }.each


Buyer beware:

#!/usr/local/bin/ruby -w

# # of iterations = 10000
# user system total real
# null_time 0.000000 0.000000 0.000000 ( 0.001561)
# map 0.880000 0.000000 0.880000 ( 0.878500)
# to_proc 2.790000 0.000000 2.790000 ( 2.799291)

# # of iterations = 100000
# user system total real
# null_time 0.020000 0.000000 0.020000 ( 0.013951)
# map 8.730000 0.010000 8.740000 ( 8.766693)
# to_proc 27.960000 0.030000 27.990000 ( 28.001288)

require 'benchmark'

class Symbol
def to_proc
Proc.new { |*args| args.shift.__send__(self, *args) }
end
end

a = (1..100).to_a

raise "stupid" unless a.map { |n| n.to_s } == a.map(&:to_s)

max = (ARGV.shift || 1_000_000).to_i

puts "# of iterations = #{max}"
Benchmark::bm(20) do |x|
x.report("null_time") do
for i in 0..max do
# do nothing
end
end

x.report("map") do
for i in 0..max do
a.map { |n| n.to_s }
end
end

x.report("to_proc") do
for i in 0..max do
a.map(&:to_s)
end
end
end



botp 02-07-2008 05:35 AM

Re: idiom I've not seen before
 
On Feb 7, 2008 1:16 PM, Ryan Davis <ryand-ruby@zenspider.com> wrote:
>
> Buyer beware:
>
> # # of iterations = 10000
> # user system total real
> # null_time 0.000000 0.000000 0.000000 ( 0.001561)
> # map 0.880000 0.000000 0.880000 ( 0.878500)
> # to_proc 2.790000 0.000000 2.790000 ( 2.799291)
>
> # # of iterations = 100000
> # user system total real
> # null_time 0.020000 0.000000 0.020000 ( 0.013951)
> # map 8.730000 0.010000 8.740000 ( 8.766693)
> # to_proc 27.960000 0.030000 27.990000 ( 28.001288)


that will change in ruby1.9 since to_proc is builtin.
eg, a run in windows,

C:\ruby1.9\bin>.\ruby.exe test.rb 1_000
# of iterations = 1000
user system total real
null_time 0.000000 0.000000 0.000000 ( 0.000000)
map 0.203000 0.000000 0.203000 ( 0.203000)
to_proc 0.156000 0.000000 0.156000 ( 0.172000)

C:\ruby1.9\bin>.\ruby.exe test.rb 10_000
# of iterations = 10000
user system total real
null_time 0.016000 0.000000 0.016000 ( 0.015000)
map 1.937000 0.000000 1.937000 ( 2.515000)
to_proc 1.610000 0.000000 1.610000 ( 1.954000)

C:\ruby1.9\bin>.\ruby.exe test.rb 100_000
# of iterations = 100000
user system total real
null_time 0.328000 0.000000 0.328000 ( 0.328000)
map 19.344000 0.000000 19.344000 ( 24.953000)
to_proc 17.296000 0.015000 17.311000 ( 18.016000)

not bad, imho.
kind regards -botp


Phrogz 02-07-2008 05:56 PM

Symbol#to_proc, lazy evaluation (was Re: idiom I've not seen before)
 
On Feb 6, 8:55 pm, Rob Saul <w...@code-gnomemad.org> wrote:
> I came across this :
> elements.sort_by(&:position).each


Loosely-related aside:

I've been learning Io[1] recently. Io (like Lisp, I gather) allows
lazy evaluation of method arguments. In Ruby terms, this would mean
that I can write something like this:

# Ruby-esque pseudo-code; neither Io nor Ruby
class Array
def select
result = []
self.each{ |el| result << el if el.sendArg(0) }
result
end
end

my_array.select( isCool? )
my_array.select( > 5 )
my_array.select( roughlyEquals( jim.newSize ) )

In Io, the "isCool?" method/message isn't (necessarily) evaluated when
you call the select method. Instead, you can perform some
introspection on the parsed message tree for each argument and choose
to ignore it, change it to a string, or send it as a message to any
object you want.

To be clear, in the above, the "isCool?" message/method would be send/
invoked on each array element. Or each element would be sent a
">( 5 )" message.

The Symbol#to_proc technique is clever, but not quite as clean as
being able to write (in Io):
elements sortBy( position )
elements map( * 2 )
elements select( size > 5 )


This same ability in Io allowed me to add a debugging method "p" (in
homage of Ruby) that labels a value with the exact call you made. For
example:

# In Io with my custom method (not Ruby)
p( gk )
#=> gk is Person_0x4de0d8:
#=> name = "Gavin Kistner"
#=> nick = "Phrogz""

p( gk name )
#=> gk name is Gavin Kistner

p( gk nick size )
#=> gk nick size is 6



[1] http://www.iolanguage.com/

Clifford Heath 02-07-2008 10:38 PM

Re: Symbol#to_proc, lazy evaluation (was Re: idiom I've not seenbefore)
 
Phrogz wrote:
> I've been learning Io[1] recently. Io (like Lisp, I gather) allows
> lazy evaluation of method arguments.

....
> In Io, the "isCool?" method/message isn't (necessarily) evaluated when
> you call the select method.


This is known as "call by name", as opposed to by reference or by value.
It was, more than anything, the single thing that caused the most difficulty
for the authors of Algol68 optimising compilers :-).

Niklaus Wirt once joked that Europeans (who know how to pronounce his name)
called him by name, whereas Americans called him by value (nickel's worth).
Maybe apocryphal, but funny :-).

Clifford Heath.


All times are GMT. The time now is 10:59 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.