Confessions of a Python fanboy

R

r

Hello fellow Pythonista's it's nice to be back after such a long
hiatus. I have recently realized my blind love affair with Python was
just that. I must admit there are better ways to program. Like your
first lay, your first programing language can leave an indelible mark
on you, but like all young chaps, the passion for programming has
sweep me away into vast new orgies of programming bliss. (ig ,little
head guides the big one.)

My adventures in Ruby.
an autobyography by rt8396

After breaking free from the wild love affair i had with Python, a new
day had dawned. I dried my eyes and soon discovered the Ruby language
(not by choice however) --now don't worry fellow Pythonistas, i am
still on your side (mostly) -- but i now realize Ruby has some good
things going for it. For instance...

1.) No need to use "()" to call a function with no arguments.
Python --> "obj.m2().m3()" --ugly
Ruby --> "obj.m1.m2.m3" -- sweeet!
Man, i must admit i really like this, and your code will look so much
cleaner.

2.) the .each method
container.each{|localVar| block}
This method can really cleanup some ugly for loops, although i really
like the readability of for loops.

3.) true OOP
Now before you go and get all "huffy" over this statement, hear me
out. Python is the best language in the world. But it damn sure has
some warts! "len(this)" instead of "obj.length" max(that) instead of
[1,2,3,4,5].max(). You know what i am talking about here people. We
all get complacent and It seems easier to just cope with these
problems instead of fighting for change. But look at the French, WHAT
THE HELL HAS THAT DONE FOR THEM, *NOTHING*!!!!

As for the rest of Ruby, i am not impressed. The redundant usage of
"end" over indention perplexes me. The Perlish feel of "require" and
the horrifically cryptic idioms of Ruby regular expressions. The
"puts" and "gets" seem childish and the math class does not even have
a degrees or radians function!

Anyway, i thought i would get this off my chest and catch up with old
friends in the meantime. We can all make Python the perfect language
it needs to be, but it ain't gonna be easy!
Thank you all

PS stay tuned for more from this series....
 
A

alex23

1.) No need to use "()" to call a function with no arguments.
Python --> "obj.m2().m3()" --ugly
  Ruby --> "obj.m1.m2.m3"  -- sweeet!
Man, i must admit i really like this, and your code will look so much
cleaner.

How do you distinguish between calling a method with no arguments, and
getting access to the method object itself (because it _is_ an object,
y'know, it's OO all the way down...)?
2.) the .each method
container.each{|localVar| block}
This method can really cleanup some ugly for loops, although i really
like the readability of for loops.

map(lambda localVar: <block>, sequence)

or:

def usefully_named_func(var):
<block>
return var

transformed = [usefully_named_func(v) for v in sequence]
3.) true OOP
Now before you go and get all "huffy" over this statement, hear me
out. Python is the best language in the world. But it damn sure has
some warts! "len(this)" instead of "obj.length" max(that) instead of
[1,2,3,4,5].max().

As the Zen says: '[P]racticality beats purity'. Personally, I'm not
sure how a handful of convenient built-in functions make a language in
which _everything is an object_ somehow "false" OO.

If you're really that concerned with writing "true" OO (for some
wildly variable value of "true"), there's nothing stopping you from
doing so now:

obj.__len__()

With max(), this is a built-in that takes _any_ iterable and an
optional key function, and returns the highest value as per the key.
This means that _every_ iterable object - as _well_ as every object
that supports enough of the iterator protocol - can be handed to max()
and a result obtained. So at best, I just need to make sure my new
sequence-type provides the iterator protocol and viola, it works with
max() without me having to hand-code a .max() that's specialised for
my new type, and without Python forcing me to have a complex
inheritance chain just to make sure I include the right
MaxableSequence ancestor to inherit the right .max().
PS stay tuned for more from this series....

Is this going to be more of you telling us - without any apparent
irony whatsoever - how Ruby has some valid points after all your
vilification last year when we said the same to you? If so, where can
I sign up?!

(You should consider trading guest spot posts with Xah Lee on your
respective blogs. You both have a very similar approach to programming
& programming languages and I think the synergy would be amazing to
see.)
 
C

Chris Rebert

How do you distinguish between calling a method with no arguments, and
getting access to the method object itself (because it _is_ an object,
y'know, it's OO all the way down...)?

IIRC from the Pickaxe, to get at a method object, you call a method on
the object whose specific job it is to return method objects.
Unsurprisingly, this method is itself named "method". So:

foo.bar #calls the "bar" method on foo
foo.method:)bar) #returns the method "bar" of foo, as an object

Cheers,
Chris
 
C

Carl Banks

1.) No need to use "()" to call a function with no arguments.
Python --> "obj.m2().m3()" --ugly
  Ruby --> "obj.m1.m2.m3"  -- sweeet!
Man, i must admit i really like this, and your code will look so much
cleaner.

How do you distinguish between calling a method with no arguments, and
getting access to the method object itself (because it _is_ an object,
y'know, it's OO all the way down...)?
2.) the .each method
container.each{|localVar| block}
This method can really cleanup some ugly for loops, although i really
like the readability of for loops.

map(lambda localVar: <block>, sequence)

or:

def usefully_named_func(var):
    <block>
    return var

transformed = [usefully_named_func(v) for v in sequence]
3.) true OOP
Now before you go and get all "huffy" over this statement, hear me
out. Python is the best language in the world. But it damn sure has
some warts! "len(this)" instead of "obj.length" max(that) instead of
[1,2,3,4,5].max().

As the Zen says: '[P]racticality beats purity'. Personally, I'm not
sure how a handful of convenient built-in functions make a language in
which _everything is an object_ somehow "false" OO.

If you're really that concerned with writing "true" OO (for some
wildly variable value of "true"), there's nothing stopping you from
doing so now:

    obj.__len__()

With max(), this is a built-in that takes _any_ iterable and an
optional key function, and returns the highest value as per the key.
This means that _every_ iterable object - as _well_ as every object
that supports enough of the iterator protocol - can be handed to max()
and a result obtained. So at best, I just need to make sure my new
sequence-type provides the iterator protocol and viola, it works with
max() without me having to hand-code a .max() that's specialised for
my new type, and without Python forcing me to have a complex
inheritance chain just to make sure I include the right
MaxableSequence ancestor to inherit the right .max().
PS stay tuned for more from this series....

Is this going to be more of you telling us - without any apparent
irony whatsoever - how Ruby has some valid points after all your
vilification last year when we said the same to you?  If so, where can
I sign up?!

(You should consider trading guest spot posts with Xah Lee on your
respective blogs. You both have a very similar approach to programming
& programming languages and I think the synergy would be amazing to
see.)

Here is some wisdom from Guido van Rossum on the matter:

http://mail.python.org/pipermail/python-dev/2006-May/064841.html


Carl Banks
 
M

Marco Mariani

r said:
My adventures in Ruby.

Oh, it's you.
Good boy.
Now, why don't you have a look at javascript and come back in six months?
Or better yet, haskell and twelve months.

thanks
 
J

Jean-Michel Pichavant

superpollo said:
Masklinn wrote:
...
...
how would you correct a newbie (like me) who says:

"well, the main difference between a function and a method (from the
caller's pow) is a syntactic one:

fun(obj, arguments)

as opposed to:

obj.met(arguments)

but the effect is just about the same."

?

bye

My suggestion

- OO programming:
length(foo) calls the foo instance(or class for some language) length method
length(bar) calls the bar instance length method, it is **not** the same
than the foo method

- non OO programming:
length(foo) calls the length function with foo as parameter
length(bar) calls the **same** length function with the bar parameter
(so you better make sure length is handling both foo and bar)

So the difference is definitely **not** a syntactic one, but it is true
that the syntax obj.method() better illustrates the bind mechanism of
the OO programming.

JM
 
M

Masklinn

Masklinn wrote:
...
...
how would you correct a newbie (like me) who says:

"well, the main difference between a function and a method (from the
caller's pow) is a syntactic one:

fun(obj, arguments)

as opposed to:

obj.met(arguments)

but the effect is just about the same."

?
Depending on the way things are implemented, it can be very similar
(see CLOS' generic functions, which have the same look as functions
but dispatch based on parameter types).

In Python, the difference would be that functions don't automatically
dispatch (you have a function for everybody, and any dispatch you
perform based on argument types or other qualifiers has to be done
manually) whereas methods do dispatch on the first [implied] argument
(you execute a precise method corresponding to the object it's being
called on).

So fun(obj, *arguments) will call the same `fun` whether `obj` is an
int, a string or an HTTPFactory whereas obj.met(*arguments) will call
a different `met` each time (they all have the same "unqualified" name
[and signature if it's part of a protocol], but might very well be
implemented completely differently). Therefore -- in python -- the
effect isn't anywhere "just about the same".
 
C

Colin J. Williams

Some have treated this as a troll. I don't.
r wrote:
[snip]
1.) No need to use "()" to call a function with no arguments.
Python --> "obj.m2().m3()" --ugly
Ruby --> "obj.m1.m2.m3" -- sweeet!
Man, i must admit i really like this, and your code will look so much
cleaner.
+1
2.) the .each method
container.each{|localVar| block}
This method can really cleanup some ugly for loops, although i really
like the readability of for loops.
Not clear.
3.) true OOP
Now before you go and get all "huffy" over this statement, hear me
out. Python is the best language in the world. But it damn sure has
some warts! "len(this)" instead of "obj.length" max(that) instead of
[1,2,3,4,5].max(). You know what i am talking about here people. We
all get complacent and It seems easier to just cope with these
problems instead of fighting for change. But look at the French, WHAT
THE HELL HAS THAT DONE FOR THEM, *NOTHING*!!!!
+0.6
or better [1, 2, 3, 4, 5].len or [1, 2, 3, 4, 5].max

What has this got to do with "true OOP"?

[snip]
 
F

Falcolas

1.) No need to use "()" to call a function with no arguments.
Python --> "obj.m2().m3()" --ugly
  Ruby --> "obj.m1.m2.m3"  -- sweeet!
Man, i must admit i really like this, and your code will look so much
cleaner.

I personally would not prefer this, and would likely continue to use
(), precisely for code clarity - let me explain:

foo.nextval
foo.val
foo.previousval

Which of the calls above referenced instance variables, and which ones
called functions which changed the internal state of foo? I would have
trouble saying, just based on the calls above. I would have to go back
to the definition or documentation of foo to identify which is doing
what. On the other hand, the following gives a better clue as to what
is happening (granted not perfect, but better):

foo.nextval()
foo.val
foo.previousval()

~G
 
I

Inky 788

How do you distinguish between calling a method with no arguments, and
getting access to the method object itself (because it _is_ an object,
y'know, it's OO all the way down...)?

I agree with alex here. Will take the explicit syntax over the extra
cognitive load of figuring out exactly what's going on with
`obj.m1.m2.m3`.

Python has its warts, but requiring ()'s on function calls isn't one
of them. :)
 
R

r

I personally would not prefer this, and would likely continue to use
(), precisely for code clarity - let me explain:

foo.nextval
foo.val
foo.previousval

Which of the calls above referenced instance variables, and which ones
called functions which changed the internal state of foo? I would have
trouble saying, just based on the calls above. I would have to go back
to the definition or documentation of foo to identify which is doing
what. On the other hand, the following gives a better clue as to what
is happening (granted not perfect, but better):

foo.nextval()
foo.val
foo.previousval()

~G

I held your exact same view before i learned the Ruby language. And
your veiw makes some good points, however, naming conventions with
eliminate this problem all together. All "method names" should use the
underscore to separate words, "variable names" should use camelCase,
"constants" in all caps, and "class defs" in titlecase.

def go_and_do_this_for_me_now(self, *args)
self.variableNameHere
MyClassNameHere
THISISACONSTANT -or- THIS_IS_A_CONSTANT


in your example i would have used the following

foo.next_value
foo.value
foo.prev_value

good naming conventions will make your life (and everybody else's)
much easier when debugging code.
 
M

Masklinn

I personally would not prefer this, and would likely continue to use
(), precisely for code clarity - let me explain:

foo.nextval
foo.val
foo.previousval

Which of the calls above referenced instance variables
Well, that's very simple: none of them. In Ruby (as in Smalltalk),
public instance variables simply don't exist.
and which ones called functions which changed the internal state of
foo?
That you can't say, but neither can you say in Python as they could
all be properties. And of course just because it's a method doesn't
mean it mutates the object.
I would have
trouble saying, just based on the calls above. I would have to go back
to the definition or documentation of foo to identify which is doing
what. On the other hand, the following gives a better clue as to what
is happening (granted not perfect, but better):
Well... it doesn't give much of a clue no really.
 
M

Masklinn

I agree with alex here. Will take the explicit syntax over the extra
cognitive load of figuring out exactly what's going on with
`obj.m1.m2.m3`.
There's no cognitive load whatsoever: it's calling methods. Always.
Ruby simply gives you no other option. Now it could be very simple
methods to instance attributes, akin to a java getter, but it's still
only methods.

Furthermore Ruby has a pretty nice convention (sadly not used enough I
think) taken from Scheme where it's possible to postfix a method name
with "!" (note: the "!" is part of the name, there's no magic) to
indicate that this method modifies the object it's called on rather
than simply returning stuff.
 
R

r

Furthermore Ruby has a pretty nice convention (sadly not used enough I  
think) taken from Scheme where it's possible to postfix a method name  
with "!" (note: the "!" is part of the name, there's no magic) to  
indicate that this method modifies the object it's called on rather  
than simply returning stuff.

Another oddity i did not like at first but must admit is growing on me
vector.reverse --> returns a new reversed vector
vector.reverse! --> modifies the instance vector in-place

Of course in python you would do...
vector.reverse --> in-place
vector.reversed --> in-place

The above example works pretty good, but this doesn't always "sound"
good. Take for example this...
point3d.offset --> return a new pt
point3d.offseted --> What did you say!?!?!

Now try Ruby's way
point3d.offset!
point3d.offset

a symbol works better for these things
 
R

r

Traceback (most recent post last):
File "<Confessions of a Python Fanboy>", lines (13,14), in <post>
vector.reverse --> in-place
vector.reversed --> in-place
DumbMistakeError:

Of course in python you would do...
vector.reverse --> in-place
vector.reversed --> new vector
 
J

Jean-Michel Pichavant

r said:
I held your exact same view before i learned the Ruby language. And
your veiw makes some good points, however, naming conventions with
eliminate this problem all together. All "method names" should use the
underscore to separate words, "variable names" should use camelCase,
"constants" in all caps, and "class defs" in titlecase.

def go_and_do_this_for_me_now(self, *args)
self.variableNameHere
MyClassNameHere
THISISACONSTANT -or- THIS_IS_A_CONSTANT


in your example i would have used the following

foo.next_value
foo.value
foo.prev_value

good naming conventions will make your life (and everybody else's)
much easier when debugging code.
How do I know if foo.value is an attribute or if it is a method that
returns the foo value ? It seems you can make the difference only when
tokens are composed of more than one word, not very handy don't you think ?

Just feeding the troll.

JM
 
C

Carsten Haese

r said:
Of course in python you would do...
vector.reverse --> in-place
vector.reversed --> in-place

You do know that only one of those works in-place, right?
The above example works pretty good, but this doesn't always "sound"
good. Take for example this...
point3d.offset --> return a new pt
point3d.offseted --> What did you say!?!?!

Now try Ruby's way
point3d.offset!
point3d.offset

a symbol works better for these things

Or you could use a better verb:

point3d.move -> modifies in place
point3d.moved -> returns a new point

-Carsten
 
R

r

How do I know if foo.value is an attribute or if it is a method that
returns the foo value ? It seems you can make the difference only when
tokens are composed of more than one word, not very handy don't you think ?

Just feeding the troll.

JM

You can still use empty parenthesis in Ruby if that floats your boat.

obj.method() <-- note the empty parenthesis

I am just saying don't make them mandatory, thats all. In any case
where ambiguity abounds, by all means use the damn parenthisis.

Now Ruby will even let you call a method *that has arguments* with no
parenthisis -- however, i do not think this is a good idea. Consider
the following

Geom::Transformation.rotation pt, vec, ang
bad coder!, bad!
...and leads to worn out eyeball parsers in a hurry

Geom::Transformation.rotation(pt, vec, ang)
yes, good boy!
 
T

Tim Rowe

2009/7/30 r said:
Like your
first lay, your first programing language can leave an indelible mark
on you

That's true. FOCAL scarred me for life.
but i now realize Ruby has some good
things going for it.

Any language that gets any sort of real use has to have. For instance,
I love Ada's numeric types (you can specify either the minimum number
of significant figures or the maximum delta for a real type, and it
will give you a type that satisfies that -- or a compilation error if
it can't. That matches genuine problem domains far better than having
to remember how many bits in a double on this particular system, and
reduces portability bugs).
3.) true OOP
Now before you go and get all "huffy" over this statement, hear me
out. Python is the best language in the world. But it damn sure has
some warts! "len(this)" instead of "obj.length" max(that) instead of
[1,2,3,4,5].max(). You know what i am talking about here people. We
all get complacent and It seems easier to just cope with these
problems instead of fighting for change. But look at the French,  WHAT
THE HELL HAS THAT DONE FOR THEM, *NOTHING*!!!!

I seem to recall recent studies showing that the French were on
average happier than Brits or Americans. Don't knock it!
As for the rest of Ruby, i am not impressed. The redundant usage of
"end" over indention perplexes me. The Perlish feel of "require" and
the horrifically cryptic idioms of Ruby regular expressions. The
"puts" and "gets" seem childish and the math class does not even have
a degrees or radians function!

The operating system dependency built into the language did it for me.
That and the fact that I couldn't stop laughing for long enough to
learn any more when I read in the Pragmatic Programmer's Guide that
"Ruby, unlike less flexible languages, lets you alter the value of a
constant." Yep, as they say "Bug" = "Undocumented feature"!
 
M

Masklinn

How do I know if foo.value is an attribute or if it is a method that
returns the foo value ?
It cannot be an attribute. Ruby doesn't give access to attributes,
they're always solely private (as in Smalltalk). Also you shouldn't
reply to r, he has no idea about what he's talking about.
 

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,995
Messages
2,570,228
Members
46,818
Latest member
SapanaCarpetStudio

Latest Threads

Top