A newbie would like some code criticism, please

I'm learning Ruby and I'd like some criticism on a program that I wrote.
It interfaces with iTunes and runs through all the songs, (reasonably)
ensuring proper title capitalization. It's a small program and I would have
simply posted except that, for some unknown reason, MS Outlook Express keeps
converting the tabs into single spaces.
    I'm open to comments on style versus what is standard protocol for the
Ruby community, as well.
    I hope the program may be as useful to any of you as it is for me...

http://theorem.ca/~dlkong/iTunes_title_filter.rb.gz

    There's also a pattern that often comes up for me and I would like some
help with it...

first = true
list.each do |item|
    if first
        # do something special for the first case

        first = false
    else
        # do something else for every other item
    end
end

    Is there a better way to do this? Perhaps some way to simply iterate
over every element other than the first one? Something that avoid a check
every iteration?

    Thank you...

Just Another Victim of the Ambient Morality wrote:

first = true
list.each do |item|
    if first
        # do something special for the first case

        first = false
    else
        # do something else for every other item
    end
end

    Is there a better way to do this? Perhaps some way to simply iterate over every element other than the first one? Something that avoid a check every iteration?

There are several ways of doing this:

   list.each_with_index do |item, i|
     if i == 0
       # first item
     else
       # not the first item
     end
   end

Though it's not very pretty

   # returns the first item and removes it
   # from the array
   list.shift

   list.each do |item|
     # the rest of the items
   end

Note that this alters `list'! The following won't:

   # returns the first item, keeps it in
   # the array
   list.first

   ary[1...ary.length].each do |item|
     # all but the first item
   end

I'm sure there are even more ways of doing it.

Cheers,
Daniel

Hi,

    There's also a pattern that often comes up for me and I would like some
help with it...

first = true
list.each do |item|
    if first
        # do something special for the first case

        first = false
    else
        # do something else for every other item
    end
end

    Is there a better way to do this? Perhaps some way to simply iterate
over every element other than the first one? Something that avoid a check
every iteration?

If you don't mind clobbering 'list':

do_something_for_first(list.shift)
list.each do |item|
  do_something_else(item)
end

or if you can't alter list, how about:

do_something_for_first(list[0])
list[1..-1].each do |item| ...

When faced with problems like that I find it handy to fire up irb and
just try different things until the solution emerges. It also helps to
have the pages for 'Enumerable' and 'Array' bookmarked in Programming
Ruby.

Jon

Just Another Victim of the Ambient Morality wrote:

    I'm learning Ruby and I'd like some criticism on a program that I wrote. It interfaces with iTunes and runs through all the songs, (reasonably) ensuring proper title capitalization. It's a small program and I would have simply posted except that, for some unknown reason, MS Outlook Express keeps converting the tabs into single spaces.
    I'm open to comments on style versus what is standard protocol for the Ruby community, as well.
    I hope the program may be as useful to any of you as it is for me...

http://theorem.ca/~dlkong/iTunes_title_filter.rb.gz

    There's also a pattern that often comes up for me and I would like some help with it...

first = true
list.each do |item|
    if first
        # do something special for the first case

        first = false
    else
        # do something else for every other item
    end
end

    Is there a better way to do this? Perhaps some way to simply iterate over every element other than the first one? Something that avoid a check every iteration?

Sometimes also #inject will help but that depends on what you do in the block. For example:

irb(main):001:0> %w{aa bb cc dd}.inject {|a, b| a + ", " + b}
=> "aa, bb, cc, dd"

Other than that I'd probably stick with the solution that uses #each_with_index because it at least avoids creating a new array.

Kind regards

  robert

I'm trying to test the itunes code but can't get it to work?
Even the following script errors out:

#test itunes with ole
require 'win32ole'

itunes= WIN32OLE.new('iTunes.Application')
puts itunes.ole_methods

The error is:
C:\tools\scripts\test>ruby itunes.rb
itunes.rb:4:in `ole_methods': Failed to GetTypeInfo (RuntimeError)
    HRESULT error code:0x8002801d
      Library not registered. from itunes.rb:4

While ole works fine, because I can run:
require 'win32ole'

excel= WIN32OLE.new('excel.application')
puts excel.ole_methods
excel['Visible']=TRUE
wb = excel.Workbooks.Add()
sleep 10
excel.quit

Any ideas?
-Tim

    There's also a pattern that often comes up for me and I would like some
help with it...

first = true
list.each do |item|
    if first
        # do something special for the first case

        first = false
    else
        # do something else for every other item
    end
end

    Is there a better way to do this? Perhaps some way to simply iterate
over every element other than the first one? Something that avoid a check
every iteration?

I usually add a couple of methods to Array to facilitate such things,
named after funcs from my ol' ML days:

class Array
   def head
      first
   end
   def tail
      self[1..-1]
   end
end

list.head.do_something_special
list.tail.each do |item|
   item.do_something_else
end

i'm not happy with the suggested solutions. i think the inject solution is OK when it works, and next best is each_with_index. but i think worrying about indexes is too low level when we don't actually want to deal with numbers. it's worse when you care about the last iteration and have to worry about off-by-one errors (you need to do something special on list.length-1) what might be nicer is either variable capture in loops (i guess that is rejected because it's too confusing?) or each_with_first_last (with a shorter name).

it'd work like:

list.each_with_first_last do |item, state|
   if state.first?
     #....
   elsif state.last?
     #...
   else
   #...
   end
end

does anyone have a good idea for what to name this?

also what order should the arguments be in? inject is memo,item and each_with_index is item,index...

-- Elliot Temple

···

On Jul 6, 2006, at 7:53 AM, Just Another Victim of the Ambient Morality wrote:

    There's also a pattern that often comes up for me and I would like some
help with it...

first = true
list.each do |item|
    if first
        # do something special for the first case

        first = false
    else
        # do something else for every other item
    end
end

    Is there a better way to do this?

Everybody else seems to be focusing on your "first, rest" question. You
also asked about general coding style and correctness...

I'm a newbie too, so take this with a grain of salt unless one of the
senior members agrees with me. The thing I found most notable about
your code overall was the use of { } for multi-line blocks. This is
certainly legal, but I think it is considered poor form, as I don't ever
see it in ruby code listed here or in books. As I understand it, the
preferred way is to use {} for blocks that are all on one line, and do -
end pair for multi-line blocks.

best,
jp

Just Another Victim of the Ambient Morality wrote:

···

I'm learning Ruby and I'd like some criticism on a program that I wrote.
It interfaces with iTunes and runs through all the songs, (reasonably)
ensuring proper title capitalization. It's a small program and I would
have
simply posted except that, for some unknown reason, MS Outlook Express
keeps
converting the tabs into single spaces.
    I'm open to comments on style versus what is standard protocol for
the
Ruby community, as well.
    I hope the program may be as useful to any of you as it is for me...

http://theorem.ca/~dlkong/iTunes_title_filter.rb.gz

    There's also a pattern that often comes up for me and I would like
some
help with it...

first = true
list.each do |item|
    if first
        # do something special for the first case

        first = false
    else
        # do something else for every other item
    end
end

    Is there a better way to do this? Perhaps some way to simply
iterate
over every element other than the first one? Something that avoid a
check
every iteration?

    Thank you...

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

Works for me. Not too helpful for your particular problem, but it does
narrow it down to your machine :frowning:

What version of ruby are you running? Have you tried using the
Windows OLE browser to find the iTunes OLE methods? The error looks
like something is wrong with the iTunes OLE bindings on your machine
and not the ruby win32 hooks.

I hate to even type this, but you might try reinstalling iTunes and
see if the problem goes away.

Blessings,
TwP

···

On 7/6/06, Tim Hoolihan <tim@hoolihan.net> wrote:

I'm trying to test the itunes code but can't get it to work?
Even the following script errors out:

#test itunes with ole
require 'win32ole'

itunes= WIN32OLE.new('iTunes.Application')
puts itunes.ole_methods

The error is:
C:\tools\scripts\test>ruby itunes.rb
itunes.rb:4:in `ole_methods': Failed to GetTypeInfo (RuntimeError)
    HRESULT error code:0x8002801d
      Library not registered. from itunes.rb:4

While ole works fine, because I can run:
require 'win32ole'

excel= WIN32OLE.new('excel.application')
puts excel.ole_methods
excel['Visible']=TRUE
wb = excel.Workbooks.Add()
sleep 10
excel.quit

Any ideas?
-Tim

You might want to search the archives of ruby-talk - IIRC we had
several lenghty discussions about these kind of problems. I
personally didn't yet need these. And if, the boolean toggle is ok for
me.

Cheers

robert

···

2006/7/6, Elliot Temple <curi@curi.us>:

i'm not happy with the suggested solutions. i think the inject
solution is OK when it works, and next best is each_with_index. but i
think worrying about indexes is too low level when we don't actually
want to deal with numbers. it's worse when you care about the last
iteration and have to worry about off-by-one errors (you need to do
something special on list.length-1) what might be nicer is either
variable capture in loops (i guess that is rejected because it's too
confusing?) or each_with_first_last (with a shorter name).

--
Have a look: Robert K. | Flickr

i think worrying about indexes is too low level when we don't actually want to deal with
numbers.

I agree.

It's an Interesting problem. I came up with the following way, but
it's sort of ugly. Too bad there isn't a syntax for calling methods
w/ multiple blocks.

class Array
  def borders(head = nil, tail = nil, &block)
    a = self.dup
    if head
      head[a.shift]
    end
    if tail
      t = a.pop
    end
    a.each &block
    if tail
      tail[t]
    end
  end
end

You just give optional blocks for what to do on the first and last
iterations. Actually it would probably be better if you specified
them by keyword, but it's already ugly enough as is =)

x = [1,2,3,4,5,6,7]

x.borders(
  lambda do |h|
    puts h * 10
  end,
  lambda do |t|
    puts t + 3
  end) do |i|
    puts i
end

···

--
Lou.

Tim Hoolihan wrote:

The error is:
C:\tools\scripts\test>ruby itunes.rb
itunes.rb:4:in `ole_methods': Failed to GetTypeInfo (RuntimeError)
    HRESULT error code:0x8002801d
      Library not registered. from itunes.rb:4

To chime in with the other responses, it sounds like the iTunes.exe, or
whatever it's called, is not registered as automation server on your
machine. You might try logging into the directory where the executable
is installed, and running the following command line:

  iTunes.exe /regserver

···

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

Everybody else seems to be focusing on your "first, rest" question. You
also asked about general coding style and correctness...

I'm a newbie too, so take this with a grain of salt unless one of the
senior members agrees with me. The thing I found most notable about
your code overall was the use of { } for multi-line blocks. This is
certainly legal, but I think it is considered poor form, as I don't ever
see it in ruby code listed here or in books. As I understand it, the
preferred way is to use {} for blocks that are all on one line, and do -
end pair for multi-line blocks.

Honestly I do not think so, personally I prefer do..end to {..} unless {..}
looks prettier.
I too see a tendency to use {} on short blocks but would not go so far to
say that e.g.

File.open(__FILE__)' {
    >f>
    f.each {
    ...
    }
}

is bad or even uncommon practice.
The liberty to use do...end or {} is given on purpose.

Cheers
Robert

best,

···

On 7/7/06, Jeff Pritchard <jp@jeffpritchard.com> wrote:

jp

Just Another Victim of the Ambient Morality wrote:
> I'm learning Ruby and I'd like some criticism on a program that I wrote.
> It interfaces with iTunes and runs through all the songs, (reasonably)
> ensuring proper title capitalization. It's a small program and I would
> have
> simply posted except that, for some unknown reason, MS Outlook Express
> keeps
> converting the tabs into single spaces.
> I'm open to comments on style versus what is standard protocol for
> the
> Ruby community, as well.
> I hope the program may be as useful to any of you as it is for me...
>
> http://theorem.ca/~dlkong/iTunes_title_filter.rb.gz
>
> There's also a pattern that often comes up for me and I would like
> some
> help with it...
>
> first = true
> list.each do |item|
> if first
> # do something special for the first case
>
> first = false
> else
> # do something else for every other item
> end
> end
>
> Is there a better way to do this? Perhaps some way to simply
> iterate
> over every element other than the first one? Something that avoid a
> check
> every iteration?
>
> Thank you...

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

--
Deux choses sont infinies : l'univers et la bêtise humaine ; en ce qui
concerne l'univers, je n'en ai pas acquis la certitude absolue.

- Albert Einstein

Hi --

···

On Sat, 15 Jul 2006, Robert Dober wrote:

On 7/7/06, Jeff Pritchard <jp@jeffpritchard.com> wrote:

Everybody else seems to be focusing on your "first, rest" question. You
also asked about general coding style and correctness...

I'm a newbie too, so take this with a grain of salt unless one of the
senior members agrees with me. The thing I found most notable about
your code overall was the use of { } for multi-line blocks. This is
certainly legal, but I think it is considered poor form, as I don't ever
see it in ruby code listed here or in books. As I understand it, the
preferred way is to use {} for blocks that are all on one line, and do -
end pair for multi-line blocks.

Honestly I do not think so, personally I prefer do..end to {..} unless {..}
looks prettier.
I too see a tendency to use {} on short blocks but would not go so far to
say that e.g.

File.open(__FILE__)' {
  >f>
  f.each {
  ...
  }
}

is bad or even uncommon practice.

I think putting |f| on its own line is uncommon, and kind of
odd-looking, though it will certainly work.

David

--
http://www.rubypowerandlight.com => Ruby/Rails training & consultancy
Ruby for Rails => RUBY FOR RAILS (reviewed on
                                     Slashdot, 7/12/2006!)
http://dablog.rubypal.com => D[avid ]A[. ]B[lack's][ Web]log
dblack@wobblini.net => me