def print_numbers()
[1, 2, 3, 4, 5, 6].map { |n|
[n * n, n * n * n]
}.reject { |square, cube|
square == 25 || cube == 64
}.map { |square, cube|
cube
}.each { |n|
puts n
}
end
This strikes me as a terrible example. For example, this is
significantly clearer:
def print_numbers()
for n in [1,2,3,4,5,6]:
square, cube = n * n, n * n * n
if square != 25 and cube != 64:
print n
This is not an exact translation. My example prints the cubes. It is
my fault for using "n" as the parameter in the last block. I would
rename the parameter to cube.
I /can/ see arguments for ruby style blocks in python, but not for
this sort of thing, or lisp style quoted expressions[1]. ie I can see
situations where you have more complex code in real life where they
will definitely simplify things.
[1] This is perhaps more appropriate because '(a b c) is equivalent
to (quote a b c), and quote a b c can be viewed as close to
python's expression "lambda: a b c"
However, I can also see that in simple situations - such as the
example you post - they will have a tendency to make code
significantly less clear/direct.
I suppose, if I have a choice between something (hard being possible &
simple code looking simple) and (hard things being simpler & simple
things looking harder), I'd probably personally choose the former.
This is not because I don't like hard things being simple, but because
I think that simple things are more common and making them look harder
is a mistake.
I agree with much of what you are saying. The example is indeed
terribly contrived.
I'm not sure I agree that there is anything unclear or undirect about
the Ruby, though. I've been fairly immersed in Ruby code, so maybe
it's been warping my brain, but once you get over the unfamiliarity of
the syntax, you see that there's actually a rhythm to the code.
Setting aside punctuation and parameter lists, the code clearly
expresses the transformations and actions in the natural order that
you'd do them:
LIST map
expression
reject
criteria
map
expression
each
statement
In English, for the list elements, map them to tuples of squares and
cubes, reject the oddballs, take the cube, and print it out.
[1, 2, 3, 4, 5, 6].map { |n|
[n * n, n * n * n]
}.reject { |square, cube|
square == 25 || cube == 64
}.map { |square, cube|
cube
}.each { |cube|
puts cube
}
For such a small problem, I agree it's verbose. But it's also
completely flat--you don't need to use an "if" statement to express
the concept of rejection.