Perl, Haskell, stuff
I've never studied Python, but I'd quite like to at some point in the future. It seems very much like Perl with a different set of design criteria. Yeah, there are differences, but compare with C, Lisp, COBOL, and you can see why Perl and Python are clustered together in the "P languages" (Perl/Python/P^HRuby etc.)
Actually, that's one of the main reasons I've not expended signifant effort into learning Python - I can hurt my brain far more by trying to learn C or Haskell. But I'm sure it would be a good thing to do at some point. Here are a few notes on first impressions: these are just that, impressions, and may not be factually accurate: if you want to know full and correct details about Python, there are many excellent blogs that will clarify.
2008-09-25 Thanks for the excellent comments, I'll fold in corrections below!
(2008-09-25: Bill Mill points out that map remains; reduce got moved to Standard Lib, as comprehensions already do the right thing; and grep doesn't exist. Is that called "filter" in Python? Of course comprehensions can already to map/grep too)
On the other hand, python has list comprehensions which work equally well on lazy generators! Very nice indeed. It also has a much fuller destructuring bind than Perl's (which only works on single-level lists). So some good, some bad, and some interesting syntax and features. I doubt there's a clear "winner", some more discussion on Perl/Python (via Lisp of course) in Paul Graham's Revenge of the Nerds post.
Oh, and Python has continuations! With a builtin yield command. Perl has the Coro module, which is a fantastic piece of work, but rather complicated with confusing documentation. The yield command itself is in Coro::Generator but it has a number of limitations, like not being able to clone a continuation. There was a lovely post on creating monadic "do-notation" using continuations only, and I ported it to Perl with much swearing only to find that though it worked great for simple monads, it failed utterly for the List monad (important as it's what list comprehensions are built on) precisely because of this. Apparently the Perl internals don't really mesh with this, so it's unlikely that we'll be getting it for Perl 5 any time soon. Point to Python.
(2008-09-25: dolio points out I'm confusing generators and coroutines. Yup, I do that, sorry! I think one can be implemented in terms of each other (and vice-versa?), and that some literature does also blur the distinction, but could be wrong about that too? And yes, Ruby has callcc, but apparently the Monad example I was reading can't be easily ported to Ruby because the continuations/coroutines/thingies generated by yield aren't clonable)
Will on Geekup posted some nice examples of "declarators on attributes", which I think are similar to lvalue tied methods, but look rather better designed. (From Damian Conway's talk Contextual::Return may fix the problems Perl has with this kind of nice syntax. I say may as with Damian's talks it's hard to tell whether they truly are a massive advance in usability and functionality or crack-fueled insanity). Actually, declarators deserve their own section:
But talking about declarators, I have to ask:
Some differences I've heard mentioned include (with no figures or such to back them up...):
There is a constant meme that Python is somehow more "modern" than Perl. This is almost never qualified, I remember in this interesting book on programming language design that it was mentioned that the fact that Python's regular expressions lived in an external module was a more modern design that Perl's, which had them as builtins. Perhaps Perl not building in support for declarators and list comprehensions is more modern too? I'm sure if I say this often enough, it'll be a good substitute for actually making sense :-)
But Python does seem to get more buzz, with things like Google's AppEngine supporting Python before Perl. Hey ho. I still think that there are many more Perl jobs going, for what that's worth.
Off the top of my head, there's Twisted, Python's equivalent to POE; Django (Catalyst); and PyGame (possibly comparable to SDL_Perl?) as fairly high-profile complex libraries that show, to be honest, that both languages are pretty healthy with regards to module support.
(2008-09-25: Bill Mill points out PyPI link, and admits it's "still no CPAN, but it's coming along", which is more or less what I was trying to suggest ;-)
Osfameron's blog on Haskell, Perl programming, stuff.
dolio
September 25th, 2008 at 2:54 am
Are you sure Python has continuations? I was under the impression that it had generators (which your stuff about the 'yield' keyword seems to indicate you're talking about), but those are not full first-class continuations (and Coro sounds like coroutines, which are also not continuations).
It's possible that things have changed without my hearing about it, though (I don't watch Python very closely).
Ruby, for instance, has continuations (see Kernel#callcc or something of that sort).
Bill Mill
September 25th, 2008 at 5:30 am
> Things that you miss out on include multiline strings
errmmm... no you don't.
def foobar(): return """this is a long string that is triple-quoted therefore it is a multiline string"""
Bill Mill
September 25th, 2008 at 5:36 am
> Guido wanted to remove (I think) reduce, grep, map from the core language, and there was much gnashing of teeth.
Nope, reduce got moved to the standard library instead of the builtin functions because list comprehensions are now the built-in way to perform reduces. map() is still in the builtins and there's never been a grep() function, I'm not sure what you're talking about there.
> CPAN is a big advantage for the Perl community
PyPI is still no CPAN, but it's coming along.
Pawel Murias
September 25th, 2008 at 10:02 am
lambda's in python don't really mix with the indentation oriented syntax, the none-deprecated equivalent is def somename(): pass foo(somename)
if you can make up enough meaningfull names, it's better ;)
GTof
September 25th, 2008 at 12:37 pm
About Python, Ruby and the monads, i think it's the opposite. Monads on Ruby are very simple thanks to http://github.com/aanand/ruby-do-notation/tree/master and the blocks of Ruby. The impementation in http://www.valuedlessons.com/2008/01/monads-in-python-with-nice-syntax.html have two problem :
1 - he copies the generator by replaying it from the beginng, it's not very efficient. 2 - lambdas in python are restraint to only expression
Furthermore when trying to implement monad in Python i noticed some more issues. Imagine you want a function :
def foo(a): return do x >= (lamnda x : N(a))
'a' occrus in a lambda in an expression, that's bad !
I tried to use the same technique as in Ruby but cecause of the complexity of the Python bytecode i gaved up.
If you want you can use the code i've done to simulate do-notation. It works but code need to be in strings which are parsed, transformed and interpreded. it's not as beatiful as in Ruby.
#
THE DO NOTATION
#
import re import compiler
PARSE ASSIGNMENT "x <- m"
doasgn = re.compile(r"^\s(\w+)\s> (" + dolist(l[1:]) + ")")
TRANSORM A DO BLOCK INTO A BIND EXPRESSION
do = lambda s : dolist(dostmt.findall(s))
COMPILE A DO BLOCK INTO A CODE EXPRESSION
cdo = lambda s : compiler.compile(do(s),'compiledo.py','eval')
PYTHON HAS PROBLEMS TO SEE LOCAL VARIABLES WHEN EVALUATING :
#
def test(x) :
return eval(do("""
List.mreturn(x)
""")
#
print test(5).run()
#
Will give the good result but :
#
def test(x) :
return eval(do("""
y <- .....
List.mreturn(x)
""")
#
print test(5).run()
#
Will give the error : NameError: global name 'x' is not defined
To avoid that, we build a closure from the list of local variables
with (lambda x : ...)(locals()["x"])
So x is in the context of the expression with the good value in locals
def closure(v,m): l = v for x in m.keys() : l = "((lambda " + x + " : " + l + ")(m[\"" + x + "\"]))" return "(lambda m : " + l + ")"
JUST TO EVALUATE THE BLOCK
def rundo(g,l,s): return eval(closure(do(s),l),g,l)(l)
#
MONADES
#
class Monad: value=None def init(self,val): self.value=val
#
MONADE LISTE
#
def concat(x) : res = [] for y in x : res.extend(y) return res
class Liste(Monad): @staticmethod def mreturn(val) : return Liste([val])
def guard(b): if b : return Liste.mreturn(()) else : return Liste.zero()
EXEMPLES
test = eval(do(""" x <- Liste(["1" , "2" ]) y <- Liste(["3" , "4" ]) Liste.mreturn (x + " and " + y) """))
print test.value
Another point. Continuation and may yield be différent on one other point i think. When you want to use delimited continuation, i wonder if it's possible to implement shift/reset with yield. Maybe yes.
Good post anyway :)
Bill Mill
September 25th, 2008 at 5:38 pm
@dolio python 2.5 gained generators that can be sent values; this makes them isomorphic to coroutines.
Are coroutines isomorphic to continuations?
Bill Mill
September 25th, 2008 at 5:43 pm
> Is that called "filter" in Python?
ahha - yes. Guido likes filter when used with builtins, but thinks a list comp is clearer than filter with a lambda.
dolio
September 26th, 2008 at 2:08 am
Bill Mill: I'm relatively sure that continuations are more powerful than coroutines, although I don't have any specific examples.
Websites tagged "pygame" on Postsaver
October 3rd, 2008 at 10:32 am
[...] - "Osfameron": Some thoughts on Python saved by osoy232008-09-19 - Implementation Language saved by gaastra342008-09-19 - Making a [...]
Brock
October 6th, 2008 at 7:02 pm
Coroutines are "one-shot" continuations. That is, with full continuations you can re-activate the same bundle of state multiple times. With coroutines you can stop-and-bundle some state, but you can only resume it once.
Perl's Coro provides coroutines, not continuations.
Interestingly enough, for one interesting use of continuations -- inverting the control of web applications ala Seaside -- it turns out that coroutines are Good Enough (tm).
Sal
February 22nd, 2009 at 8:57 am
I think whitespace is most understood. It is usually seen as a gross feature when you start perusing the language. However once you are have some momentum and actually start using the language, you will come to realize that it is one of its strengths; Code just seems to flow and productivity increases. Long time Perl master Eric Raymond discovered this as well (http://www.linuxjournal.com/article/3882).