Scope problem (?) in implementing Design Patterns in Ruby

R

Ryan Davis

I'm hoping that employing "Design Patterns in Ruby" will lead to less
coding errors and more easily maintained code. I'm stuck with the Not
pattern in the File Finding pattern in Chapter 15.

Design patterns do not lead to less coding errors nor more easily =
maintained code.

Design patterns simply provide developers with a shared vocabulary to =
oft-used structures. It allows them to more easily communicate. If =
you're coding in a vacuum it won't help (from that perspective).

Not to say that it isn't worthwhile to read more code. That's always =
worthwhile.
 
7

7stud --

RichardOnRails wrote in post #998460:
I have only one question: I put a space between the & and the method
following it; the code broke. Is the construct you used documented on-
line somewhere? I've peeked at lambda documentation so I've got the
drift but I haven't used it in any of my code so far.

Your bible, "The Well-Grounded Rubyist" uses the &:meth_name construct a
lot, and David Black says that the '&' in '&:meth_name' does two things:

1) It calls the specified object's to_proc() method. And Symbol#to_proc
is defined like this:

class Symbol
def to_proc
proc{|obj, *args| obj.send(self, *args)}
#self=:meth_name
end
end

That just creates a function that takes an object as an argument and
sends() the :meth_name to the object, i.e. the function calls the
:meth_name method on the object.

2) The '&' tells ruby to convert the Proc to a block.
 
R

RichardOnRails

[Note:  parts of this message were removed to make it a legal post.]

Hi Richard,

The & has to be adjacent to "all" or "filename" to act as expected. The &
can mean one of two related things when you pass it to a method:

1. It can mean "pass the lambda expression that this variable points to into
a block". That makes the following to snippets equivalent:

# Snippet 1
filter_function = lambda {|x| x == 2 }
[1, 2, 3, 4, 2].select &filter_function

# Snippet 2
[1, 2, 3, 4, 2].select {|x| x == 2 }

2. It can mean "pass the instance method named by a symbol, and treat it as
a block".

That makes these two equivalent:

# Snippet 1
[1, 2, 3, 4, 2].select {|x| x.even? }

# Snippet 2
[1, 2, 3, 4, 2].select(&:even?)

So what my code is doing is calling the all method, for example, and that
method's sole job is to return a lambda that can then be passed in per the
above. You don't have to wrap the lambda in a method like I did. You could
also just say:

all = lambda {|x| x }

I hope that makes things a little clearer!

Cheers,
David
I checked out your Version 2.  Added puts stuff and restriction to
names of files, which should probably be another one of your methods
instead of my hard-coding.
Expanded code:http://www.pastie.org/1895917
Output:http://www.pastie.org/1895932
I have only one question: I put a space between the & and the method
following it; the code broke.  Is the construct you used documented on-
line somewhere?  I've peeked at lambda documentation so I've got the
drift but I haven't used it in any of my code so far.
I copied your memo on the approach and plan to review it and use/
expand your code after I finish getting Russ Olson's code working or
giving up on it.  To his credit,  he posted his code on-line so I can
avoid typos and he included an apparently thorough set of unit tests.
So I've got a lot of studying to do.
Again,  thanks for your guidance and great ideas,
Richard

Hi again, Dave,
I hope that makes things a little clearer!

Crystal! as Kaffee said to Col. Jessep during their Gitmo meeting (A
Few Good Men)

Thanks for illuminating another area of Ruby where my proficiency
needs enhancement :)

Best,
Richard
 
S

Steve Klabnik

[Note: parts of this message were removed to make it a legal post.]
1) It calls the specified object's to_proc() method. And Symbol#to_proc
is defined like this:

Small note, and some history:

This was originally introduced in ActiveSupport, where that was in fact the
definition. But performance was terrible. It was added to 1.8.7 & 1.9, but
is implemented in C, and is a bit more efficient. The semantics are the same
though.
 
R

RichardOnRails

RichardOnRails wrote in post #998460:




Your bible, "The Well-Grounded Rubyist" uses the &:meth_name construct a
lot, and David Black says that the '&' in '&:meth_name' does two things:

1) It calls the specified object's to_proc() method.  And Symbol#to_proc
is defined like this:

class Symbol
  def to_proc
    proc{|obj, *args| obj.send(self, *args)}
    #self=:meth_name
  end
end

That just creates a function that takes an object as an argument and
sends() the :meth_name to the object, i.e. the function calls the
:meth_name method on the object.

2) The '&' tells ruby to convert the Proc to a block.

Hi 7stud,

I just your the response you posted a week of two ago, for which I am
grateful
Your bible, "The Well-Grounded Rubyist" uses the &:meth_name construct a
lot, and David Black says that...

I had looked at the indices of several books for a reference to the
prefix &, to no avail. So I abandoned that idea and thus never
checked Black's book.

Thanks to your note, I see that Black has indexed two dense sections
related to the prefixed &, so I've got them on my To-Do list for
study.

Thanks again for taking the trouble to directing me to Black's
coverage.

Best wishes,
Richard
 
R

RichardOnRails

Second, look into higher order functions. They let you change code from this:

Hi Dave,

I just want to let you know your tutelage on this thread has not gone
in vain.

1. I wanted to return a list (i.e. array) of filenames rather than
concatenated strings. Maybe parsing the concatenated strings would
have gotten me my lists, but I want the arrays to be the direct output
(in part just to see if I understood your code well enough to do it.)

2. I wanted to do it by passing a search pattern to Filename.new and
a directory to the related expression.

These changes are displayed at http://www.pastie.org/1969301

I'm continuing to work on embracing the higher-order methods you
advocated.

Best wishes,
Richard
 
D

David Jacobs

Hi Richard,

Glad the advice helped!

Probably a more concise (and robust) way to get the full pathname of your Dir[] results would be:

full_name = File.expand_path(path)

This has the advantage of expanding '~' to '/home/richard' (or whatever).

If you add in higher order functions *here* (I'm just saying this to reinforce the earlier concept along with the above method), you go from this:

array = []
Dir.chdir(dir) do
Dir['**/*'].each do |path| # Added each & block
full_name = File.join(dir, path)
array << path
end
end
array

To this:

Dir.chdir(dir) do
Dir['**/*'].map {|path| File.expand_path(path) }
end
On Tuesday, 24 May 2011 at 11:35 pm, RichardOnRails wrote:
 
R

RichardOnRails

Hi Richard,

Glad the advice helped!

Probably a more concise (and robust) way to get the full pathname of yourDir[] results would be:

full_name = File.expand_path(path)

This has the advantage of expanding '~' to '/home/richard' (or whatever).

If you add in higher order functions *here* (I'm just saying this to reinforce the earlier concept along with the above method), you go from this:

array = []
Dir.chdir(dir) do
Dir['**/*'].each do |path|  # Added each & block
 full_name = File.join(dir, path)
 array << path
end
end
array

To this:

Dir.chdir(dir) do
Dir['**/*'].map {|path| File.expand_path(path) }
endOn Tuesday, 24 May 2011 at 11:35 pm, RichardOnRails wrote:

I just want to let you know your tutelage on this thread has not gone
in vain.
1. I wanted to return a list (i.e. array) of filenames rather than
concatenated strings. Maybe parsing the concatenated strings would
have gotten me my lists, but I want the arrays to be the direct output
(in part just to see if I understood your code well enough to do it.)
2. I wanted to do it by passing a search pattern to Filename.new and
a directory to the related expression.
These changes are displayed athttp://www.pastie.org/1969301
I'm continuing to work on embracing the higher-order methods you
advocated.
Best wishes,
Richard

Hi David,

Thanks for your additional improvement. Shrinking 8 lines down to 3
reduces the likelihood of error 62.5% I'd say. I like those odds|

I'm presently going through David Black's treatise as fast as I can
internalize the stuff. Specifically, I just found out the the number
of Enumerable methods went from 26 to 47 as I switched my WindowsXP-
Pro's PATH from Ruby 1.8.6 to 1.9.2. I just ran into a minor problem
that I'm going to post on a separate thread because I don't want
presume to hang on your coat-tails.

Best wishes,
Richard
 

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,755
Messages
2,569,537
Members
45,024
Latest member
ARDU_PROgrammER

Latest Threads

Top