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 M. wrote:

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,

    # 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

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

Just Another Victim of the Ambient M. wrote:

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

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 Jul 6, 2006, at 7:53 AM, Just Another Victim of the Ambient
Morality wrote:

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

end

Is there a better way to do this?

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

2006/7/6, Elliot T. [email protected]:

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

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

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

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

On 7/7/06, Jeff P. [email protected] wrote:

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,

converting the tabs into single spaces.
help with it…
end

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

preferred way is to use {} for blocks that are all on one line, and do -
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