Inject idiom

Dear all,

I am new to Ruby (coming right away from Perl). I’ve been playing with
Hpricot for the sake of learning and wrote a simple script to hash link
entries with their tags from del.icio.us front page.

My first attempt is more or less Perl-inspired:

require ‘hpricot’
require ‘open-uri’

doc = Hpricot(open(“http://del.icio.us/”))
tags = {}
doc.search(“//div.hotlist/ol/li”).each do |entry|
link = entry.search(“h4/a”).first[‘href’]
taglist = []
entry.search(“div/ul/li/a”).each do |tag|
taglist << tag.inner_html
end
tags[link] = taglist
end

p tags

I then tried to use the inject method:

doc = Hpricot( open(“http://del.icio.us/”) )
tags = doc.search(“//div.hotlist/ol/li”).inject({}) do | hash, entry |
link = entry.search(“h4/a”).first[‘href’]
hash[link] = entry.search(“div/ul/li/a”).inject([]) do | list, tag |
list << tag.inner_html
end
hash
end

I wonder what the best practice is? The most readable and best suited to
Ruby-style of programming. In Perl, although there is more than one way
to do every thing you want, there are definitely best practices. What
about Ruby? How do one use the inject idiom best?

Thanks in advance to all Rubyists for their help,

Ömer.

Hi Ömer,

On Sat, Jul 12, 2008 at 3:49 AM, عمر ملقب بالثانی
[email protected] wrote:

I wonder what the best practice is? The most readable and best suited to
Ruby-style of programming. In Perl, although there is more than one way
to do every thing you want, there are definitely best practices. What
about Ruby? How do one use the inject idiom best?

Do you like this?

doc = Hpricot(open(“http://del.icio.us/”))
tags = doc.search(“//div.hotlist/ol/li”).inject({}){|hash,entry|
hash[entry.search(“h4/a[1]”).first[‘href’]] =
entry.search(“div/ul/li/a/*”).to_a
hash
}

I sometimes want a hash setter method returning the hash itself:

class Hash
def set(key, value)
self.store(key, value)
return self
end
end

HTH,

Thanks to both of you ara.t.howard and Kentaro-san for the nice hints.
As far as I could tell from your tips, Ruby-style encourages conciseness
(hence the use of hash.update or the custom .set method that returns the
hash). And it seems that inject({}) is in any case preferred to h={}
and each loop, right?

GOTO Kentaro wrote:

Do you like this?
[…]

Yes. Short and to the point but still quite clear to a beginner.

ara.t.howard wrote:

i prefer
[…]

I liked the map method a lot (it reminds me the Perl map) and the way
one can build the hash step by step with .update (or .merge!) [on that,
I checked in The Ruby P.ming Language]. I’ll try to stick on that
kind of idiom.

. use space to give meaning: a newline is one char
. use explicit var names as comments

I am already used to this with Perl… (I pasted a slightly less spaced
code here)

. try to minimize method chaining so stacktraces to line #42 have
at least some meaning

I got your point on minimising method chaining but not what you meant
with line #42.

Thanks again.

Kind regards, Ömer.

On Jul 12, 2008, at 7:30 AM, عمر ملقب بالثانی wrote:

I got your point on minimising method chaining but not what you meant
with line #42.

simply that an error message in the logs like

foobar exception from foo.rb:42

is very hard to debug when the line looks like this

foo.bar.foobar.barfoo.method

a @ http://codeforpeople.com/

ara.t.howard wrote:

simply that an error message in the logs like
foobar exception from foo.rb:42

is very hard to debug when the line looks like this
foo.bar.foobar.barfoo.method

I see, thanks.

On Jul 11, 2008, at 12:49 PM, عمر ملقب بالثانی wrote:

doc = Hpricot( open(“http://del.icio.us/”) )
tags = doc.search(“//div.hotlist/ol/li”).inject({}) do | hash, entry |
link = entry.search(“h4/a”).first[‘href’]
hash[link] = entry.search(“div/ul/li/a”).inject([]) do | list, tag |
list << tag.inner_html
end
hash
end

i prefer

doc = Hpricot( open(“http://del.icio.us/”) )

tags =
doc.search(“//div.hotlist/ol/li”).inject({}) do | hash, entry |

 href = entry.search("h4/a").first['href']
 list = entry.search("div/ul/li/a").map{|tag| tag.inner_html}

 hash.update href => list

end

. use space to give meaning: a newline is one char
. use explicit var names as comments
. try to minimize method chaining so stacktraces to line #42 have
at least some meaning
. use hash.update with inject because it returns self

these things are religious i realize but, coming from perl, you
understand.

kind regards.

a @ http://codeforpeople.com/

ara.t.howard wrote:

foo.bar.foobar.barfoo.method

Surely the aim of all programming is to pack as much functionality as
possible into a single line of code. Everyone knows newlines are
horrendously expensive, so they should be used sparingly. :wink:

Dave

On Jul 12, 2008, at 3:36 PM, Dave B. wrote:

ara.t.howard wrote:

foo.bar.foobar.barfoo.method

Surely the aim of all programming is to pack as much functionality as
possible into a single line of code. Everyone knows newlines are
horrendously expensive, so they should be used sparingly. :wink:

I’ve found that my instantiating only a single newline and passing
around a reference has helped my coding style immensely!

TwP

Tim P. wrote:

I’ve found that my instantiating only a single newline and passing
around a reference has helped my coding style immensely!

And why not do away with \w+ method names, while we’re at it?

NEWLINE = “\n”

class Foo
define_method NEWLINE do
“bar”
end
define_method NEWLINE*2 do
“baz”
end
end

p Foo.new.send(NEWLINE)
p Foo.new.send(NEWLINE*2)

On Jul 12, 2008, at 3:54 PM, Tim P. wrote:

I’ve found that my instantiating only a single newline and passing
around a reference has helped my coding style immensely!

LOL!

a @ http://codeforpeople.com/

On Jul 12, 2008, at 3:54 PM, Tim P. wrote:

I’ve found that my instantiating only a single newline and passing
around a reference has helped my coding style immensely!

http://drawohara.com/post/42041039/ive-found-that-my-instantiating-only-a-single

a @ http://codeforpeople.com/