inject idiom

  • Thread starter عمر ملقب بالثانی
  • Start date
Ø

عمر ملقب بالثانی

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.
 
G

GOTO Kentaro

SGkgw5ZtZXIsCgpPbiBTYXQsIEp1bCAxMiwgMjAwOCBhdCAzOjQ5IEFNLCDYudmF2LEg2YXZhNmC
2Kgg2KjYp9mE2KvYp9mG24wKPGJvcmRlbGVudG91dGdlbnJlQGdvb2dsZW1haWwuY29tPiB3cm90
ZToKPiBJIHdvbmRlciB3aGF0IHRoZSBiZXN0IHByYWN0aWNlIGlzPyBUaGUgbW9zdCByZWFkYWJs
ZSBhbmQgYmVzdCBzdWl0ZWQgdG8KPiBSdWJ5LXN0eWxlIG9mIHByb2dyYW1taW5nLiAgSW4gUGVy
bCwgYWx0aG91Z2ggdGhlcmUgaXMgbW9yZSB0aGFuIG9uZSB3YXkKPiB0byBkbyBldmVyeSB0aGlu
ZyB5b3Ugd2FudCwgdGhlcmUgYXJlIGRlZmluaXRlbHkgYmVzdCBwcmFjdGljZXMuIFdoYXQKPiBh
Ym91dCBSdWJ5PyBIb3cgZG8gb25lIHVzZSB0aGUgaW5qZWN0IGlkaW9tIGJlc3Q/CgpEbyB5b3Ug
bGlrZSB0aGlzPwoKZG9jID0gSHByaWNvdChvcGVuKCJodHRwOi8vZGVsLmljaW8udXMvIikpCnRh
Z3MgPSBkb2Muc2VhcmNoKCIvL2Rpdi5ob3RsaXN0L29sL2xpIikuaW5qZWN0KHt9KXt8aGFzaCxl
bnRyeXwKICBoYXNoW2VudHJ5LnNlYXJjaCgiaDQvYVsxXSIpLmZpcnN0WydocmVmJ11dID0KICAg
IGVudHJ5LnNlYXJjaCgiZGl2L3VsL2xpL2EvKiIpLnRvX2EKICBoYXNoCn0KCkkgc29tZXRpbWVz
IHdhbnQgYSBoYXNoIHNldHRlciBtZXRob2QgcmV0dXJuaW5nIHRoZSBoYXNoIGl0c2VsZjoKCmNs
YXNzIEhhc2gKICBkZWYgc2V0KGtleSwgdmFsdWUpCiAgICBzZWxmLnN0b3JlKGtleSwgdmFsdWUp
CiAgICByZXR1cm4gc2VsZgogIGVuZAplbmQKCgpIVEgsCgotLQpHb3Rva2VuCg==
 
A

ara.t.howard

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

i prefer

doc =3D Hpricot( open("http://del.icio.us/") )

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

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

hash.update href =3D> 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 =20
at least some meaning
. use hash.update with inject because it returns self

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

kind regards.

a @ http://codeforpeople.com/
 
Ø

عمر ملقب بالثانی

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 said:
Do you like this?
[...]

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

ara.t.howard said:
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 Programming 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.
 
A

ara.t.howard

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 said:
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.
 
D

Dave Bass

ara.t.howard said:
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. ;-)

Dave
 
T

Tim Pease

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. ;-)

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

TwP
 
J

Joel VanderWerf

Tim said:
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)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top