Interesting talk on Python vs. Ruby and how he would like Python to have just a bit more syntactic f


S

sjdevnull

So there is no distinction between functions and procedures, then?

Not in most modern languages, no. i think the major places they are
differentiated are in functional languages and in pre-1993ish
languages (give or take a few years), neither of which applies to
Python or Ruby.
 
Ad

Advertisements

M

Michael Sparks

    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

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'm well aware that's opinion however,

Regards,


Michael.
 
S

Steve Howell

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

Lawrence D'Oliveiro

In message
Michael said:
[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"

You got to be kidding.
 
Ad

Advertisements

T

Timothy N. Tsvetkov

Gary's friend Geoffrey Grosenbach says in his blog post (which Gary
linked to): "Python has no comparable equivalent to Ruby’s do end
block. Python lambdas are limited to one line and can’t contain
statements (for, if, def, etc.). Which leaves me wondering, what’s the
point?"

I'm sorry, lambda's do support if's and for's. Also, lambda's are
expressions, not statements, but you can pass them around, keep them
in a dictionary if you want to. And if you need more than one line of
statements, for crying out loud use a def? And who needs those "do-
end" blocks anyway, trying to turn Python into Pascal?

I think there are some nice use-cases for anonymous functions /
blocks. First, mentioned above, is pretty DSL. And the second is using
blocks in map/reduce functions. Yes, you can pass there a function but
I believe that in most situations it is more readable to pass a
multiline anonymous function / block than defined somewhere function
written only for a single map/reduce operation. And often when you use
reduce it is a bit more complicated then just one line function.
 

Top