[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

how to be cool with map

Giles Bowkett

8/22/2007 6:54:00 PM

So I've got this file-checking script:

def check
ok = true
for_every_app do |app,app_info|
ok = File.exists?(app_info[:root])
end
ok
end

And it has a bug, which is that if it evaluates a good file after a
bad file, it'll return true for the whole list.

So here's my suggested change:

def check
ok = true
for_every_app.values.each do |app_info|
ok = File.exists?(app_info[:root]) if ok
end
ok
end

Because if we have one false value, then the whole test is
unnecessary. It's basically like a short-circuit operator.

But I think there's a better way to do it with map.

Something like

File.exists?(for_every_app.values.map{|x| x}

I think I'm way off, though. How do I get that right?

--
Giles Bowkett

Blog: http://gilesbowkett.bl...
Portfolio: http://www.gilesg...
Tumblelog: http://giles.t...

8 Answers

David A. Black

8/22/2007 7:02:00 PM

0

Erik Veenstra

8/22/2007 8:04:00 PM

0

Faster, because it breaks the loop as soon as possible, and
less LOC:

def check
for_every_app.values.find do |app_info|
not File.exists?(app_info[:root])
end ? false : true
end

You may want to skip the "? false : true" part, but that breaks
the encapsulation.

gegroet,
Erik V. - http://www.erikve...


Stefano Crocco

8/22/2007 8:31:00 PM

0

Alle mercoledì 22 agosto 2007, Erik Veenstra ha scritto:
> Faster, because it breaks the loop as soon as possible, and
> less LOC:
>
> def check
> for_every_app.values.find do |app_info|
> not File.exists?(app_info[:root])
> end ? false : true
> end
>
> You may want to skip the "? false : true" part, but that breaks
> the encapsulation.
>
> gegroet,
> Erik V. - http://www.erikve...

This is shorter, and breaks as soon as a non-existing file is found

def check
!for_every_app.values.any?{|f| !File.exist?(f)}
end

Stefano

Kaldrenon

8/22/2007 8:35:00 PM

0

On Aug 22, 2:54 pm, "Giles Bowkett" <gil...@gmail.com> wrote:
> So I've got this file-checking script:
>
> def check
> ok = true
> for_every_app do |app,app_info|
> ok = File.exists?(app_info[:root])
> end
> ok
> end
>
> And it has a bug, which is that if it evaluates a good file after a
> bad file, it'll return true for the whole list.
>
> So here's my suggested change:
>
> def check
> ok = true
> for_every_app.values.each do |app_info|
> ok = File.exists?(app_info[:root]) if ok
> end
> ok
> end
>
> Because if we have one false value, then the whole test is
> unnecessary. It's basically like a short-circuit operator.
>
> But I think there's a better way to do it with map.
>
> Something like
>
> File.exists?(for_every_app.values.map{|x| x}
>
> I think I'm way off, though. How do I get that right?
>
> --
> Giles Bowkett
>
> Blog:http://gilesbowkett.bl...
> Portfolio:http://www.gilesg...
> Tumblelog:http://giles.t...

How about inject?

for_every_app.inject(true) {|good,x| good = File.exists?(x) if good}

David A. Black

8/22/2007 8:55:00 PM

0

Kaldrenon

8/22/2007 9:06:00 PM

0

On Aug 22, 4:34 pm, Kaldrenon <kaldre...@gmail.com> wrote:
> On Aug 22, 2:54 pm, "Giles Bowkett" <gil...@gmail.com> wrote:
>
>
>
> > So I've got this file-checking script:
>
> > def check
> > ok = true
> > for_every_app do |app,app_info|
> > ok = File.exists?(app_info[:root])
> > end
> > ok
> > end
>
> > And it has a bug, which is that if it evaluates a good file after a
> > bad file, it'll return true for the whole list.
>
> > So here's my suggested change:
>
> > def check
> > ok = true
> > for_every_app.values.each do |app_info|
> > ok = File.exists?(app_info[:root]) if ok
> > end
> > ok
> > end
>
> > Because if we have one false value, then the whole test is
> > unnecessary. It's basically like a short-circuit operator.
>
> > But I think there's a better way to do it with map.
>
> > Something like
>
> > File.exists?(for_every_app.values.map{|x| x}
>
> > I think I'm way off, though. How do I get that right?
>
> > --
> > Giles Bowkett
>
> > Blog:http://gilesbowkett.bl...
> > Portfolio:http://www.gilesg...
> > Tumblelog:http://giles.t...
>
> How about inject?
>
> for_every_app.inject(true) {|good,x| good = File.exists?(x) if good}

I guess this would be for_every_app.values.inject(true) {|good,x| good
= File.exists?(x) if good}

But I think the idea was clear.

Stefano Crocco

8/22/2007 9:17:00 PM

0

Alle mercoledì 22 agosto 2007, David A. Black ha scritto:
> You can save yourself the double negative:
>
>    for_every_app.values.all?{|f| File.exist?(f)}
>
> And even save the creation of an intermediate array of values:
>
>    for_every_app.all?{|a,b| File.exist?(b)}
>
> But I repeat myself :-)  (See my earlier post.)
>
>
> David

You're right. Somehow, I thought that all? needed to iterate over all the
values and any? didn't. Of course, now I realized that, just as any? will
stop at the first positive result, all? will stop at the first negative
result.

Stefano

ara.t.howard

8/23/2007 5:42:00 PM

0


On Aug 22, 2007, at 12:54 PM, Giles Bowkett wrote:

> So I've got this file-checking script:
>
> def check
> ok = true
> for_every_app do |app,app_info|
> ok = File.exists?(app_info[:root])
> end
> ok
> end

this sends alarm bells ringing to me. i would expect, from that
small sample of code, that i could do

a_ok = apps.all?{|app| app.info.root.exist?}

which is to say apps is a method or collection, an app knows it's
info, an info object knows it's root, and that root is a Pathname
object so therefore has an exist method. which would obviate the
need for a method ;-)

2cts.

a @ http://draw...
--
we can deny everything, except that we have the possibility of being
better. simply reflect on that.
h.h. the 14th dalai lama