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.

···

--
Posted via http://www.ruby-forum.com/.

Hi Ömer,

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/&quot;\))
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,

···

On Sat, Jul 12, 2008 at 3:49 AM, عمر ملقب بالثانی <bordelentoutgenre@googlemail.com> wrote:

--
Gotoken

i prefer

doc = Hpricot( open("http://del.icio.us/&quot;\) )

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/

···

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

doc = Hpricot( open("http://del.icio.us/&quot;\) )
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

--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama

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

···

--
Posted via http://www.ruby-forum.com/\.

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/

···

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.

--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama

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.

···

--
Posted via http://www.ruby-forum.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

···

--
Posted via http://www.ruby-forum.com/\.

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

TwP

···

On Jul 12, 2008, at 3:36 PM, Dave Bass 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:

Tim Pease 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!

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:36 PM, Dave Bass wrote:

--
       vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

LOL!

a @ http://codeforpeople.com/

···

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

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

--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama

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

a @ http://codeforpeople.com/

···

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

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

--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama