Re: Confessions of a Python fanboy
On Monday 11 May 2015 11:46, zipher wrote: By having methods like len() in your built-in namespace when it's really only relevant to objects that are types of containers, you blur one primary component of OOP: encapsulation. Gosh, one would almost think that Python's concept of OOP wasn't pure enough for you. You should talk to that other guy who says that Python is too pure, his name is Mark Rosenblitt-Janssen. I'm sure you two would have a lot to talk about. -- Steve -- https://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On 11/05/2015 07:15, Steven D'Aprano wrote: On Monday 11 May 2015 11:46, zipher wrote: By having methods like len() in your built-in namespace when it's really only relevant to objects that are types of containers, you blur one primary component of OOP: encapsulation. Gosh, one would almost think that Python's concept of OOP wasn't pure enough for you. You should talk to that other guy who says that Python is too pure, his name is Mark Rosenblitt-Janssen. I'm sure you two would have a lot to talk about. Ah, the penny has finally dropped. I recall years ago somebody pointing out his website. It had clearly been put together after the narcotics from several bulk carriers had been consumed. -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence -- https://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
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__() The issue is that Python currently blurs a very powerful conceptual boundary in CS -- between the abstract space where objects and variables are held and the concrete underlying machine. By having methods like len() in your built-in namespace when it's really only relevant to objects that are types of containers, you blur one primary component of OOP: encapsulation. Mark -- https://mail.python.org/mailman/listinfo/python-list
OFFTOPIC, WAS Re: Confessions of a Python fanboy
On Sunday, May 10, 2015 at 9:18:55 PM UTC-5, Chris Angelico wrote: On Mon, May 11, 2015 at 12:11 PM, zipher dreamingforw...@gmail.com wrote: Please take care of your quoting. You just quoted two other posts, and I have no idea who said things without going and digging in the archive. I'm sorry. I've been sleeping on the beach, away from civilization, a little too long, and didn't see that this was a post from 6 years ago. Feel free to disregard. That actually has nothing to do with it. You're still quoting without citation. Well, I replied right at the point of my correspondent (Alex23). If googlegroups isn't tracking that fact, it shouldn't put a reply button at every single message, but only at the end of the thread. This is why Google Groups has such a bad reputation. I think it's time for me to *plonk* you. I see. Someone should inform google not to put a reply after every post, but only at the end of a thread so users don't assume that it's tracking thread hierarchies. So you're point is apropos, if that's the case. In which case, my reply was to Alex23 who was replying to the OP's first post who goes by the name r. Mark -- https://mail.python.org/mailman/listinfo/python-list
Re: OFFTOPIC, WAS Re: Confessions of a Python fanboy
zipher dreamingforw...@gmail.com writes: On Sunday, May 10, 2015 at 9:18:55 PM UTC-5, Chris Angelico wrote: That actually has nothing to do with it. You're still quoting without citation. Well, I replied right at the point of my correspondent (Alex23). That's not the issue :-) The omission Chris is referring to is: in earlier messages, you were stripping the “attribution line” from directly above the quoted material. That makes it anonymous, and it becomes difficult to track who said what. The attribution line looks like: “On Sunday, May 10, 2015 at 9:18:55 PM UTC-5, Chris Angelico wrote:” without the quote marks. You need to preserve the attribution lines – as you did on the message just now, that I'm replying to – in order to show who wrote what quoted material. Only remove attribution lines if you're *also* removing all of the attributed material. Keep attribution lines for the material you're quoting. -- \“We have to go forth and crush every world view that doesn't | `\believe in tolerance and free speech.” —David Brin | _o__) | Ben Finney -- https://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
Please take care of your quoting. You just quoted two other posts, and I have no idea who said things without going and digging in the archive. I'm sorry. I've been sleeping on the beach, away from civilization, a little too long, and didn't see that this was a post from 6 years ago. Feel free to disregard. Mark -- https://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Mon, May 11, 2015 at 11:46 AM, zipher dreamingforw...@gmail.com wrote: 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__() The issue is that Python currently blurs a very powerful conceptual boundary in CS -- between the abstract space where objects and variables are held and the concrete underlying machine. By having methods like len() in your built-in namespace when it's really only relevant to objects that are types of containers, you blur one primary component of OOP: encapsulation. Please take care of your quoting. You just quoted two other posts, and I have no idea who said things without going and digging in the archive. ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Mon, May 11, 2015 at 12:11 PM, zipher dreamingforw...@gmail.com wrote: Please take care of your quoting. You just quoted two other posts, and I have no idea who said things without going and digging in the archive. I'm sorry. I've been sleeping on the beach, away from civilization, a little too long, and didn't see that this was a post from 6 years ago. Feel free to disregard. That actually has nothing to do with it. You're still quoting without citation. This is why Google Groups has such a bad reputation. I think it's time for me to *plonk* you. ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Friday 31 July 2009 04:08:33 am Masklinn wrote: On 30 Jul 2009, at 23:57 , Luis Zarrabeitia wrote: 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. Interesting. I know what internal iteration is, and I suspected it was along these lines when I saw the syntax and that .each was a function and not a keyword. But if it is internal iteration and the .each method is receiving an anonymous function, I wonder what is the scope of the variables in that function. In pseudo-python terms (using your example), x = 5 some_list.each((def (item): do_something(item, x) x = do_something_else(item) )) (or something like that). In python, the inner function would be invalid (the 'x' is local). For that construct to be equivalent to a for loop, the anonymous function shouldn't create a new scope. Is that what is happening? (If it is, this would be a big difference between anonymous and non-anonymous functions). Anyway, this is OT. Thank you for your reply. (ah, sorry for taking so long... I was out of town) -- Luis Zarrabeitia (aka Kyrie) Fac. de Matemática y Computación, UH. http://profesores.matcom.uh.cu/~kyrie -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
Steven D'Aprano ste...@remove.this.cybersource.com.au wrote in message news:pan.2009.08.04.09.28...@remove.this.cybersource.com.au... On Tue, 04 Aug 2009 10:03:53 +0200, Bruno Desthuilliers wrote: Disadvantages: your code is filled with line noise. It's an arbitrary choice between @@ meaning instance attribute and @@ meaning class attribute -- there's no logical reason for choosing one over the other, so you have to memorise which is which. It's easy to get it wrong. So far that's something I have no difficulty living with. I don't like arbitrary symbols. Most people don't -- that's why line noise is unpopular. It's hard to read, hard to write, hard to maintain, and hard to talk about. The more line-noise, the worse the language. It's not line noise if it conveys information... Of course, *ultimately* every symbol is arbitrary. There's no reason why 2 should mean the integer two, or list should mean a sequence type, but some symbols have such a long history, or have some other connection (say, with human languages), that the arbitrariness is lost. For instance, + is the obvious, non-arbitrary choice for the addition operator in any programming language using Latin symbols, and probably any programming language on Earth. (Not the *only* choice, but the obvious one.) I have a similar dislike for decorator syntax, because @ (at in English) has nothing to do with decorations. It's an arbitrary symbol. One might argue that $ would have been a more logical choice, because we turn numerals into currency by decorating it with a $ sign. (At least in the US, Canada, Australia, and a few other countries.) I use decorators all the time, and they are a fantastic invention, but the arbitrariness of the @ syntax is a negative. Oh well, one negative out of a whole lot of positives isn't too bad. You can think of @ as describing something being at the instance or the class. $ is totally arbitrary to me 'cause I don't thnk of my code as currency... At least I only have to deal with *one* such arbitrary symbol that needs memorizing. There's no need to distinguish between @@function_decorator and @class_decorator (or should it be the other way around?). Similarly, Python's choice of syntax for attributes is consistent: object.attribute works for everything, whether object is a class, an instance, a module, and whether attribute is callable or not. You can even use it on ints, provided you are clever about it: You can think of @ as being at an instance or @@ to be more emphatically (as the Japanese do in their language) integrated with a class, being available to all instances... or you can simply understand that instance vairables are more common than class variables so the shorter notation is used for the more common case... You want to talk about arbitrariness? Why is len() a function you pass objects into while objects can have methods that describe themselves to you? At least Ruby defines operators using the actual name of the operator instead of you having to remember an arbitrary magic incantation that corresponds to the operator... class Test attr_reader :data def initialize(data) @data = data end # This is the operator part... def + right Test.new @data + right.data end end Somebody who knows more Ruby than me should try writing the Zen of Ruby. Something like: (snip childish parody of Python Zen) Steven, is that any useful ? It made me feel good. Why ??? You don't like Ruby ? Fine, don't use it. Period. I can't see the point of all these pissing contests. Criticism of a language is a pissing contest? Yeah, okay, I was a tad dismissive. I un-apologetically jump to strong impressions about languages based on minimal use -- but I'm also willing to change my mind. Ruby certainly looks to me like it has some nice features. Syntax that looks like Perl isn't one of them though. Yeah, that would be the pissing contest part. You could simply have gone to the Ruby newsgroup and posted some criticisms to see what was behind those decisions. However, that would have avoided the pissing contest and perhaps you wanted one... Just because Smalltalk had a particular (mis?)feature You can drop the 'mis' part IMHO. The point of code blocks in Smalltalk is that once you have something as powerful as the message+code blocks combo, you just don't need any other 'special form' for control flow. Well, maybe, but remember, programming languages are only partly for communication to the compiler. They also have the requirement to communicate with human programmers as well, and that's even more important, because (1) humans spent a lot more time working with code than compilers do; (2) human programmers charge much more money than compilers do; (3) and you can modify the compiler to suit human needs much more easily than you can modify programmers to suit the compiler's needs.
Re: Confessions of a Python fanboy
Steven D'Aprano a écrit : On Fri, 31 Jul 2009 13:38:56 +0200, Bruno Desthuilliers wrote: On the other hand, we don't have to prefix names with @ and @@, Nope, we have to prefix them with 'self' or 'cls' (or even 'self.__class__'). Incorrect. Correct for all relevant cases, except this one: class K: ... class_attribute = 'No @@ required.' ... K().class_attribute 'No @@ required.' Once again: Ruby's attributes are *private*, so you can't access an attribute (class or instance) from outside a method. IOW, the above example is irrelevant. (snip) Disadvantages: your code is filled with line noise. It's an arbitrary choice between @@ meaning instance attribute and @@ meaning class attribute -- there's no logical reason for choosing one over the other, so you have to memorise which is which. It's easy to get it wrong. So far that's something I have no difficulty living with. and we don't have the compiler trying to *guess* whether we're calling a function or referring to a variable. Please re-read a bit more carefully - it's *all* method call. What did I misread from here? Nowhere - it's me that got it wrong here, sorry. (snip) Somebody who knows more Ruby than me should try writing the Zen of Ruby. Something like: (snip childish parody of Python Zen) Steven, is that any useful ? It made me feel good. Why ??? You don't like Ruby ? Fine, don't use it. Period. I can't see the point of all these pissing contests. But seriously, while I admit that I have very little Ruby experience, and so aren't in a great position to judge, it seems to me that Ruby doesn't have anything like Python's over-riding design principles (the Zen). If there is a design principle to Ruby, I can't see what it is. Fullfill the tastes of Matz ?-) (snip) Although I'm sure Ruby has its good points. I'm not convinced anonymous code blocks are one of them though. Ruby's code blocks come from Smalltalk, where they are an absolute necessity since message passing (which code blocks are part of) is the *only* builtin control flow in Smalltalk - so you just *need* this construction to provide branching and iterations. Just because Smalltalk had a particular (mis?)feature You can drop the 'mis' part IMHO. The point of code blocks in Smalltalk is that once you have something as powerful as the message+code blocks combo, you just don't need any other 'special form' for control flow. doesn't mean that other languages should copy it. Nope. But OTHO, Python is famous for all the features it copied from other languages !-) -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Tue, 04 Aug 2009 10:03:53 +0200, Bruno Desthuilliers wrote: Disadvantages: your code is filled with line noise. It's an arbitrary choice between @@ meaning instance attribute and @@ meaning class attribute -- there's no logical reason for choosing one over the other, so you have to memorise which is which. It's easy to get it wrong. So far that's something I have no difficulty living with. I don't like arbitrary symbols. Most people don't -- that's why line noise is unpopular. It's hard to read, hard to write, hard to maintain, and hard to talk about. The more line-noise, the worse the language. Of course, *ultimately* every symbol is arbitrary. There's no reason why 2 should mean the integer two, or list should mean a sequence type, but some symbols have such a long history, or have some other connection (say, with human languages), that the arbitrariness is lost. For instance, + is the obvious, non-arbitrary choice for the addition operator in any programming language using Latin symbols, and probably any programming language on Earth. (Not the *only* choice, but the obvious one.) I have a similar dislike for decorator syntax, because @ (at in English) has nothing to do with decorations. It's an arbitrary symbol. One might argue that $ would have been a more logical choice, because we turn numerals into currency by decorating it with a $ sign. (At least in the US, Canada, Australia, and a few other countries.) I use decorators all the time, and they are a fantastic invention, but the arbitrariness of the @ syntax is a negative. Oh well, one negative out of a whole lot of positives isn't too bad. At least I only have to deal with *one* such arbitrary symbol that needs memorizing. There's no need to distinguish between @@function_decorator and @class_decorator (or should it be the other way around?). Similarly, Python's choice of syntax for attributes is consistent: object.attribute works for everything, whether object is a class, an instance, a module, and whether attribute is callable or not. You can even use it on ints, provided you are clever about it: 42 .__class__ type 'int' Somebody who knows more Ruby than me should try writing the Zen of Ruby. Something like: (snip childish parody of Python Zen) Steven, is that any useful ? It made me feel good. Why ??? You don't like Ruby ? Fine, don't use it. Period. I can't see the point of all these pissing contests. Criticism of a language is a pissing contest? Yeah, okay, I was a tad dismissive. I un-apologetically jump to strong impressions about languages based on minimal use -- but I'm also willing to change my mind. Ruby certainly looks to me like it has some nice features. Syntax that looks like Perl isn't one of them though. Just because Smalltalk had a particular (mis?)feature You can drop the 'mis' part IMHO. The point of code blocks in Smalltalk is that once you have something as powerful as the message+code blocks combo, you just don't need any other 'special form' for control flow. Well, maybe, but remember, programming languages are only partly for communication to the compiler. They also have the requirement to communicate with human programmers as well, and that's even more important, because (1) humans spent a lot more time working with code than compilers do; (2) human programmers charge much more money than compilers do; (3) and you can modify the compiler to suit human needs much more easily than you can modify programmers to suit the compiler's needs. So I'd ask, does Smalltalk's message passing model match the way human beings think? If not, then that's a good sign it might be a misfeature. doesn't mean that other languages should copy it. Nope. But OTHO, Python is famous for all the features it copied from other languages !-) Absolutely! There's nothing wrong with copying *good* features :) -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
Steven D'Aprano a écrit : On Tue, 04 Aug 2009 10:03:53 +0200, Bruno Desthuilliers wrote: Disadvantages: your code is filled with line noise. It's an arbitrary choice between @@ meaning instance attribute and @@ meaning class attribute -- there's no logical reason for choosing one over the other, so you have to memorise which is which. It's easy to get it wrong. So far that's something I have no difficulty living with. I don't like arbitrary symbols. Neither do I - when there are too many at least. But I can certainly live with a couple ones. Now the point wasn't about my personal tastes, but about the fact that this particular pair of arbitrary symbols was IMHO still usable - IOW, I wouldn't dismiss Ruby on this sole point. Most people don't -- that's why line noise is unpopular. It's hard to read, hard to write, hard to maintain, and hard to talk about. The more line-noise, the worse the language. OTHO, too much verbosity is a pain too. Ever programmed in AppleScript ? set the attribute XXX of object YYY of collection ZZZ to SomeValue... Yuck. I bet you prefer zzz[yyy].xxx = SomeValue - which uses three arbitrary symbols. (snip) Oh well, one negative out of a whole lot of positives isn't too bad. Indeed. You could perhaps learn a bit more about Ruby's positives if you don't block on what you perceive (rightfully or not) as negative points ?-) (snip) Somebody who knows more Ruby than me should try writing the Zen of Ruby. Something like: (snip childish parody of Python Zen) Steven, is that any useful ? It made me feel good. Why ??? You don't like Ruby ? Fine, don't use it. Period. I can't see the point of all these pissing contests. Criticism of a language is a pissing contest? Not necessarily. But: Yeah, okay, I was a tad dismissive. I un-apologetically jump to strong impressions about languages based on minimal use Possibly, yes. -- but I'm also willing to change my mind. Ruby certainly looks to me like it has some nice features. Syntax that looks like Perl isn't one of them though. Not my cup of tea neither FWIW. But Ruby is nowhere near Perl in terms of line noise. Just because Smalltalk had a particular (mis?)feature You can drop the 'mis' part IMHO. The point of code blocks in Smalltalk is that once you have something as powerful as the message+code blocks combo, you just don't need any other 'special form' for control flow. Well, maybe, but remember, programming languages are only partly for communication to the compiler. They also have the requirement to communicate with human programmers as well, and that's even more important, because (1) humans spent a lot more time working with code than compilers do; (2) human programmers charge much more money than compilers do; (3) and you can modify the compiler to suit human needs much more easily than you can modify programmers to suit the compiler's needs. So I'd ask, does Smalltalk's message passing model match the way human beings think? Does all human beings think the same way ? And aren't human beings able to learn new ways ? Smalltalk's only control flow construct might seem a bit weird at first when all you've been exposed to so far are more traditional special constructs, but it's not hard to learn and is way more uniform and flexible than having special constructs for each and any possible situation. One could ask if functional programming or OO matches the way human beings think. From experience, some of us just find FP and / or OO just obvious, and some won't never get it. FWIW, there are quite a few features and idioms in Python that I _now_ find readable and obvious, but that would have puzzled me ten years ago. This reminds me of a shop where the CTO had forbidden using any OO feature of the main language used there because nobody would understand it (needless to say, I only stayed there a couple weeks...). doesn't mean that other languages should copy it. Nope. But OTHO, Python is famous for all the features it copied from other languages !-) Absolutely! There's nothing wrong with copying *good* features :) Well... at least when they make sense and integrate smoothly into the target language. -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On 4 Aug 2009, at 11:28 , Steven D'Aprano wrote: So I'd ask, does Smalltalk's message passing model match the way human beings think? Yes. -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Thu, 30 Jul 2009 18:06:31 -0500, Robert Kern wrote: On 2009-07-30 16:44, r wrote: On Jul 30, 4:29 pm, Emmanuel Surleauemmanuel.surl...@gmail.com wrote: 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? 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. 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. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On 30 Jul 2009, at 23:52 , Jan Kaliszewski wrote: Dnia 30-07-2009 o 22:41:57 Masklinn maskl...@masklinn.net napisał(a): On 30 Jul 2009, at 22:23 , Jan Kaliszewski wrote: 30-07-2009 o 13:36:49 Masklinn maskl...@masklinn.net wrote: On 30 Jul 2009, at 06:04 , alex23 wrote: On Jul 30, 1:06 pm, r rt8...@gmail.com wrote: 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] The issue here is of course that `map` and comprehensions are transformations. `#each` exists for effectful iterations (Ruby has `#map` for the map operation). So the intent expressed by `#each` and `map` isn't the same. Furthermore and this is the most problematic limitation of Python here, `lambda` doesn't allow complex transformations due to its restrictions, so one has to switch to named functions which works but isn't sexy (and tends to lower readability imo). I don't see any real limitation. What's wrong in: for localVar in container: block Well what's wrong with using that rather than `map`, `filter` or a list comprehension? (and if you don't see what the limitations of `lambda` are, you probably very rarely use it) I know well about the expression-only-limitation of lambda, fortnately there is the 'for' loop construct (or, alternatively, you can define a named function). And then, what's wrong with using 'for' rather than 'map', 'filter' etc.? Nothing, but then again nothing's wrong using C's for either. But I do think that using higher-order functions: * tends to be terser while not going overly terse, it only removes boilerplate * is more composable (it's pretty easy to tack another transformer in your chain, the same way defining iterator/generator transformers and chaining them is simpler than doing the same thing using explicit `for…in`) * it clearly spells the intent of the programmer, while `for` can be anything and everything, and one has to dive into the code to know even the high-level operations performed (is it a basic transformation? A filtering or partitioning? A reduction? An application of side effects?) Agree, that 'anonymous block syntax' would be nice in some cases, but I don't see any real limitation caused by lack of it i.e. something you can't (all you can only with unreasonable effort). There are no limitations, but once again there never are. There are no actual limitations to using conditional jumps over iterators either. And ruby's container.each is very similar to Python's iter() Uh… not at all… OK, .each is like Python's iter() + some form of iterating over it ('for' loop or '[i]map'...). Well of course Enumerable#each is similar to map/imap, it's the same core principle. -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On 30 Jul 2009, at 23:57 , Luis Zarrabeitia wrote: 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). -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Thu, 30 Jul 2009 18:47:04 +0100, Tim Rowe wrote: 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. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Fri, Jul 31, 2009 at 6:08 PM, Masklinn maskl...@masklinn.net wrote: snip... but since Python doesn't have anonymous functions that usage tends to be a bit too verbose ... snip Sorry to interrupt, but wouldn't lambda in Python be considered as 'anonymous functions'? -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Fri, Jul 31, 2009 at 1:21 AM, Xavier Hocont...@xavierho.com wrote: On Fri, Jul 31, 2009 at 6:08 PM, Masklinn maskl...@masklinn.net wrote: snip... but since Python doesn't have anonymous functions that usage tends to be a bit too verbose ... snip 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 -- http://blog.rebertia.com -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Fri, Jul 31, 2009 at 6:25 PM, Chris Rebert c...@rebertia.com wrote: 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, but what about this: def goBig(x): while True: x = x ** 2 yield x for result in goBig(10): if result 10 ** 100: break print result It's a silly example, but wouldn't goBig(10) in this example be a full anonymous function? Just being curious. -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Fri, Jul 31, 2009 at 1:31 AM, Xavier Hocont...@xavierho.com wrote: On Fri, Jul 31, 2009 at 6:25 PM, Chris Rebert c...@rebertia.com wrote: 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, but what about this: def goBig(x): while True: x = x ** 2 yield x for result in goBig(10): if result 10 ** 100: break print result It's a silly example, but wouldn't goBig(10) in this example be a full anonymous function? No, because it has a name, namely goBig; this obviously prevents it from being anonymous. For comparison, note how the function in the following example is never given a name, and is thus anonymous: (lambda x: x+5)(6) 11 Cheers, Chris -- http://blog.rebertia.com -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Fri, Jul 31, 2009 at 6:38 PM, Chris Rebert c...@rebertia.com wrote: No, because it has a name, namely goBig; this obviously prevents it from being anonymous. For comparison, note how the function in the following example is never given a name, and is thus anonymous: (lambda x: x+5)(6) 11 Oh, I see. I was thinking in terms of using a variable to give the function a name. In that case, I understand. Thanks again for bearing me with my random thoughts. -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
r wrote: 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..., Challenging even the most accepted mechanisms of a language is a proof of intelligence. Descartes's doubt method : The basic strategy of /Descartes/ http://www.philosophypages.com/ph/desc.htm's method of doubt http://www.philosophypages.com/dy/d9.htm#doubt is to defeat skepticism http://www.philosophypages.com/dy/s5.htm#skep on its own ground. Begin by doubting the truth of everything—not only the evidence http://www.philosophypages.com/dy/e9.htm#evid of the senses and the more extravagant cultural presuppositions, but even the fundamental process of reasoning itself. If any particular truth about the world can survive this extreme skeptical challenge, then it must be truly indubitable and therefore a perfectly certain foundation for knowledge So let's make the method call parenthesis a truly indubitable and therefore a perfectly certain foundation. Those who want to remove the parenthesis on python method calls raise the hand ! JM -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On 31 Jul 2009, at 10:25 , Chris Rebert wrote: On Fri, Jul 31, 2009 at 1:21 AM, Xavier Hocont...@xavierho.com wrote: On Fri, Jul 31, 2009 at 6:08 PM, Masklinn maskl...@masklinn.net wrote: snip... but since Python doesn't have anonymous functions that usage tends to be a bit too verbose ... snip 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. Yes, and they're limited to a single *expression*, so before Python 3, lambda: print foo is out. Likewise, it isn't possible to have an if/ else statement within a lambda (though a ternary is ok), or a with, … since Python statements aren't expressions. -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Jul 31, 8:28 am, Steven D'Aprano st...@remove-this- cybersource.com.au wrote: On Thu, 30 Jul 2009 18:06:31 -0500, Robert Kern wrote: On 2009-07-30 16:44, r wrote: On Jul 30, 4:29 pm, Emmanuel Surleauemmanuel.surl...@gmail.com wrote: 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? 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. 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? Not only that - does 'return inner' return the function inner or the result of function inner? How does ruby pass a function as an object? Iain -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On 31 Jul 2009, at 11:54 , Iain King wrote: On Jul 31, 8:28 am, Steven D'Aprano st...@remove-this- cybersource.com.au wrote: On Thu, 30 Jul 2009 18:06:31 -0500, Robert Kern wrote: On 2009-07-30 16:44, r wrote: On Jul 30, 4:29 pm, Emmanuel Surleauemmanuel.surl...@gmail.com wrote: 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? 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. 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? Not only that - does 'return inner' return the function inner or the result of function inner? How does ruby pass a function as an object? Ruby doesn't have functions as such. It has methods and blocks (which would be anonymous functions). `def` always creates methods. To get a (bound) method object, you simply call `method` on an instance e.g. `foo.method(:bar)` is equivalent to `foo.bar` in Python (it returns a bound method object without calling it). Blocks are usually created as part of the calls: `foo.bar {do_something}` the part between braces (braces included) is a block, which will be passed to the method `bar`. Sadly, Ruby's blocks are magical syntax (doesn't mean they have to be, in Smalltalk there's nothing magical about blocks for instance) so you can't just do `foo = {do_something}`, you have to turn them into `Proc` objects with the `proc` constructor (or `lambda`, it's equivalent and looks better so I'll use that): `foo = lambda {do_something}`. If you use the magical syntax previously shown, Ruby handles the turning of a block into an actual `Proc` instance. And since Ruby doesn't have a `()` operator, it uses a method instead (`#call`), so you simply do `foo.call` to execute the proc and get its value. All in all, much like Smalltalk, Ruby tends not to favor raw functions the way Python does, so a direct translation of the Python code doesn't make much sense. -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
Steven D'Aprano a écrit : On Thu, 30 Jul 2009 18:47:04 +0100, Tim Rowe wrote: 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. Well, at least Python doesn't pretend to have real symbolic constants - we all know it's only a convention !-) We don't even get a compiler warning! Of course - from the compiler's POV, it's only usual rebinding. On the other hand, we don't have to prefix names with @ and @@, Nope, we have to prefix them with 'self' or 'cls' (or even 'self.__class__'). and we don't have the compiler trying to *guess* whether we're calling a function or referring to a variable. Please re-read a bit more carefully - it's *all* method call. Python is 'uniform' in obj.name is always an attribute lookup (methods being attributes), Ruby is uniform in that 'obj.name' is always a method call. Somebody who knows more Ruby than me should try writing the Zen of Ruby. Something like: (snip childish parody of Python Zen) Steven, is that any useful ? Although I'm sure Ruby has its good points. I'm not convinced anonymous code blocks are one of them though. Ruby's code blocks come from Smalltalk, where they are an absolute necessity since message passing (which code blocks are part of) is the *only* builtin control flow in Smalltalk - so you just *need* this construction to provide branching and iterations. Wether it makes sense to have code blocks in Ruby is another question since Ruby does provide traditional control flow features, but then one could question Python's lambda (hem...) too. -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On 31 Jul 2009, at 13:38 , Bruno Desthuilliers wrote: Steven D'Aprano a écrit : On Thu, 30 Jul 2009 18:47:04 +0100, Tim Rowe wrote: 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. Ruby's code blocks come from Smalltalk, where they are an absolute necessity since message passing (which code blocks are part of) is the *only* builtin control flow in Smalltalk - so you just *need* this construction to provide branching and iterations. I'm not so sure about the way you say it. I'm pretty sure traditional flow control structures preceded Smalltalk by a pair of decades so it's not that Smalltalk's designers found it necessary to use blocks messages, but that they understood blocks messages could trivially replace most control structures (making *those* unnecessary), making the core language simpler and more flexible. In other words, I see it the other way around. Wether it makes sense to have code blocks in Ruby is another question since Ruby does provide traditional control flow features Well it does at least allow for the creation of new flow control structures in library land when the existing ones aren't enough (e.g. allows Ruby not to require the introduction of a `with` statement). Though Ruby's blocks are nowhere near as flexible as Smalltalk's. -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
Masklinn a écrit : On 31 Jul 2009, at 13:38 , Bruno Desthuilliers wrote: Steven D'Aprano a écrit : On Thu, 30 Jul 2009 18:47:04 +0100, Tim Rowe wrote: 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. Ruby's code blocks come from Smalltalk, where they are an absolute necessity since message passing (which code blocks are part of) is the *only* builtin control flow in Smalltalk - so you just *need* this construction to provide branching and iterations. I'm not so sure about the way you say it. I'm not sure about the way you understand it !-) I'm pretty sure traditional flow control structures preceded Smalltalk by a pair of decades Yes, of course - and that's not the point. What's important is that: so it's not that Smalltalk's designers found it necessary to use blocks messages, but that they understood blocks messages could trivially replace most control structures (making *those* unnecessary), making the core language simpler and more flexible. Exactly. In other words, I see it the other way around. My wording may have been a bit confusing, indeed. It was implied (but perhaps a bit unclear) that restricting control structures to messages and blocks was a design choice. Wether it makes sense to have code blocks in Ruby is another question since Ruby does provide traditional control flow features Well it does at least allow for the creation of new flow control structures in library land when the existing ones aren't enough (e.g. allows Ruby not to require the introduction of a `with` statement). Yeps. But then other traditionnal control flow features become redundant. Though Ruby's blocks are nowhere near as flexible as Smalltalk's. -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On 31 Jul 2009, at 15:12 , Bruno Desthuilliers wrote: Masklinn a écrit : On 31 Jul 2009, at 13:38 , Bruno Desthuilliers wrote: Steven D'Aprano a écrit : On Thu, 30 Jul 2009 18:47:04 +0100, Tim Rowe wrote: 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. Ruby's code blocks come from Smalltalk, where they are an absolute necessity since message passing (which code blocks are part of) is the *only* builtin control flow in Smalltalk - so you just *need* this construction to provide branching and iterations. [misunderstandings on my part/clarifications on yours] Well it does at least allow for the creation of new flow control structures in library land when the existing ones aren't enough (e.g. allows Ruby not to require the introduction of a `with` statement). Yeps. But then other traditionnal control flow features become redundant. They can be anyway: Ruby doesn't deprecate most control flows as the actual usages of blocks are a bit restricted (cannot be used for `while` as it would require the serialization to a Proc, and Ruby's syntax doesn't allow sending multiple blocks to a method so `if…else` is out as well). And I assume they reintroduced the for…in sugar to ease the transition from more traditional languages (using #each and others seems the suggested collection iterators across the community). -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
Steven D'Aprano wrote: On Thu, 30 Jul 2009 18:47:04 +0100, Tim Rowe wrote: 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! That's quite different, actually. Python doesn't claim to have constants! Can't misinterpret what you can't have, can you? [Holds breath while awaiting counter-example... :] ~Ethan~ -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Jul 31, 4:08 pm, Ethan Furman et...@stoneleaf.us wrote: Steven D'Aprano wrote: On Thu, 30 Jul 2009 18:47:04 +0100, Tim Rowe wrote: 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! That's quite different, actually. Python doesn't claim to have constants! Can't misinterpret what you can't have, can you? [Holds breath while awaiting counter-example... :] ~Ethan~ The convention being detailed in PEP8: http://www.python.org/dev/peps/pep-0008/ basically, anything in ALL_CAPS is a constant, assuming you follow those style guidelines. Iain -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Fri, Jul 31, 2009 at 11:35 AM, Iain Kingiaink...@gmail.com wrote: On Jul 31, 4:08 pm, Ethan Furman et...@stoneleaf.us wrote: Steven D'Aprano wrote: On Thu, 30 Jul 2009 18:47:04 +0100, Tim Rowe wrote: 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! That's quite different, actually. Python doesn't claim to have constants! Can't misinterpret what you can't have, can you? [Holds breath while awaiting counter-example... :] ~Ethan~ The convention being detailed in PEP8: http://www.python.org/dev/peps/pep-0008/ basically, anything in ALL_CAPS is a constant, assuming you follow those style guidelines. Right, but that's a style guide and not a language definition. Nobody claims that anything in there is a part of the language. Iain -- http://mail.python.org/mailman/listinfo/python-list -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Fri, 31 Jul 2009 13:38:56 +0200, Bruno Desthuilliers wrote: On the other hand, we don't have to prefix names with @ and @@, Nope, we have to prefix them with 'self' or 'cls' (or even 'self.__class__'). Incorrect. class K: ... class_attribute = 'No @@ required.' ... K().class_attribute 'No @@ required.' No 'self' or 'cls' in sight. I can see a vague advantage to using @ to create instance attributes and @@ to creating class attributes -- it makes it easy to create class attributes inside a method without needing to do a double lookup. In Python terms: def K: def method(self): self.__class__.attr = Class attribute would be: def K: def method(self): @@attr = Class attribute Advantages: you save a few characters and (possibly!) a couple of runtime lookups. Disadvantages: your code is filled with line noise. It's an arbitrary choice between @@ meaning instance attribute and @@ meaning class attribute -- there's no logical reason for choosing one over the other, so you have to memorise which is which. It's easy to get it wrong. 'self' and 'cls' at least are words, even if 'cls' is badly misspelled :) and we don't have the compiler trying to *guess* whether we're calling a function or referring to a variable. Please re-read a bit more carefully - it's *all* method call. What did I misread from here? [quote] When Ruby sees a name such as ``a'' in an expression, it needs to determine if it is a local variable reference or a call to a method with no parameters. To decide which is the case, Ruby uses a heuristic. As Ruby reads a source file, it keeps track of symbols that have been assigned to. It assumes that these symbols are variables. When it subsequently comes across a symbol that might be either a variable or a method call, it checks to see if it has seen a prior assignment to that symbol. If so, it treats the symbol as a variable; otherwise it treats it as a method call. [end quote] And see the example pathological case comparing a function call (not method) and a variable. http://ruby-doc.org/docs/ProgrammingRuby/html/language.html Python is 'uniform' in obj.name is always an attribute lookup (methods being attributes), Ruby is uniform in that 'obj.name' is always a method call. Which would be relevant if I was talking about method calls, but I wasn't. Somebody who knows more Ruby than me should try writing the Zen of Ruby. Something like: (snip childish parody of Python Zen) Steven, is that any useful ? It made me feel good. But seriously, while I admit that I have very little Ruby experience, and so aren't in a great position to judge, it seems to me that Ruby doesn't have anything like Python's over-riding design principles (the Zen). If there is a design principle to Ruby, I can't see what it is. I'm the first to admit that I'm far too inexperienced with the language to make this a fair judgement. Unfair it might be, but it doesn't necessarily mean I'm wrong! *wink* Ruby just seems to be far more complicated than Python: things which Python does at runtime, with a function call, Ruby has special syntax for: a bunch of words.split() %w(a bunch of words) ord('a') ?a That makes the barrier to entry far higher: it's easier to leverage existing knowledge to interpret unfamiliar Python code than unfamiliar Ruby code. Or so it seems to me. Oh, and I admit that Python decorators are a conspicuous counter-example. I wouldn't do without them, but neither would I expect somebody to intuit what they do. Although I'm sure Ruby has its good points. I'm not convinced anonymous code blocks are one of them though. Ruby's code blocks come from Smalltalk, where they are an absolute necessity since message passing (which code blocks are part of) is the *only* builtin control flow in Smalltalk - so you just *need* this construction to provide branching and iterations. Just because Smalltalk had a particular (mis?)feature doesn't mean that other languages should copy it. I know, I know, Ruby people swear by anonymous code blocks, and I've read Paul Graham too. But I'm really not so sure that the benefits of anonymous code blocks are great enough to overcome the disadvantages of anonymous code blocks. Wether it makes sense to have code blocks in Ruby is another question since Ruby does provide traditional control flow features, but then one could question Python's lambda (hem...) too. lambda, by allowing the function to be only a single expression, doesn't suffer the disadvantages of anonymous code blocks. lambda, by allowing the function to be only a single expression, also has fewer advantages than anonymous code blocks. I think lambda ends up on the more advantages than disadvantages side. I'm keeping my mind open regarding Ruby code blocks. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On 31 Jul 2009, at 17:55 , Steven D'Aprano wrote: But seriously, while I admit that I have very little Ruby experience, and so aren't in a great position to judge, it seems to me that Ruby doesn't have anything like Python's over-riding design principles (the Zen). If there is a design principle to Ruby, I can't see what it is. As far as I know, Ruby doesn't have anything like the Zen no. But then again, I don't know any language other than Python with such a document. Ruby just seems to be far more complicated than Python: things which Python does at runtime, with a function call, Ruby has special syntax for: a bunch of words.split() %w(a bunch of words) ord('a') ?a That's the Perl heritage. And since it inherits from Perl, TIMTOWTDI: a bunch of words.split = [a, bunch, of, words] a[0] = 97 (yes, the indexing operator returns a character code if provided a single index. With two, it returns as string slice) Oh and %w() isn't really equivalent to split(): you don't use it to split a string but to create a list of strings, so the equivalent expression in Python would be `[a, bunch, of, words]`. That makes the barrier to entry far higher: it's easier to leverage existing knowledge to interpret unfamiliar Python code than unfamiliar Ruby code. Or so it seems to me. That's probable. Although I'm sure Ruby has its good points. I'm not convinced anonymous code blocks are one of them though. Ruby's code blocks come from Smalltalk, where they are an absolute necessity since message passing (which code blocks are part of) is the *only* builtin control flow in Smalltalk - so you just *need* this construction to provide branching and iterations. Just because Smalltalk had a particular (mis?)feature doesn't mean that other languages should copy it. I know, I know, Ruby people swear by anonymous code blocks, and I've read Paul Graham too. But I'm really not so sure that the benefits of anonymous code blocks are great enough to overcome the disadvantages of anonymous code blocks. What are the disadvantages of anonymous functions? -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
Masklinn wrote: #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. Python's iterator protocol was developed in part to avoid the (inside-out) callback style of programming. Writing virtual collections as generator functions instead of iterator or iterable classes saves a lot of boilerplate code. The itertools modules shows how nicely iterators can be composed in a way that is much more awkward with callbacks. 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) )) And how does Ruby do the equivalent of def double(it): for i in it: yield 2*i for i,j in zip(double(some_list), some_gen_func(args)): print(do_something(i+j,i-j)) Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
2009/7/31 Steven D'Aprano st...@remove-this-cybersource.com.au: On Thu, 30 Jul 2009 18:47:04 +0100, Tim Rowe wrote: 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! We don't actually *declare* that something is constant and then have that declaration ignored. Python doesn't lie to us, although (as in any language) a programmer might. -- Tim Rowe -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Jul 31, 3:49 am, Masklinn maskl...@masklinn.net wrote: On 31 Jul 2009, at 10:25 , Chris Rebert wrote: On Fri, Jul 31, 2009 at 1:21 AM, Xavier Hocont...@xavierho.com wrote: On Fri, Jul 31, 2009 at 6:08 PM, Masklinn maskl...@masklinn.net wrote: snip... but since Python doesn't have anonymous functions that usage tends to be a bit too verbose ... snip 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. Yes, and they're limited to a single *expression*, so before Python 3, lambda: print foo is out. Likewise, it isn't possible to have an if/ else statement within a lambda (though a ternary is ok), or a with, … since Python statements aren't expressions. Perhaps you can't do lambda foo: print foo, but you *can* do lambda x: sys.stdout.write(x). Combined with the ternary if, it seem sufficient if you want to stick to the ideal Simple is better than Complex. Sure, with statements allowed in anonymous functions, you can save on a line of typing (def blargh(x):), but I don't feel the obfuscation is worth the cost. ~G -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On 31 Jul 2009, at 18:24 , Terry Reedy wrote: Masklinn wrote: #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. Python's iterator protocol was developed in part to avoid the (inside-out) callback style of programming. Writing virtual collections as generator functions instead of iterator or iterable classes saves a lot of boilerplate code. The itertools modules shows how nicely iterators can be composed in a way that is much more awkward with callbacks. 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) )) And how does Ruby do the equivalent of def double(it): for i in it: yield 2*i for i,j in zip(double(some_list), some_gen_func(args)): print(do_something(i+j,i-j)) Somethign along the lines of some_list.map{|e| 2*e}.zip(some_gen_func(args)).each {|i, j| puts(do_something(i+j, i-j)) } The `#each` call after `#zip` is not actually necessary, but I find it clearer. Oh, and some_gen_func and do_something probably wouldn't work that way (as I said above, Ruby isn't big on named functions and doesn't actually have them) -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Fri, 31 Jul 2009 18:15:15 +0200, Masklinn wrote: I know, I know, Ruby people swear by anonymous code blocks, and I've read Paul Graham too. But I'm really not so sure that the benefits of anonymous code blocks are great enough to overcome the disadvantages of anonymous code blocks. What are the disadvantages of anonymous functions? In no particular order, and not necessarily exhaustive: * The risk of obfuscation in your code. That's fairly minimal for lambdas, because they're just a single expression, but for a large anonymous code block (ACB) defined inside a named function, it may be difficult for the reader to easily distinguish which bits are the outer function and which are the ACB. * Loss of useful debugging information. Take this example from Python: def main(f): ... return f(3) ... main(lambda n: 2/(n-3)) Traceback (most recent call last): File stdin, line 1, in module File stdin, line 2, in main File stdin, line 1, in lambda ZeroDivisionError: integer division or modulo by zero def my_special_function(n): ... return 2/(n-3) ... main(my_special_function) Traceback (most recent call last): File stdin, line 1, in module File stdin, line 2, in main File stdin, line 2, in my_special_function ZeroDivisionError: integer division or modulo by zero If your code has only one anonymous function (whether a lambda or a full multi-line block), then it's easy to identify which lambda raised the exception: there is only one it could be. But if your code uses lots of lambdas, the lack of a function name makes it hard to distinguish one lambda from another lambda. Anonymity makes identification harder. * Risk of code-duplication and breaking the principle of Once And Only Once. Anonymous functions are generally created, used, then immediately thrown away -- or at least made more-or-less inaccessible for reuse. An anonymous function stored in a callback still exists, but the coder isn't able to easily re-use it for another callback somewhere else in the code. Consequently, there's a temptation for the coder to write the same function multiple times: add_button(Parrot, colour=blue, callback=lambda x: x.stuff('a')) add_button(Cheese, flavour=tasty, callback=lambda x: x.thing('b')) add_button(Canary, colour=yellow, callback=lambda x: x.stuff('a')) instead of: def bird_callback(x): return x.stuff('a') add_button(Parrot, colour=blue, callback=bird_callback) add_button(Cheese, flavour=tasty, callback=lambda x: x.thing('b')) add_button(Canary, colour=yellow, callback=bird_callback) * Recursion is more or less impossible without fragile tricks. (At least for Python. I don't know how recursion operates in Ruby.) -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Friday 31 July 2009 18:54:23 Tim Rowe wrote: 2009/7/31 Steven D'Aprano st...@remove-this-cybersource.com.au: On Thu, 30 Jul 2009 18:47:04 +0100, Tim Rowe wrote: 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! We don't actually *declare* that something is constant and then have that declaration ignored. Python doesn't lie to us, although (as in any language) a programmer might. You could say that Ruby doesn't either, you just need to read the documentation. Ruby's unwritten motto is flexibility über alles. In this regard, it is consistent (1). Not much is really bolted down in Ruby. You get encapsulation, but it's so easy to break that it's mostly symbolic. It's a language which gives great power to the programmer. Whether Ruby programmers handle this power responsibly is another debate. Cheers, Emm (1) I find Ruby to be pretty consistent in general, which is not always the case of Python. -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On 31 Jul 2009, at 20:17 , Steven D'Aprano wrote: On Fri, 31 Jul 2009 18:15:15 +0200, Masklinn wrote: I know, I know, Ruby people swear by anonymous code blocks, and I've read Paul Graham too. But I'm really not so sure that the benefits of anonymous code blocks are great enough to overcome the disadvantages of anonymous code blocks. What are the disadvantages of anonymous functions? In no particular order, and not necessarily exhaustive: * The risk of obfuscation in your code. That's fairly minimal for lambdas, because they're just a single expression, but for a large anonymous code block (ACB) defined inside a named function, it may be difficult for the reader to easily distinguish which bits are the outer function and which are the ACB. I believe that one's unadulterated BS. * Loss of useful debugging information. Take this example from Python: def main(f): ... return f(3) ... main(lambda n: 2/(n-3)) Traceback (most recent call last): File stdin, line 1, in module File stdin, line 2, in main File stdin, line 1, in lambda ZeroDivisionError: integer division or modulo by zero def my_special_function(n): ... return 2/(n-3) ... main(my_special_function) Traceback (most recent call last): File stdin, line 1, in module File stdin, line 2, in main File stdin, line 2, in my_special_function ZeroDivisionError: integer division or modulo by zero If your code has only one anonymous function (whether a lambda or a full multi-line block), then it's easy to identify which lambda raised the exception: there is only one it could be. But if your code uses lots of lambdas, the lack of a function name makes it hard to distinguish one lambda from another lambda. Anonymity makes identification harder. The traceback gives you the line of the anonymous function (even in python) so unless you have several anonymous functions on the same line, there's no reason why that would be much of an issue. Furthermore, Python doesn't provide any more information when the error happens out of a function (in a `for` or a `with`), so it's not like there's much of a difference here between Ruby's block-based approach and Python's statements-based approach. * Risk of code-duplication and breaking the principle of Once And Only Once. Anonymous functions are generally created, used, then immediately thrown away -- or at least made more-or-less inaccessible for reuse. An anonymous function stored in a callback still exists, but the coder isn't able to easily re-use it for another callback somewhere else in the code. Consequently, there's a temptation for the coder to write the same function multiple times: add_button(Parrot, colour=blue, callback=lambda x: x.stuff('a')) add_button(Cheese, flavour=tasty, callback=lambda x: x.thing('b')) add_button(Canary, colour=yellow, callback=lambda x: x.stuff('a')) instead of: def bird_callback(x): return x.stuff('a') add_button(Parrot, colour=blue, callback=bird_callback) add_button(Cheese, flavour=tasty, callback=lambda x: x.thing('b')) add_button(Canary, colour=yellow, callback=bird_callback) Yes, that one I can give you though I don't think that's a big issue. And it's not like it's hard to extract the anonymous function into a named one and then use that on the third strike, so I really don't believe that point holds much water. * Recursion is more or less impossible without fragile tricks. (At least for Python. I don't know how recursion operates in Ruby.) Code blocks are rarely if ever used recursively. If an operation is using anonymous functions recursively, then there's often something very wrong with the idea leading to that code. So I find this objection irrelevant. -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Fri, 31 Jul 2009 20:41:12 +0200, Emmanuel Surleau wrote: We don't actually *declare* that something is constant and then have that declaration ignored. Python doesn't lie to us, although (as in any language) a programmer might. You could say that Ruby doesn't either, Well you could say a lot of things. Admittedly you don't need a separate constant declaration, but creating a variable name with an initial uppercase letter is sufficient to make it a (supposed) constant: irb(main):049:0* Thing = 5 = 5 irb(main):050:0 Thing = 7 (irb):50: warning: already initialized constant Thing = 7 As you can see, Ruby (well, irb at least) considers that Thing is a constant, and then goes ahead and changes it anyway. Apart from the use of an arbitrary naming convention instead of an explicit make this constant declaration, and the feeble way Ruby capitulates when you change it, I think having actual write-once constants is actually a plus. you just need to read the documentation. Ruby's unwritten motto is flexibility über alles. In this regard, it is consistent (1). It's consistent in its inconsistency sort of thing perhaps? Not much is really bolted down in Ruby. You get encapsulation, but it's so easy to break that it's mostly symbolic. Out of curiosity, can you read/write class and instance attributes from outside the class without using a getter/setter? -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Saturday 01 August 2009 03:46:12 Steven D'Aprano wrote: On Fri, 31 Jul 2009 20:41:12 +0200, Emmanuel Surleau wrote: We don't actually *declare* that something is constant and then have that declaration ignored. Python doesn't lie to us, although (as in any language) a programmer might. You could say that Ruby doesn't either, Well you could say a lot of things. Admittedly you don't need a separate constant declaration, but creating a variable name with an initial uppercase letter is sufficient to make it a (supposed) constant: *shrugs* I see it as a way to encourage (but not force) people to follow a coding convention. Is this such a bad thing? irb(main):049:0* Thing = 5 = 5 irb(main):050:0 Thing = 7 (irb):50: warning: already initialized constant Thing = 7 As you can see, Ruby (well, irb at least) considers that Thing is a constant, and then goes ahead and changes it anyway. I'm quite aware of how constants work in Ruby, yes :) Apart from the use of an arbitrary naming convention instead of an explicit make this constant declaration, and the feeble way Ruby capitulates when you change it, I think having actual write-once constants is actually a plus. Nothing wrong with naming conventions. This encourages a uniform coding style, something which Python could really use. you just need to read the documentation. Ruby's unwritten motto is flexibility über alles. In this regard, it is consistent (1). It's consistent in its inconsistency sort of thing perhaps? No, just consistent. Not much is really bolted down in Ruby. You get encapsulation, but it's so easy to break that it's mostly symbolic. Out of curiosity, can you read/write class and instance attributes from outside the class without using a getter/setter? If you have an instance f class with a attribute @foo which doesn't have an accessor, you could do: f.instance_eval(@foo='bar') And yes, instance_eval is evil. Cheers, Emm -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
r wrote: 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 -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On 30 Jul 2009, at 06:04 , alex23 wrote: On Jul 30, 1:06 pm, r rt8...@gmail.com wrote: 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...)? As chris pointed out, there's a method for that, to which a symbol is provided: `Object#method(methodname)`, which is basically equivalent to `getattr(object, methodname)` in Python. 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] The issue here is of course that `map` and comprehensions are transformations. `#each` exists for effectful iterations (Ruby has `#map` for the map operation). So the intent expressed by `#each` and `map` isn't the same. Furthermore and this is the most problematic limitation of Python here, `lambda` doesn't allow complex transformations due to its restrictions, so one has to switch to named functions which works but isn't sexy (and tends to lower readability imo). 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. That's an interesting point, but not relevant at the end of the day: `foo.length` and `length(foo)` have the same practicality. On the other hand Ruby can be praised for the coherence: everything's a method period end of the story; while Python does have a dichotomy between methods and functions/generic methods (whether or not that dichotomy bothers users is another issue). 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(). Well interestingly, Ruby works pretty much the same way. Where Python asks that you implement the iterator protocol to have `max` work, Ruby asks that you implement the `each` method (also called the Enumerable protocol) and mixin `Enumerable` (http://ruby-doc.org/core/classes/Enumerable.html ). Then you get max (and min, map, etc…) for free. Of course you're free to re-implement all of them manually if you wish to do so (or if you need those operations to return your custom collection rather than arrays). Enumerable is merely a convenience mixin. So there's no big difference here (and note that mixins aren't necessarily part of the inheritance chain, though they're implemented that way in Ruby). Also, it's voilà not viola (a viola is a bowed string instrument, slightly bigger than a violin, whereas voilà is a french interjection used to call attention or suggest the appearance of something, as if by magic). 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?! I fear I'll have to agree with that sentiment. -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
Masklinn wrote: ... That's an interesting point, but not relevant at the end of the day: `foo.length` and `length(foo)` have the same practicality. On the other hand Ruby can be praised for the coherence: everything's a method period end of the story; while Python does have a dichotomy between methods and functions/generic methods (whether or not that dichotomy bothers users is another issue). ... 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 -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
superpollo wrote: Masklinn wrote: ... That's an interesting point, but not relevant at the end of the day: `foo.length` and `length(foo)` have the same practicality. On the other hand Ruby can be praised for the coherence: everything's a method period end of the story; while Python does have a dichotomy between methods and functions/generic methods (whether or not that dichotomy bothers users is another issue). ... 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 -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On 30 Jul 2009, at 14:03 , superpollo wrote: Masklinn wrote: ... That's an interesting point, but not relevant at the end of the day: `foo.length` and `length(foo)` have the same practicality. On the other hand Ruby can be praised for the coherence: everything's a method period end of the story; while Python does have a dichotomy between methods and functions/generic methods (whether or not that dichotomy bothers users is another issue). ... 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. -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
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] -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Jul 29, 9:06 pm, r rt8...@gmail.com wrote: 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 -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Jul 30, 12:04 am, alex23 wuwe...@gmail.com wrote: On Jul 30, 1:06 pm, r rt8...@gmail.com wrote: 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...)? 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. :) -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Jul 30, 11:31 am, Falcolas garri...@gmail.com wrote: On Jul 29, 9:06 pm, r rt8...@gmail.com wrote: 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 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. -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On 30 Jul 2009, at 18:31 , Falcolas wrote: On Jul 29, 9:06 pm, r rt8...@gmail.com wrote: 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 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. -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On 30 Jul 2009, at 19:01 , Inky 788 wrote: On Jul 30, 12:04 am, alex23 wuwe...@gmail.com wrote: On Jul 30, 1:06 pm, r rt8...@gmail.com wrote: 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...)? 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. -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Jul 30, 12:15 pm, Masklinn maskl...@masklinn.net wrote: [snip] 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 -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
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 -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
r wrote: On Jul 30, 11:31 am, Falcolas garri...@gmail.com wrote: On Jul 29, 9:06 pm, r rt8...@gmail.com wrote: 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 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 -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Jul 30, 12:37 pm, Jean-Michel Pichavant jeanmic...@sequans.com wrote: r wrote: On Jul 30, 11:31 am, Falcolas garri...@gmail.com wrote: On Jul 29, 9:06 pm, r rt8...@gmail.com wrote: 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 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 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! -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
r wrote: 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 -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
2009/7/30 r rt8...@gmail.com: 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! -- Tim Rowe -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On 30 Jul 2009, at 19:37 , Jean-Michel Pichavant wrote: r wrote: On Jul 30, 11:31 am, Falcolas garri...@gmail.com wrote: On Jul 29, 9:06 pm, r rt8...@gmail.com wrote: 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 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 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. -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On 30 Jul 2009, at 19:42 , Carsten Haese wrote: r wrote: 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? 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. -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
r wrote: On Jul 30, 12:15 pm, Masklinn maskl...@masklinn.net wrote: [snip] 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 how to reverse a string in python? must i usa a temp? like: s = ciccio l = list(s) l.reverse() s = .join(l) s 'oiccic' ??? bye -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Jul 30, 11:56 am, Masklinn maskl...@masklinn.net wrote: On 30 Jul 2009, at 19:37 , Jean-Michel Pichavant wrote: r wrote: 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. 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. 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. 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. -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
Tim Rowe wrote: 2009/7/30 r rt8...@gmail.com: 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 doesn't the decimal module do some of that too? bye -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On 30 Jul 2009, at 20:05 , superpollo wrote: r wrote: On Jul 30, 12:15 pm, Masklinn maskl...@masklinn.net wrote: [snip] 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 how to reverse a string in python? must i usa a temp? like: s = ciccio l = list(s) l.reverse() s = .join(l) s 'oiccic' ??? bye s = s[::-1] -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On 30 Jul 2009, at 20:06 , Falcolas wrote: On Jul 30, 11:56 am, Masklinn maskl...@masklinn.net wrote: On 30 Jul 2009, at 19:37 , Jean-Michel Pichavant wrote: r wrote: 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. 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. 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. 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) -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
MRAB wrote: superpollo wrote: ... how to reverse a string in python? must i usa a temp? like: s = ciccio l = list(s) l.reverse() s = .join(l) s 'oiccic' ??? Use slicing with a step of -1: s = ciccio s[::-1] 'oiccic' lol bye -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
30-07-2009 o 13:36:49 Masklinn maskl...@masklinn.net wrote: On 30 Jul 2009, at 06:04 , alex23 wrote: On Jul 30, 1:06 pm, r rt8...@gmail.com wrote: 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] The issue here is of course that `map` and comprehensions are transformations. `#each` exists for effectful iterations (Ruby has `#map` for the map operation). So the intent expressed by `#each` and `map` isn't the same. Furthermore and this is the most problematic limitation of Python here, `lambda` doesn't allow complex transformations due to its restrictions, so one has to switch to named functions which works but isn't sexy (and tends to lower readability imo). I don't see any real limitation. What's wrong in: for localVar in container: block And ruby's container.each is very similar to Python's iter() *j -- Jan Kaliszewski (zuo) z...@chopin.edu.pl -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On 30 Jul 2009, at 22:23 , Jan Kaliszewski wrote: 30-07-2009 o 13:36:49 Masklinn maskl...@masklinn.net wrote: On 30 Jul 2009, at 06:04 , alex23 wrote: On Jul 30, 1:06 pm, r rt8...@gmail.com wrote: 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] The issue here is of course that `map` and comprehensions are transformations. `#each` exists for effectful iterations (Ruby has `#map` for the map operation). So the intent expressed by `#each` and `map` isn't the same. Furthermore and this is the most problematic limitation of Python here, `lambda` doesn't allow complex transformations due to its restrictions, so one has to switch to named functions which works but isn't sexy (and tends to lower readability imo). I don't see any real limitation. What's wrong in: for localVar in container: block Well what's wrong with using that rather than `map`, `filter` or a list comprehension? (and if you don't see what the limitations of `lambda` are, you probably very rarely use it) And ruby's container.each is very similar to Python's iter() Uh… not at all… -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
superpollo wrote: r wrote: how to reverse a string in python? must i usa a temp? like: s = ciccio l = list(s) l.reverse() s = .join(l) s 'oiccic' ??? No. ''.join(list(reversed('abc'))) 'cba' 'abc'[2::-1] 'cba' 'abc'[10::-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 -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Jul 30, 3:55 pm, Terry Reedy tjre...@udel.edu wrote: superpollo wrote: 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. -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
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 -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Thursday 30 July 2009 04:41:57 pm Masklinn wrote: On 30 Jul 2009, at 22:23 , Jan Kaliszewski wrote: 30-07-2009 o 13:36:49 Masklinn maskl...@masklinn.net wrote: I don't see any real limitation. What's wrong in: for localVar in container: block 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) And ruby's container.each is very similar to Python's iter() 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. -- Luis Zarrabeitia (aka Kyrie) Fac. de Matemática y Computación, UH. http://profesores.matcom.uh.cu/~kyrie -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Jul 30, 4:57 pm, Luis Zarrabeitia ky...@uh.cu wrote: [snip] 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..., -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On 2009-07-30 16:44, r wrote: On Jul 30, 4:29 pm, Emmanuel Surleauemmanuel.surl...@gmail.com wrote: 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? 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 -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
2009/7/30 superpollo u...@example.net: Tim Rowe wrote: 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 doesn't the decimal module do some of that too? Not as far as I can tell, no. -- Tim Rowe -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
r wrote: On Jul 30, 3:55 pm, Terry Reedy tjre...@udel.edu wrote: superpollo wrote: 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 -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Thu, 30 Jul 2009 17:57:48 -0400, Luis Zarrabeitia wrote: 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} I don't think each is a particularly compelling example of Ruby's blocks - as you say, it's easily replaceable with a Python for-loop. The advantage of Ruby's syntax is that it allows you to define further functions that are sort-of like new control structures. So you have things like: File.open('myfile', 'r') do |file| while line = file.gets puts line end end Which is like a python's: with open('myfile', 'r) as f: for line in f: print f However, with Ruby, this kind of scoping construct can be added without adding new syntax. Another interesting example is the Sinatra web framework, which allows you to write a web app with something like: get '/' do Index page end post '/:name' do Posted to + params[:name] end Which looks something like a DSL for web apps, but is accomplished solely with normal ruby functions. More: http://www.sinatrarb.com/intro.html Ruby blocks are, fundamentally, syntactic sugar, but they are kind of neat. -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Friday 31 July 2009 01:06:31 Robert Kern wrote: On 2009-07-30 16:44, r wrote: On Jul 30, 4:29 pm, Emmanuel Surleauemmanuel.surl...@gmail.com wrote: 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? 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. 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 -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Jul 30, 1:06 pm, r rt8...@gmail.com wrote: 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.) -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Wed, Jul 29, 2009 at 9:04 PM, alex23wuwe...@gmail.com wrote: On Jul 30, 1:06 pm, r rt8...@gmail.com wrote: 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...)? 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 -- http://blog.rebertia.com -- http://mail.python.org/mailman/listinfo/python-list
Re: Confessions of a Python fanboy
On Jul 29, 9:04 pm, alex23 wuwe...@gmail.com wrote: On Jul 30, 1:06 pm, r rt8...@gmail.com wrote: 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 -- http://mail.python.org/mailman/listinfo/python-list