Re: Multi-line lambda proposal.
Kaz Kylheku enlightened us with: > Which proposed lambda syntax is closest in this sense? I was talking about different ways (your multi-line lambda vs. the currently implemented one) of doing function decorators. > Is it unusual to have a tougher time explaining X than Y to people > who are learning a language, where X and Y are different features? See above: same feature, function decorators. Sybren -- The problem with the world is stupidity. Not saying there should be a capital punishment for stupidity, but why don't we just take the safety labels off of everything and let the problem solve itself? Frank Zappa -- http://mail.python.org/mailman/listinfo/python-list
Re: Multi-line lambda proposal.
Duncan Booth wrote: > Kaz Kylheku wrote: > > > Duncan Booth wrote: > >> One big problem with this is that with the decorator the function has > >> a name but with a lambda you have anonymous functions so your > >> tracebacks are really going to suck. > > > > Is this an issue with this particular design that is addressed by > > other designs? > > Yes. Decorators don't interfere with the name of the underlying function > displayed in tracebacks. No, I mean do other multi-line lambda design fix this problem somehow? It looks to me like the programmer's choice, quite simply. Both programs shown by [EMAIL PROTECTED] use lambda. The first one uses a decorator to actually define the wrapped function: @arg_range(5, 17) def f(arg): return arg*2 The arg_range function uses a nesting of two lambdas, yet the decorated function still has a name that nicely shows up in tracebacks. So in other words, lambdas and decorators play along nicely. f = arg_range(5, 17, lambda(arg)): return arg*2 Here, the programmer made a decision to define a global function using an assigment operator instead of def. The underlying function is the lambda itself. That is not a problem with the multi-line lambda. A lambda feature is not even required to do create a version of this problem: foo = arg_range(5, 17, bar) Now the function is called as foo(), but what the programmer sees in the traceback is "bar", which is potentially confusing. The traceback will show that bar() is being called from some given file and line number, but when that is inspected, there is no bar() there, only an expression which contains the function call foo() (and possibly other calls). I'm only interested in discussing the relative merits of my multi-line lambda proposal versus others. I'm not interested in debating people who think that other people who want multi-line lambdas should not have them. I also hope that everyone understands that lambdas, multi-line or not, are not the best tool for every situation for which they are a possible candidate. I agree with that, and am not interested in debating it either. It's off topic to the question of designing that labmda, except insofar as the design of the lambda influences whether or not lambda is a good choice in a situation. I.e. "lambda is a bad choice for this situation if it is designed like this, but not (or less so) if it is designed like this." > > Are the existing one-line lambdas free from this problem? > > No, but since a single line lambda does virtually nothing it isn't as > serious. Decorators are useful enough that in some situation you might > decorate every method in a class (e.g. for a web application you might > apply security settings with decorators). In that situation you have just > messed up every stack frame in every traceback. The problem there is that the programmer uses anonymous functions for class methods, rather than decorating named class methods. (Are anonymous class methods even possible? Lambdas can take an object as their first argument, but that's not the same thing.) > I end up reading tracebacks quite a lot, and it is the sequence of the > function > names which matter first, I don't usually need to go and look at the file > and code lines. > > > > Let me make the observation that name of an inner function is, alone, > > insufficient to identify that function in a debugging scenario. If you > > have some inner function called I, defined within function F, you need > > to know that it's the I inside F, and not some other I. > > > If the stack frame shows I called from F then it is usually a pretty good > guess that it means the I inside F. "Pretty good guess" doesn't cut it. Fact is, that the identities of these functions are not unambiguously pinned down by their name alone; moreover, the line number and file information alone actually does precisely pinpoint the location of the exception. If only the names of functions appeared in the traceback, it would be less useful. If foo calls bar in three different places, you would not know which of those three places is responsible for the call of bar from foo. Moreover, in the bottom-most frame, you would not know which line in the function actually triggered the traceback. So I do not believe your claim that you rarely need to look at the line number information when comprehending tracebacks. -- http://mail.python.org/mailman/listinfo/python-list
Re: Multi-line lambda proposal.
Terry Reedy wrote: > So name it err_inner. Or _err. Right. The C language approach to namespaces. -- http://mail.python.org/mailman/listinfo/python-list
Re: Multi-line lambda proposal.
"Kaz Kylheku" <[EMAIL PROTECTED]> wrote in message news:[EMAIL PROTECTED] > Let me make the observation that name of an inner function is, alone, > insufficient to identify that function in a debugging scenario. If you > have some inner function called I, defined within function F, you need > to know that it's the I inside F, and not some other I. > > Look at what happens with: > def err(): > ... def inner(): > ... return nonexistent > ... return inner > ... err() > err()() > Traceback (most recent call last): > File "", line 1, in ? > File "", line 3, in inner > NameError: global name 'nonexistent' is not defined So name it err_inner. Or _err. tjr -- http://mail.python.org/mailman/listinfo/python-list
Re: Multi-line lambda proposal.
Kaz Kylheku wrote: > Duncan Booth wrote: >> One big problem with this is that with the decorator the function has >> a name but with a lambda you have anonymous functions so your >> tracebacks are really going to suck. > > Is this an issue with this particular design that is addressed by > other designs? Yes. Decorators don't interfere with the name of the underlying function displayed in tracebacks. > > Are the existing one-line lambdas free from this problem? No, but since a single line lambda does virtually nothing it isn't as serious. Decorators are useful enough that in some situation you might decorate every method in a class (e.g. for a web application you might apply security settings with decorators). In that situation you have just messed up every stack frame in every traceback. > > Is there really a problem? The Python tracebacks identify every frame > by file and line number, as well as name, if one is available. Great, and I suppose that if they printed out the line numbers in binary that wouldn't make it harder to understand the traceback either. I end up reading tracebacks quite a lot, and it is the sequence of the function names which matter first, I don't usually need to go and look at the file and code lines. > > Let me make the observation that name of an inner function is, alone, > insufficient to identify that function in a debugging scenario. If you > have some inner function called I, defined within function F, you need > to know that it's the I inside F, and not some other I. > If the stack frame shows I called from F then it is usually a pretty good guess that it means the I inside F. Besides, I don't usually name all my inner functions I; I find that giving them meaningful names tends to help. -- http://mail.python.org/mailman/listinfo/python-list
Re: Multi-line lambda proposal.
Sybren Stuvel wrote: > [EMAIL PROTECTED] enlightened us with: > > this is how I think it should be done with multi-line lambdas: > > > > def arg_range(inf, sup, f): > > return lambda(arg): > > if inf <= arg <= sup: > > return f(arg) > > else: > > raise ValueError > > This is going to be fun to debug if anything goes wrong. Ever seen > such a traceback? I'm looking at various tracebacks now. I don't see any special problems with lambdas. Inner functions are inadequately identified, so that the file and line number has to be used, which works just as well as for lambdas. > A function decorator is supposed to add something to a function. The > syntax that sticks the closest to that of defining a function seems > most Pythonic to me. Which proposed lambda syntax is closest in this sense? > I can already foresee that I'll have a tougher time explaining your > lambda-based "decorators", than the current decorators, to people > learning Python. Is it unusual to have a tougher time explaining X than Y to people who are learning a language, where X and Y are different features? For instance, an assignment statement is easier to explain than a metaclass. Therefore, assignment statements are probably going to be covered in an earlier lecture of a Python course than metaclasses. In what language are features equally easy to explain? It's possible to use Python while pretending that lambdas don't exist at all. (That's true of the lambda in its current form, as well as the proposed forms). -- http://mail.python.org/mailman/listinfo/python-list
Re: Multi-line lambda proposal.
Duncan Booth wrote: > One big problem with this is that with the decorator the function has a > name but with a lambda you have anonymous functions so your tracebacks are > really going to suck. Is this an issue with this particular design that is addressed by other designs? Are the existing one-line lambdas free from this problem? Is there really a problem? The Python tracebacks identify every frame by file and line number, as well as name, if one is available. Let me make the observation that name of an inner function is, alone, insufficient to identify that function in a debugging scenario. If you have some inner function called I, defined within function F, you need to know that it's the I inside F, and not some other I. Look at what happens with: >>> def err(): ... def inner(): ... return nonexistent ... return inner ... >>> err() >>> err()() Traceback (most recent call last): File "", line 1, in ? File "", line 3, in inner NameError: global name 'nonexistent' is not defined In the traceback, the programmer is told that the error occured in a function called inner. However, there could be many functions called inner, including a global one. The programmer is not told that it's the function inner which is defined inside the function err, which could be done with some qualified name syntax like err.inner or whatever. So this piece of information is about as useful as being told that it was inside a lambda. The real key which lets the programmer correlate the error back to the source code is the file name and line number. When he locates that line of code, then it's obvious---aha---it is in the middle of an inner function called "inner", which also happens to be inside a global function called "err". -- http://mail.python.org/mailman/listinfo/python-list
Re: Multi-line lambda proposal.
[EMAIL PROTECTED] enlightened us with: > this is how I think it should be done with multi-line lambdas: > > def arg_range(inf, sup, f): > return lambda(arg): > if inf <= arg <= sup: > return f(arg) > else: > raise ValueError This is going to be fun to debug if anything goes wrong. Ever seen such a traceback? > and instead of > @arg_range(5, 17) > def f(arg): > return arg*2 > > you do: > f = arg_range(5, 17, lambda(arg)): > return arg*2 A function decorator is supposed to add something to a function. The syntax that sticks the closest to that of defining a function seems most Pythonic to me. I can already foresee that I'll have a tougher time explaining your lambda-based "decorators", than the current decorators, to people learning Python. Sybren -- The problem with the world is stupidity. Not saying there should be a capital punishment for stupidity, but why don't we just take the safety labels off of everything and let the problem solve itself? Frank Zappa -- http://mail.python.org/mailman/listinfo/python-list
Re: Multi-line lambda proposal.
[EMAIL PROTECTED] wrote: > this is how I think it should be done with multi-line lambdas: > > def arg_range(inf, sup, f): > return lambda(arg): > if inf <= arg <= sup: > return f(arg) > else: > raise ValueError > > and instead of > @arg_range(5, 17) > def f(arg): > return arg*2 > > you do: > f = arg_range(5, 17, lambda(arg)): > return arg*2 > > One big problem with this is that with the decorator the function has a name but with a lambda you have anonymous functions so your tracebacks are really going to suck. -- http://mail.python.org/mailman/listinfo/python-list
Re: Multi-line lambda proposal.
this is how I think it should be done with multi-line lambdas: def arg_range(inf, sup, f): return lambda(arg): if inf <= arg <= sup: return f(arg) else: raise ValueError and instead of @arg_range(5, 17) def f(arg): return arg*2 you do: f = arg_range(5, 17, lambda(arg)): return arg*2 -- http://mail.python.org/mailman/listinfo/python-list
Re: Multi-line lambda proposal.
Antoon Pardon wrote: > Could you give me an example. Suppose I have the following: > > def arg_range(inf, sup): > > def check(f): > > def call(arg): > if inf <= arg <= sup: > return f(arg) > else: > raise ValueError > > return call > > return check def arg_range(inf, sup) return lambda(f): return lambda(arg): if inf <= arg <= sup: return f(arg) else raise ValueError Nice; now I can see what this does: returns a function that, for a given function f, returns a function which passes its argument arg to f if the argument is in the [inf, sup] range, but otherwise raises a ValueError. The English description pops out from the nested lambda. The names in the inner-function version only serve to confuse. The function check doesn't check anything; it takes a function f and returns a validating function wrapped around f. In fact, an excellent name for the outer-most inner function is that of the outer function itself: def range_checked_function_maker(inf, sup): def range_checked_function_maker(f): def checked_call_of_f(arg): if inf <= arg <= sup: return f(arg) else: raise ValueError return checked_call_of_f return range_checked_function_maker This alone makes a good case for using an anonymous function: when you have a function which does nothing but return an object, and that function has some noun as its name, it's clear that the name applies to the returned value. This: def forty_two(): return 42 is not in any way made clearer by: def forty_two(): forty_two = 42 return forty_two :) -- http://mail.python.org/mailman/listinfo/python-list
Re: Multi-line lambda proposal.
Kaz Kylheku wrote: > Kaz Kylheku wrote: > > But suppose that the expression and the multi-line lambda body are > > reordered? That is to say, the expression is written normally, and the > > mlambda expressions in it serve as /markers/ indicating that body > > material follows. This results in the most Python-like solution. > > Unfortunately, while this idea has intuitive appeal, It does? Didn't seem so in the responses you got so far, did it... ;-) SCNR > it leaves some > problems to solve; namely, lambdas that occur in expressions embedded > within statement syntax which has body material of its own. For > instance > > # lambda defined and immediately called here > if lambda(x)(4) < 0: > print "a" > elif y = 4: > print "b" > else: > print "foo" > > Where to stick the lambda body? It's not hard to come up with > straightforward answers, except that they are not particularly > appealing. One rule might be that the lambda bodies have to be placed > immediately after the statement body material, set off by the lambda: > thing. In the case of if/elif/else, they have to be placed behind the > closest suite that follows the expression in the syntax of the > statement: > > if lambda(x)(4) < 0: > print "a" > lambda: > return x + 1 > elif y = 4: > print "b" > else: > print "foo" > > The overall rule is simple and uniform: each suite can have lambda: > clauses. These have to match lambda() occurences in the expression (or > expression list) immediately to the left in the same grammar > production. Sorry to tell you this, but I think that kind of thing is exactly what the BDFL had in mind when he talked about "Rube-Goldberg-Devices" in Python... -- http://mail.python.org/mailman/listinfo/python-list
Re: Multi-line lambda proposal.
Op 2006-05-10, [EMAIL PROTECTED] schreef <[EMAIL PROTECTED]>: > multi-line lambdas, had it been added to python a long time ago, would > had reduced a lot of complexity in the language. > for example - with multi-line lambdas - decorators are unneccesary. I don't like the words neccesary or unneccesary in these discussions, because they rarely add anything. For instances decorators are unneccesary in python now, even without multi-line lambdas. There is nothing you can do with decorators that you can't do without. > just give the multi-line lambda as an argument to a function - no need > for special syntax.. There is no need for special syntax. The decorators are just syntactic sugar to do something that was already possible before. > the alternative decorators would also be simpler. > currently when you want to create a "decorator-that-accepts-additional- > arguments" you gotta make a funtion that gets those > additional-arguments and returns a function that will be the decorator. Could you give me an example. Suppose I have the following: def arg_range(inf, sup): def check(f): def call(arg): if inf <= arg <= sup: return f(arg) else: raise ValueError return call return check @arg_range(3, 12) def func(arg): return arg How would this look simpler with multi-line lambda's? -- Antoon Pardon -- http://mail.python.org/mailman/listinfo/python-list
Re: Multi-line lambda proposal.
[EMAIL PROTECTED] enlightened us with: > multi-line lambdas, had it been added to python a long time ago, > would had reduced a lot of complexity in the language. for example > - with multi-line lambdas - decorators are unneccesary. I love decorators. > just give the multi-line lambda as an argument to a function - no > need for special syntax.. Ehm... multi-line lamda /is/ a special syntax. > the alternative decorators would also be simpler. currently when > you want to create a "decorator-that-accepts-additional- arguments" > you gotta make a funtion that gets those additional-arguments and > returns a function that will be the decorator. A bit tricky, but so far easier to understand than the multi-line lambda tricks proposed. Sure, it's a function that returns a function that returns a function, but still except for the @ it's syntactically "just Python". Sybren -- The problem with the world is stupidity. Not saying there should be a capital punishment for stupidity, but why don't we just take the safety labels off of everything and let the problem solve itself? Frank Zappa -- http://mail.python.org/mailman/listinfo/python-list
Re: Multi-line lambda proposal.
multi-line lambdas, had it been added to python a long time ago, would had reduced a lot of complexity in the language. for example - with multi-line lambdas - decorators are unneccesary. just give the multi-line lambda as an argument to a function - no need for special syntax.. the alternative decorators would also be simpler. currently when you want to create a "decorator-that-accepts-additional- arguments" you gotta make a funtion that gets those additional-arguments and returns a function that will be the decorator. -- http://mail.python.org/mailman/listinfo/python-list
Re: Multi-line lambda proposal.
Kaz Kylheku enlightened us with: > In the case of if/elif/else, they have to be placed behind the > closest suite that follows the expression in the syntax of the > statement: > > if lambda(x)(4) < 0: > print "a" > lambda: > return x + 1 > elif y = 4: > print "b" > else: > print "foo" > > The overall rule is simple and uniform: each suite can have lambda: > clauses. These have to match lambda() occurences in the expression > (or expression list) immediately to the left in the same grammar > production. IMHO I think it's ugly and unreadable. If you use it in such a way, a much more elegant way would be to use an inner function: def increment(x): return x + 1 if increment(4) < 0: print "a" elif y = 4: print "b" else: print "foo" This also solves the readability issue when there are multiple multi-line lambdas involved. Just write a couple of inner functions neatly under each other, and call them by name. From my point of view, that's much more readable, and if there is any error, it'll be much easier to find due to proper tracebacks. > On the other hand, some people might find this compromise more > attractive: simply do not allow multi-line lambdas in compound > statements. I'm one of those people. I don't like multi-line lambdas at all, actually. Sybren -- The problem with the world is stupidity. Not saying there should be a capital punishment for stupidity, but why don't we just take the safety labels off of everything and let the problem solve itself? Frank Zappa -- http://mail.python.org/mailman/listinfo/python-list
Re: Multi-line lambda proposal.
DH wrote: > Kaz Kylheku wrote: > > I've been reading the recent cross-posted flamewar, and read Guido's > > article where he posits that embedding multi-line lambdas in > > expressions is an unsolvable puzzle. > > To say that multi-line lambda is an unsolvable problem is completely > absurd. Note that the "solution" is understood to entail the BDFL stamp of approval. Furthermore it has already been solved. > http://wiki.python.org/moin/AlternateLambdaSyntax#head-c81743c0b461ab6812564785c7bc7ba581dec6fa Meh. I think the syntax you linked to would result in gobs of ugly and unreadable code. I like how the examples are always part of relatively simple statements ("Look, it's readable!"). Try citing examples of these statements at work in if conditions, generator expressions, as default arguments to functions, multiple times in the same statement. Try showing what they look like nested. The "readable" example would turn into ASCII vomit. Probably the day it makes it into Python is the day Python jumps the shark. Carl Banks -- http://mail.python.org/mailman/listinfo/python-list
Re: Multi-line lambda proposal.
Kaz Kylheku wrote: > I've been reading the recent cross-posted flamewar, and read Guido's > article where he posits that embedding multi-line lambdas in > expressions is an unsolvable puzzle. To say that multi-line lambda is an unsolvable problem is completely absurd. Furthermore it has already been solved. http://wiki.python.org/moin/AlternateLambdaSyntax#head-c81743c0b461ab6812564785c7bc7ba581dec6fa So I agree with you, but I doubt you'll have any luck getting your proposal or any other multiline lambda proposal accepted into python anytime soon. -- http://mail.python.org/mailman/listinfo/python-list
Re: Multi-line lambda proposal.
Kaz Kylheku wrote: > But suppose that the expression and the multi-line lambda body are > reordered? That is to say, the expression is written normally, and the > mlambda expressions in it serve as /markers/ indicating that body > material follows. This results in the most Python-like solution. Unfortunately, while this idea has intuitive appeal, it leaves some problems to solve; namely, lambdas that occur in expressions embedded within statement syntax which has body material of its own. For instance # lambda defined and immediately called here if lambda(x)(4) < 0: print "a" elif y = 4: print "b" else: print "foo" Where to stick the lambda body? It's not hard to come up with straightforward answers, except that they are not particularly appealing. One rule might be that the lambda bodies have to be placed immediately after the statement body material, set off by the lambda: thing. In the case of if/elif/else, they have to be placed behind the closest suite that follows the expression in the syntax of the statement: if lambda(x)(4) < 0: print "a" lambda: return x + 1 elif y = 4: print "b" else: print "foo" The overall rule is simple and uniform: each suite can have lambda: clauses. These have to match lambda() occurences in the expression (or expression list) immediately to the left in the same grammar production. On the other hand, some people might find this compromise more attractive: simply do not allow multi-line lambdas in compound statements. -- http://mail.python.org/mailman/listinfo/python-list
Re: Multi-line lambda proposal.
Op 2006-05-09, Scott David Daniels schreef <[EMAIL PROTECTED]>: > Kaz Kylheku wrote: >> I've been reading the recent cross-posted flamewar, and read Guido's >> article where he posits that embedding multi-line lambdas in >> expressions is an unsolvable puzzle. >> >> So for the last 15 minutes I applied myself to this problem and come up >> with this off-the-wall proposal for you people. Perhaps this idea has >> been proposed before, I don't know. > > Well, ask yourself, what is the complexity, and what is the > benefit. You are solving a problem that causes very little > pain, and introducing a mechanism that is likely to inspire > thousands of lines of unmaintainable code. Essentially, a > rule that says, "if it is not a simple expression, pick a > name for it" is just not a bad idea. Well I guess that seems a good rule of thumb. The problem is that even a simple "expression" sometimes requires a name in python or turns it into a more complex function. Take the following example: def incr_cnt_by_one(obj): obj.cnt += 1 IMO that is simple enough not to require a name. But it is almost impossible to put this behaviour in a lambda. If you do you end up with something like: lambda obj: setattr(obj, 'cnt', obj.cnt + 1) So maybe a general lambda is indeed impossible in python. A pity IMO, but not that big a deal. But the limit that certain statements are not expressions makes that you sometimes require a name even with some simple stuff like: def Raise_ValueError(): raise ValueError RegisterErrorFunction(Raise_ValueError) What would be so horrible if we could do the following: RegisterErrorFunction(lambda: raise ValueError) or treat_all(aList, lambda obj: obj.cnt += 1) -- Antoon Pardon -- http://mail.python.org/mailman/listinfo/python-list
Re: Multi-line lambda proposal.
Kaz Kylheku enlightened us with: > I've been reading the recent cross-posted flamewar, and read Guido's > article where he posits that embedding multi-line lambdas in > expressions is an unsolvable puzzle. > [...] > a = lambda(x, y), lambda(s, t), lambda(u, w): u + w > statement1 > statement2 > lambda: > statement3 > statement4 I think it's a very ugly solution. If you need multiple lines in your lambda, use an inner function. If you need a couple of single-line lambdas and use them in a multi-line expression, assign them to a name and use that name in their stead. > a = lambda(x, y): > return x + y And what's the advantage of that above this? def a(x, y): return x + y > More examples: lambda defined in a function call argument > > a = foo(lambda (x, y)): > return x + y > > Confusing? Not if you read it properly. "A lambda function is > constructed with arguments x, y and passed to foo, and the result is > assigned to a. Oh, and by the way, the body of the > lambda is: return x + y." I think it's very, very ugly. Use inner functions for that. They are a much cleaner solution than this. Sybren -- The problem with the world is stupidity. Not saying there should be a capital punishment for stupidity, but why don't we just take the safety labels off of everything and let the problem solve itself? Frank Zappa -- http://mail.python.org/mailman/listinfo/python-list
Re: Multi-line lambda proposal.
Kaz Kylheku wrote: > But suppose that the expression and the multi-line lambda body are > reordered? That is to say, the expression is written normally, and the > mlambda expressions in it serve as /markers/ indicating that body > material follows. This results in the most Python-like solution. I think your proposal is good, but it might be more easily understood if we gave names to the lambdas, so that they could be easily picked out in the source code. It could look something like this: func(lambda foo): foo: print "Foo!" Come to think of it, maybe we could put the lambdas before the statement they're used in instead of in front of it. That could look something like this: lambda foo: print "Foo!" func(lambda foo) Then again, it would probably be simpler to reuse an existing block-starting keyword for the purpose. Maybe something like this? def foo(): print "Foo!" func(foo) -- http://mail.python.org/mailman/listinfo/python-list
Re: Multi-line lambda proposal.
Kaz Kylheku wrote: > I've been reading the recent cross-posted flamewar, and read Guido's > article where he posits that embedding multi-line lambdas in > expressions is an unsolvable puzzle. > > So for the last 15 minutes I applied myself to this problem and come up > with this off-the-wall proposal for you people. Perhaps this idea has > been proposed before, I don't know. Well, ask yourself, what is the complexity, and what is the benefit. You are solving a problem that causes very little pain, and introducing a mechanism that is likely to inspire thousands of lines of unmaintainable code. Essentially, a rule that says, "if it is not a simple expression, pick a name for it" is just not a bad idea. --Scott David Daniels [EMAIL PROTECTED] -- http://mail.python.org/mailman/listinfo/python-list