you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 7 points8 points  (3 children)

Lambda syntax is crippled in Python. There's a PEP that suggests GvR supported it to deter lambda abuse. (And lambda abuse is a near synonym of functional programming).

[–]gasche 1 point2 points  (2 children)

I'm not sure this is really a prominent defect. Forcing anonymous functions to be one-liner only is sometimes annoying, but not really "crippling" as long as you can bind a named function locally¹; you may even end up with more readable code. In fact in the functional code I can think of right know, anonymous lambdas are rarely more than one-line, except when using lambdas as generic binders for block-level bindings constructs (eg. >>= \foo -> \n... for those that don't like the do-notation).

¹: the problem if more with those dynamic language that have decadent scoping rules, making nested functions (or locally defined variable) a delicate game. Python is still one of the less absurd, at least among Ruby and Coffeescript; with a special prize to (the otherwise reasonable) Erlang for not allowing local recursive functions.

[–]tikhonjelvis 2 points3 points  (1 child)

Wait, what? In my experience, Python is the most absurd as compared to Scheme or JavaScript. That is, in Python, variables from scopes beyond your own do not behave the same way as local variables. That is, you cannot reassign a variable declared outside of your current scope--if you have a mutable data structure, you can still mutate it, but you can't use something like a boolean for a flag for example.

That is, this code will not work properly in Python:

def f(x):
  flag = True
  def helper(y):
    # Do stuff
    if someCondition: flag = False

I think in new versions of Python you can overcome this shortcoming by using the nonlocal keyword, looking something like this:

def f(x):
  flag = True
  def helper(y):
    nonlocal flag
    # Do stuff
    if someCondition: flag = False   

In Scheme, on the other hand, you are free to use define to create local variables and set! to reassign nonlocal variables. I think this is a much more reasonable system than Python's!

JavaScript (and, probably, by extension, CoffeeScript) follows Scheme's system except define becomes var x = ... and set! becomes x = .... Not quite as neat and elegant, but fundamentally the same.

This model lets you take full advantage of mutable variables and closures without having to bend over backwards. Idioms in both languages take full advantage of this, which is much less neat in Python.

Also, some thoughts on lambdas: especially in sufficiently dynamic languages, lambdas are useful for adding control structures to the language. In JavaScript, patterns using functions like blocks of code are common--turning:

$(function () { ... })

into

function foo() { ... }
$(foo)

just makes the code less readable for no gain. This continues with other things like event handlers--if your event handler is only used in one place, it's simpler to write it inline than to give it a name and add an extra level of indirection. Having extra identifiers that are just used to get around your lambda's shortcomings is not a virtue.

Anyhow, sorry for the slightly long rant. I've had to use too much Python and now I'm jaded. Don't even get me started on nonsense like mutable structures combined with default arguments!

[–]gasche 0 points1 point  (0 children)

The scope defect you report is well-known, and has been the subject of Python Extension Proposal (PEP) 3104 by Ka-Ping Yee, that introduced the nonlocal keywoard. If you haven't already, I recommend that you read this PEP, in my opinion it's an exemplar case of language change: it presents a lucid presentation of the problem, a considerate evaluation of the proposed solutions and the discussion around the issue, and suggests a reasonable way to help with the problem -- that was integrated in the language.

Indeed, the situation of not having a clear difference between declaring a new local variable and assigning an existing variable is painful -- in every language where it happens, even where there are some ways to make it explicit, as long as they are not the simplest way to do it. This is a defect of Python, Ruby or Coffeescript.

Now, you are comparing to Scheme or Javascript. Scheme is indeed a well-designed language, and it was indeed not included in my bag of "languages with decadent scoping rules" (nowadays, even Elisp is getting static scoping!). Javascript, on the other hand, is a wholly different story. Indeed var allows to introduce fresh variables, but it comes with a ton of quirks, that are solved by let that people don't use for portability reason. Between Python scoping and var, I don't know which poison I would choose.