Confessions of a Python fanboy

M

Masklinn

You do know that only one of those works in-place, right?
Well mostly because the other one doesn't exist (as python has
`lst.reverse()` but `reversed(lst)`) but he was probably talking
hypothetically. Or something.
 
F

Falcolas

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.

That doesn't sound like a feature I would appreciate much, though I am
a big fan of "we're all adults here" programming. Though if they are
all functions, then adding parentheses wouldn't make much difference,
so offering the option of getting rid of them makes sense.
Well... it doesn't give much of a clue no really.

It, with few exceptions, tells me that fetching the value foo.val will
not modify the state of foo. Important stuff, at least to me.
 
M

Masklinn

That doesn't sound like a feature I would appreciate much, though I am
a big fan of "we're all adults here" programming. Though if they are
all functions, then adding parentheses wouldn't make much difference,
so offering the option of getting rid of them makes sense.
That's pretty much it.
It, with few exceptions, tells me that fetching the value foo.val will
not modify the state of foo. Important stuff, at least to me.
But because of those few exceptions, it really tells you that foo.val
*probably* doesn't modify the state of foo. Unless you go source-
diving, you can't know for sure. Only Haskell gives you that kind of
guarantees (and even then, the code you call could have an unsafe*
somewhere)
 
T

Terry Reedy

superpollo said:
how to reverse a string in python? must i usa a temp? like:

No.
>>> ''.join(list(reversed('abc'))) 'cba'
>>> 'abc'[2::-1] 'cba'
>>> 'abc'[1000000000::-1]
'cba'

Any int >= len(string)-1 will do, so the call to len will usually not be
necessary.

Needing strings reversed is not common. More common might be

for char in reversed(somestring): process(char)

Terry Jan Reedy
 
R

r

superpollo said:
r wrote:
how to reverse a string in python? must i usa a temp? like:
[snip]
Terry Jan Reedy

No "r" never wrote anything like that. reversing a string is RTFM
material, this is basic stuff here! Stop quoting me as saying things i
did not say! I never asked how to reverse a string, "superpollo"
did.
 
E

Emmanuel Surleau

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.

It has benefits - code does look better. It has also significant cons - it is
ambiguous.
For instance:

a = b

Is b a variable or a method called without parameter?
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.

It's not only the 'each' method. It's "anonymous callbacks everywhere", which
is pretty cool. Certainly one of my favourite features of Ruby.
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.

While ob.length() is more clear to read, it follows the same "operator" logic
as __iter__. Which is OK, I suppose.
But look at the French, WHAT
THE HELL HAS THAT DONE FOR THEM, *NOTHING*!!!!

I assume this was supposed to be funny?
As for the rest of Ruby, i am not impressed. The redundant usage of
"end" over indention perplexes me.

You have the choice to use {}. If you are confused over languages which do not
use indentation to delimit code blocks, you should probably try out a few
languages outside Python.
The Perlish feel of "require" and
the horrifically cryptic idioms of Ruby regular expressions.

Cryptic idioms of Ruby regular expressions? They are Perl-like regular
expressions, not exactly a far cry from what re does. Also, you can chain
them, which is extremely nice.
The "puts" and "gets" seem childish

Well, they're short and easy. Writing "gets" is more intuitive than using
raw_input()
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....

Cheers,

Emm
 
R

r

It has benefits - code does look better. It has also significant cons - it is
ambiguous.
For instance:

a = b

Is b a variable or a method called without parameter?

Hello Emanuel,
Again, who so ever names a method with such a non-descriptive name
will get whats coming to him. And if you did for some reason use such
a cryptic name as "b", do yourself (and everyone else) a favor and
follow it with "()" to denote the method call. Remember when something
is optional that means you have an option to use it OR not use it.

optional (http://definr.com/optional)
adj: possible but not necessary; left to personal choice [ant:
obligatory]


simple solutions for simple problems.
 
L

Luis Zarrabeitia

Well what's wrong with using that rather than `map`, `filter` or a
list comprehension?

As I understood the question, it was "was wrong in 'for var in container' in
comparison with ruby's container.each?"

What's the (semantic) difference between

for localVar in container:
block

and

container.each{|localVar| block}

?

(the sintactic difference is quite clear... if there is no semantic
difference, I'd rather use the first version!)

Map, filter and comprehensions have little to do with that (syntactic sugar
that may allow some optimizations, but that could otherwise be replaced by
the for loop).
(and if you don't see what the limitations of
`lambda` are, you probably very rarely use it)

I'm not the poster, but:
* I use lambdas, a lot.
* I "know" python lambdas are limited, compared with theoretical lambdas.
* I don't [usually] see that as a "limitation".

Most of the time, the limitation is the lack of multiline/multiexpression
lambdas. But I've never seen a case where I would /prefer/ to have a
multiline function definition inside a comprehension or method invocation,
instead of a named function defined two lines before it.

(The second famous limitation is the inability to use statements inside
lambdas... luckily, now that we have a ternary operator and a print function,
it is less limiting)
Uh… not at all…

I agree with this. It should have said that they are equivalent in the sense
that they represent the iterator protocols of both languages, and nothing
more.

I'd like to ask, what "container.each" is, exactly? It looks like a function
call (as I've learned a few posts ago), but, what are its arguments? How the
looping "works"? Does it receive a "code" object that it has to execute?
Is .each some kind of magic keyword? (This has little to do with python or
the current thread, so feel free to reply off-list if you want to...)

Regards,

Luis.
 
R

r

I'd like to ask, what "container.each" is, exactly? It looks like a function
call (as I've learned a few posts ago), but, what are its arguments? How the
looping "works"? Does it receive a "code" object that it has to execute?
Is .each some kind of magic keyword? (This has little to do with python or
the current thread, so feel free to reply off-list if you want to...)

Regards,

Luis.

Hello Luis,

I think your question is completely valid within the context of this
thread. The purpose of his thread was to get feedback on how Python
and Ruby ideas could be cumulated into the best high level language.
And being that i am the BDFL of the "Confessions of a Python Fanboy"
thread, you have my personal permission to continue on with this
subject matter...,
 
R

Robert Kern

Hello Emanuel,
Again, who so ever names a method with such a non-descriptive name
will get whats coming to him. And if you did for some reason use such
a cryptic name as "b", do yourself (and everyone else) a favor and
follow it with "()" to denote the method call. Remember when something
is optional that means you have an option to use it OR not use it.

I believe his point is that it is ambiguous to the compiler, not humans reading
the code. Python functions and methods are first class objects. They can be
passed around. If they were auto-called, then you could not do this.

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco
 
T

Terry Reedy

r said:
superpollo said:
r wrote:
how to reverse a string in python? must i usa a temp? like:
[snip]
Terry Jan Reedy

No "r" never wrote anything like that. reversing a string is RTFM
material, this is basic stuff here! Stop quoting me as saying things i
did not say! I never asked how to reverse a string, "superpollo"
did.

Nor did what I posted say that you did. The above says that superpollo
wrote "how to reverse..., as he did. Quotes are indented once more than
the author. The above says 'r wrote' with no indent and then "No...",
which you did write, indented once.

I agree that since I did not quote anything that you wrote, I should
also have snipped your name. But I least I do attempt to snip material
irrelavant to my comments.

Terry Jan Reedy
 
E

Emmanuel Surleau

I believe his point is that it is ambiguous to the compiler, not humans
reading the code.

Actually, both. Use a variable you didn't initialize? This is what you get:

NameError: undefined local variable or method `b' for main:Object
from (irb):1

The compiler has no idea if b is a variable or a method. It also makes it very
easy to shadow an existing method by declaring a variable of the same name,
which is problematic. I suppose it is a side-effect of Ruby's Perl
philosophical inheritance - except that Perl uses sigils to prefix its
variables, negating this issue.

Cheers,

Emm
 
S

Steven D'Aprano

I believe his point is that it is ambiguous to the compiler, not humans
reading the code. Python functions and methods are first class objects.
They can be passed around. If they were auto-called, then you could not
do this.

Oh my, "r" is still around is he??? And now he's singing the praises of
Ruby, the language which he treated as the Devil's Spawn when he first
arrived. That's hilarious.

But back on topic... "r" has missed the point. It's not that a=b is hard
to understand because b is a poor name. The example could have been:

def factory_function():
magic = time.time() # or whatever
def inner():
return magic
return inner

my_function = factory_function

It's still ambiguous. Does the programmer intend my_function to become
factory_function itself, or the output of factory_function?

In Python, it's not ambiguous at all -- my_function is set to
factory_function, and *not* the output of factory_function, because you
haven't called the function.

Python's model is consistent and simple: given a function "func", you
*always* refer to the function object itself as func and you *always*
call it with func(). This applies no matter how many arguments the
function takes, or what it returns, or where it is defined.

I think it's telling that "r" the fanboy has rejected Python's advantages
(simplicity, consistency, unambiguity) in favour of lazily saving two
keystrokes.
 
M

Masklinn

I'd like to ask, what "container.each" is, exactly? It looks like a
function
call (as I've learned a few posts ago), but, what are its arguments?
How the
looping "works"? Does it receive a "code" object that it has to
execute?
Is .each some kind of magic keyword? (This has little to do with
python or
the current thread, so feel free to reply off-list if you want to...)

#each is simply a method that takes a function (called blocks in
ruby). One could call it a higher-order method I guess.

It's an implementation of the concept of internal iteration: instead
of collections yielding iterator objects, and programmers using those
through specially-built iteration constructs (e.g. `for…in`),
collections control iteration over themselves (the iteration is
performed "inside" the collection, thus the "internal" part) and the
programmer provides the operations to perform at each iterative step
through (usually) a function.

In Python (assuming we had anonymous defs and an each method on
lists), the following loop:

for item in some_list:
do_something(item)
do_something_else(item)

some_list.each((def (item):
do_something(item)
do_something_else(item)
))

There's absolutely nothing magic there, it's simply using anonymous
functions and method calls (SmallTalk initiated this approach in the
70s, and actually went much, much further than Ruby as it did away not
only with `for…in` but also with `if…else` and `while` and a bunch of
other stuff).

Now as IV pointed out, #each isn't the most interesting usage of
blocks/anonymous functions (though I do like it, because it gets rid
of no less than two keywords… even if Ruby reintroduced them as
syntactic sugar), higher-order functions (functions which act on other
functions) are (among other things) ways to create new control
structures without having to extend the core language (so are lisp-
style macros, by the way).

Of course Python does have higher-order functions (functions are first-
class objects, so it's possible and frequent to have functions act on
other functions), but since Python doesn't have anonymous functions
that usage tends to be a bit too verbose beyond simple cases (also, of
course, this kind of usages is neither in the "genes" nor in the
stdlib).

In closing, IV has an example of how blocks make `with` unnecessary in
Ruby (the functionality can be implemented at the library level rather
than the language one). Generally, anonymous functions in OO languages
are a way to inject behavior into third-party methods/objects. Kind-of
a first-class Visitor support.

-m

PS: there's actually a bit of syntactic magic in Ruby's blocks, and
it's one of the things I hate in the language, but it's not relevant
to the role of blocks, and unnecessary to it: SmallTalk has no magical
syntax).
 
S

Steven D'Aprano

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"!

That's no different from Python's "constant by convention". We don't even
get a compiler warning!

On the other hand, we don't have to prefix names with @ and @@, and we
don't have the compiler trying to *guess* whether we're calling a
function or referring to a variable.

Somebody who knows more Ruby than me should try writing the Zen of Ruby.
Something like:

Line noise is beautiful.
Simplicity is for the simple.
Complicated just proves we're smart.
Readability only matters to the schmuck who has to maintain our code.
Special cases require breaking the rules.
In the face of ambiguity, try to guess. Go on, what could go wrong?
The more ways to do it, the better.

Although I'm sure Ruby has its good points. I'm not convinced anonymous
code blocks are one of them though.
 
C

Chris Rebert

Sorry to interrupt, but wouldn't lambda in Python be considered as
'anonymous functions'?

I believe "full" anonymous functions was intended by the author.
lambdas are limited to a single expression. "Full" anonymous functions
would be allowed to contain multiple statements.

Cheers,
Chris
 

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,769
Messages
2,569,582
Members
45,062
Latest member
OrderKetozenseACV

Latest Threads

Top