In ruby, we can add a lambda function into a function call. but it's a little ugly: [1,2,3,4].each { |x| print x } but, it really convenient. current lambda only support single line syntax. it's not very good. maybe we can add a new syntax: call: primary "(" argument-list ")" [ "lambda" parameter-list ":" suite ] the postfix lambda will translate to a single "function" object, and pass to the &arg parameter of function. so the function call will become func(*arg1, **arg2, &arg3) for example, we can write this: def print_list(*lists, &func = lambda x: true): for item in lists: map(a) lambda x: if func(x): print x call with: print_list([1,2,3], [1,2]) lambda x: if x % 2: return True else return False
On 19 Oct 2009, at 15:33 , starwing wrote:
In ruby, we can add a lambda function into a function call. but it's a little ugly:
[1,2,3,4].each { |x| print x }
but, it really convenient. current lambda only support single line syntax. it's not very good. maybe we can add a new syntax: call: primary "(" argument-list ")" [ "lambda" parameter-list ":" suite ]
the postfix lambda will translate to a single "function" object, and pass to the &arg parameter of function. so the function call will become func(*arg1, **arg2, &arg3)
for example, we can write this:
def print_list(*lists, &func = lambda x: true): for item in lists: map(a) lambda x: if func(x): print x
call with: print_list([1,2,3], [1,2]) lambda x: if x % 2: return True else return False
This is not going to end well. Also, http://mail.python.org/pipermail/python-ideas/2007-December/001279.html http://mail.python.org/pipermail/python-ideas/2008-April/001522.html http://mail.python.org/pipermail/python-ideas/2008-November/002340.html The BDFL has disliked every proposal so far, and due to the Ruby- inspired weirdness and magic of this one I really don't see him liking it any better than the ones that came before. -m
On Mon, Oct 19, 2009 at 09:33:06PM +0800, starwing wrote:
current lambda only support single line syntax. it's not very good.
This is where you've made an error. Single-line lambdas are good enough, and if you need more - just create a named function. Oleg. -- Oleg Broytman http://phd.pp.ru/ phd@phd.pp.ru Programmers don't die, they just GOSUB without RETURN.
Oleg Broytman 写道:
On Mon, Oct 19, 2009 at 09:33:06PM +0800, starwing wrote:
current lambda only support single line syntax. it's not very good.
This is where you've made an error. Single-line lambdas are good enough, and if you need more - just create a named function.
Oleg.
BUT, why we need a name? just to process something or make decide, sometimes code itself is enough. and, is there performance problems when you define a inner function in another function? (that's, that function will define every time you call the function or not?)
On Mon, Oct 19, 2009 at 10:28:58PM +0800, starwing wrote:
Oleg Broytman ??????:
Single-line lambdas are good enough, and if you need more - just create a named function.
BUT, why we need a name? just to process something or make decide, sometimes code itself is enough.
A multiline function is certainly not a simple piece of code; it requires documentation - docstring, comments - and the name is a part of the documentation.
and, is there performance problems when you define a inner function in another function? (that's, that function will define every time you call the function or not?)
A lambda, like an inner function, is recreated every time, so it's certainly no better than a named function. You should profile your program to prove there is really a performance degradation. And if there is - create a global function instead. Oleg. -- Oleg Broytman http://phd.pp.ru/ phd@phd.pp.ru Programmers don't die, they just GOSUB without RETURN.
On 19 Oct 2009, at 16:39 , Oleg Broytman wrote:
On Mon, Oct 19, 2009 at 10:28:58PM +0800, starwing wrote:
Oleg Broytman ??????:
Single-line lambdas are good enough, and if you need more - just create a named function.
BUT, why we need a name? just to process something or make decide, sometimes code itself is enough.
A multiline function is certainly not a simple piece of code; it requires documentation - docstring, comments - and the name is a part of the documentation.
Why would grouping two statements require such an overhead? Do you write a comment for each line of Python code you produce? A function, named or not, is nothing more than a bloc of code (in fact that's exactly how they're called in Smalltalk), and not all blocs of code require a name, a docstring and comments.
2009/10/19 Oleg Broytman <phd@phd.pp.ru>
On Mon, Oct 19, 2009 at 10:28:58PM +0800, starwing wrote:
Oleg Broytman ??????:
Single-line lambdas are good enough, and if you need more - just create a named function.
BUT, why we need a name? just to process something or make decide, sometimes code itself is enough.
A multiline function is certainly not a simple piece of code; it requires documentation - docstring, comments - and the name is a part of the documentation.
Having used languages that allow multiline anonymous functions (C#, Javascript) I have to say that they *can* improve the readability of code. Being forced to define functions ahead of where they belong in the logical flow of the program is not a feature of Python but a restriction. To dogmatically assert that multiline anonymous functions are *necessarily* less clear simply does the reputation of Python damage to those who use them already in other languages and know that this isn't true. I accept that it is a necessary restriction in Python (basically impossible to find a clean syntax that fits in with indentation for block structure) but to pretend that it is anything other than a restriction insults the intelligence of your audience. Michael
and, is there performance problems when you define a inner function in another function? (that's, that function will define every time you call the function or not?)
A lambda, like an inner function, is recreated every time, so it's certainly no better than a named function. You should profile your program to prove there is really a performance degradation. And if there is - create a global function instead.
Oleg. -- Oleg Broytman http://phd.pp.ru/ phd@phd.pp.ru Programmers don't die, they just GOSUB without RETURN. _______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
On Tue, 20 Oct 2009 09:33:48 am Michael Foord wrote:
2009/10/19 Oleg Broytman <phd@phd.pp.ru>
On Mon, Oct 19, 2009 at 10:28:58PM +0800, starwing wrote:
Oleg Broytman ??????:
Single-line lambdas are good enough, and if you need more - just create a named function.
BUT, why we need a name? just to process something or make decide, sometimes code itself is enough.
A multiline function is certainly not a simple piece of code; it requires documentation - docstring, comments - and the name is a part of the documentation.
Having used languages that allow multiline anonymous functions (C#, Javascript) I have to say that they *can* improve the readability of code.
Given the difficulty in testing such anonymous functions, what do they do to the correctness of programs?
Being forced to define functions ahead of where they belong in the logical flow of the program is not a feature of Python but a restriction.
I don't see that this restriction is worth the hours and hours people have spent on it. If I have code like this: function(1, None, True, { # define an anonymous dict 'a': set([1, 2, 4, 8, ...], 'b': set([2, 4, 6, 9, 12, 16, 20, ...], 'c': set([1234, 1342, 1432, ...], ... 'z': set([12, 99, 151, 153, 745, ...]) }, flag, count=4, parrot='red') with a complicated data argument, then I can write it as an anonymous variable, but it actually hurts readability to do so. There's no problem with creating an anonymous dict of any complexity I like, but for readability and correctness I'm better off pulling it out of the function call and giving it a name: d = { 'a': set([1, 2, 4, 16, 128, ...], 'b': set([2, 4, 6, 9, 12, 16, 20, ...], 'c': set([1234, 1342, 1432, ...], ... 'z': set([12, 99, 151, 153, 745, ...]) } # print d function(1, None, True, d, flag, count=4, parrot='red') In fact, if it's that complicated, I'm better off creating a function to generate it, so I can test it: function(1, None, True, d_factory(), flag, count=4, parrot='red') My point is that when it comes to data, we have anonymous data that is easy and straightforward to define, and yet we *still* prefer to give data names and define it ahead of where we use it. So why is code different? Why does defining code ahead of where you use it such a bad thing that the lambda restriction generates so much attention? -- Steven D'Aprano
On 20 Oct 2009, at 01:30 , Steven D'Aprano wrote:
Given the difficulty in testing such anonymous functions, what do they do to the correctness of programs?
Nothing different than what `with` or `while` statements do.
My point is that when it comes to data, we have anonymous data that is easy and straightforward to define, and yet we *still* prefer to give data names and define it ahead of where we use it. Not in every case.
So why is code different? Why indeed? As you said above, we have anonymous data that is easy and straightforward to define, why treat code differently and prevent this even when that code is just as easy and straightforward to define?
On Mon, Oct 19, 2009 at 7:30 PM, Steven D'Aprano <steve@pearwood.info> wrote:
On Tue, 20 Oct 2009 09:33:48 am Michael Foord wrote:
Having used languages that allow multiline anonymous functions (C#, Javascript) I have to say that they *can* improve the readability of code.
Could you provide some examples? I've seen plenty of usage in Javascript, but none that I would personally judge as improving readability -- and many that hurt badly. Even if this turns out to be a personal preference thing (some people think it is better, others just don't happen to agree), the advantage is likely small enough that it is outweighed by the advantages of standardization. (I've seen many people claim that the advantages are huge, but the people making such claims often turn out not to be familiar with nested functions.)
Given the difficulty in testing such anonymous functions, what do they do to the correctness of programs?
Anonymity of functions is generally not the biggest source of problems in Javascript. With C compilers, there is pressure to conform to the standard; with Javascript interpreters there is pressure to support existing broken content without any manual intervention (so no compiler switches). The major goal of HTML5 is to at least document and standardize the idiotic workarounds that are required to do that when parsing a web page labeled as HTML; there are similar, less advanced, plans for Javascript and the Browser Object Model, but ... I suspect "untested environment" will continue to be a much bigger issue for at least half a decade.
Being forced to define functions ahead of where they belong in the logical flow of the program is not a feature of Python but a restriction.
Agreed. But I have never felt the urge to read (as opposed to write) a full definition in the middle of call. (And if you aren't in the middle of a call, then the previous line isn't really that far ahead.) I have wished to just pass a name, and define the function later; the fact that I can't always do that is a quirk of python's execution model, but adding anonymous functions wouldn't help. And any syntax heavier than a single keyword would probably add so much noise that it would be worse than the out-of-order effect. In other words, I could understand the value of f(a, 5, delay g, "asdf") def g(x): return x But the cost is already high enough to make me unsure that it would be a worthwhile feature.
My point is that when it comes to data, we have anonymous data that is easy and straightforward to define, and yet we *still* prefer to give data names and define it ahead of where we use it. So why is code different? Why does defining code ahead of where you use it such a bad thing that the lambda restriction generates so much attention?
Data is static -- it just sits there. A name makes it shrink (in mental cost) but has no other effect -- it is like putting physical objects in a suitcase and zipping the thing shut. A function is part of the instructions; defining it somewhere else is like setting a bookmark to follow a footnote -- and then having to come back. That said, I suspect that much of the actual attention is from misunderstandings. -jJ
Michael Foord writes:
I accept that it is a necessary restriction in Python
I agree with your point that it is a restriction. But the connotation of "necessary" that it would be desirable to relax it if there were a good syntax, I don't know about that. Up to about ten years ago, I used lambda in Lisp code a lot. Since then I've found that use cases are being pried from my grasp one by one. I find nowadays that even one-liners that are simply currying a multiargument function are more readable when defined as named functions.
starwing <weasley_wx@qq.com> writes:
Oleg Broytman 写道:
Single-line lambdas are good enough, and if you need more - just create a named function.
BUT, why we need a name? just to process something or make decide, sometimes code itself is enough.
When the code is more complex than a single expression, it's already complex enough that defining it first and then referring to it makes for clearer code.
and, is there performance problems when you define a inner function in another function? (that's, that function will define every time you call the function or not?)
Measure the performance difference in your specific code base and decide on that basis. If there are such problems, then the lambda form won't help you: it defines a function of exactly the same type as what ‘def’ defines. -- \ “I don't like country music, but I don't mean to denigrate | `\ those who do. And for the people who like country music, | _o__) denigrate means ‘put down’.” —Bob Newhart | Ben Finney
On 19 Oct 2009, at 22:50 , Ben Finney wrote:
starwing <weasley_wx@qq.com> writes:
Oleg Broytman 写道:
Single-line lambdas are good enough, and if you need more - just create a named function. BUT, why we need a name? just to process something or make decide, sometimes code itself is enough. When the code is more complex than a single expression, it's already complex enough that defining it first and then referring to it makes for clearer code.
That sounds quite recursive. Is it a hard rule or are you allowed to write three consecutive statements or expressions in some cases?
Masklinn wrote:
On 19 Oct 2009, at 22:50 , Ben Finney wrote:
starwing <weasley_wx@qq.com> writes:
Oleg Broytman 写道:
Single-line lambdas are good enough, and if you need more - just create a named function. BUT, why we need a name? just to process something or make decide, sometimes code itself is enough. When the code is more complex than a single expression, it's already complex enough that defining it first and then referring to it makes for clearer code.
That sounds quite recursive. Is it a hard rule or are you allowed to write three consecutive statements or expressions in some cases?
The difference lies largely in whether or not you are bundling up that code and giving it to another piece of code to use. For myself, I don't actually agree it's a valid design rule - I think anonymous blocks have legitimate use cases (see Ars Technica's writeup of the Apple's new Grand Central Dispatch and C-level anonymous block system in OS X 10.6). However, for Python, the idea of having anonymous blocks runs headlong into the use of indentation for block delineation. You have to either come up with a non-indentation based syntax for the statements inside the anonymous blocks, essentially inventing a whole new language, or you have to embed significant whitespace inside an expression rather than only having it between statements. Nobody has come up with a solution to that mismatch which is superior to just naming the block and using a normal def statement to create it. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia ---------------------------------------------------------------
Nick Coghlan writes:
For myself, I don't actually agree it's a valid design rule - I think anonymous blocks have legitimate use cases (see Ars Technica's writeup of the Apple's new Grand Central Dispatch and C-level anonymous block system in OS X 10.6).
That doesn't look like what "anonymous block" means to me. It looks like a lambda. The difference is that an block resolves all its non-argument references in the calling context, eg, as a C macro without arguments would. But I don't see how you can assign a C macro to a variable and call it at runtime.... Now, the cases that Ruby programmers I know always propose to me as use cases for anonymous blocks rely on conventions for naming certain objects used by their blocks (typically iteration variables), thus avoiding the need to specify arguments for them. So a block seems to be a conventional way of currying a more general function to the context of a specific suite.
On 20 Oct 2009, at 07:37 , Stephen J. Turnbull wrote:
Nick Coghlan writes:
For myself, I don't actually agree it's a valid design rule - I think anonymous blocks have legitimate use cases (see Ars Technica's writeup of the Apple's new Grand Central Dispatch and C-level anonymous block system in OS X 10.6).
That doesn't look like what "anonymous block" means to me. It looks like a lambda.
An anonymous block and a lambda are the exact same thing.
The difference is that an block resolves all its non-argument references in the calling context Are you talking about forming closures here?
Now, the cases that Ruby programmers I know always propose to me as use cases for anonymous blocks rely on conventions for naming certain objects used by their blocks (typically iteration variables) Please forgive my disbelief but "what?" Ruby's blocks take arguments (they're fundamentally nothing more than anonymous functions), I've never encountered a case where "anonymous blocks [relied] on conventions for naming certain objects used within their blocks".
thus avoiding the need to specify arguments for them. See above. Some languages (Scala for instance) have "magical placeholders" to avoid having to name arguments (`_*3` is equivalent to `i => i*3`) but that's pretty much the extent of it.
So a block seems to be a conventional way of currying a more general function to the context of a specific suite. And I don't know what to make of that one either. Blocks don't have any more to do with currying than functions in general do.
Masklinn writes:
On 20 Oct 2009, at 07:37 , Stephen J. Turnbull wrote:
That doesn't look like what "anonymous block" means to me. It looks like a lambda.
An anonymous block and a lambda are the exact same thing.
<WHINE> Why use different names for them, then? At least when discussing Python which calls the concept "lambda"? </WHINE>
The difference is that an block resolves all its non-argument references in the calling context
Are you talking about forming closures here?
No, I'm talking about the exact opposite, I think. Let's forget Ruby, since we're talking about anonymous functions after all, and what I "know" about Ruby is all hearsay (and evidently not correctly understood at that). In Lisp, you can do something like this: (defvar i) (defvar f (lambda () (print i))) (do ((i 10 (- i 1))) ((< i 1)) (funcall f)) outputting 10 9 8 7 6 5 4 3 2 1 and returning nil. Ie, it was my understanding of "block" that free variables in the block have what in Lisp is called "dynamic scope".
So a block seems to be a conventional way of currying a more general function to the context of a specific suite.
That was a brain bubble, sorry.
On 20 Oct 2009, at 20:23 , Stephen J. Turnbull wrote:
Masklinn writes:
On 20 Oct 2009, at 07:37 , Stephen J. Turnbull wrote:
That doesn't look like what "anonymous block" means to me. It looks like a lambda.
An anonymous block and a lambda are the exact same thing. <WHINE> Why use different names for them, then? At least when discussing Python which calls the concept "lambda"? </WHINE>
No, I'm talking about the exact opposite, I think. Let's forget Ruby, since we're talking about anonymous functions after all, and what I "know" about Ruby is all hearsay (and evidently not correctly understood at that). In Lisp, you can do something like this:
(defvar i) (defvar f (lambda () (print i))) (do ((i 10 (- i 1))) ((< i 1)) (funcall f))
outputting 10 9 8 7 6 5 4 3 2 1 and returning nil. Ie, it was my understanding of "block" that free variables in the block have what in Lisp is called "dynamic scope". In most languages (that I know of), free variables come from the lexical scope not the dynamic one (apart from a pair of lisps, I know of no language using a dynamic scope). However as I'm not sure what
One reason is that the creators of Smalltalk liked renaming stuff. A more serious one is that as far as they were concerned, they were manipulating code blocks. There are only two places in Smalltalk where you can have code (apart from the Workspace, which is equivalent to a Python shell): methods (method bodies in Python) and blocks (lambdas). Since there are no statements and if/for/while/try/whatever are implemented through messages (method calls) and anonymous functions, it made sense to use the term blocks to designate, well, blocks. Of code. precisely happens in your code `i` could be the same in the lexical and the dynamic scope so… Using Python's syntax: def foo(): i = 5 return lambda: i def bar(fn): i = "d" print fn() fn = foo() bar(fn) here, if the language is lexically scoped the last line will print "5" whereas if it's dynamically scoped it will print "d". In pretty much every language I know (and that includes Ruby and Smalltalk) it will — as in Python — print "5".
Stephen J. Turnbull wrote:
Nick Coghlan writes:
For myself, I don't actually agree it's a valid design rule - I think anonymous blocks have legitimate use cases (see Ars Technica's writeup of the Apple's new Grand Central Dispatch and C-level anonymous block system in OS X 10.6).
That doesn't look like what "anonymous block" means to me. It looks like a lambda.
The difference lies in the fact that in C, object references are non-local by default - you have to declare them explicitly in the current scope to make them local. Hence the code you stick inline in Apple's new C extensions can manipulate locals as if it were just a normal part of the current function. Accordingly, I find the idea of a new function-like construct where all non-argument variable references are nonlocal by default to be a potentially interesting one. It has nothing to do with Python's inherent syntax problems with nesting statements inside expressions though, which is the reason I snipped that digression from my previous message. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia ---------------------------------------------------------------
On 20 Oct 2009, at 00:00 , Nick Coghlan wrote:
However, for Python, the idea of having anonymous blocks runs headlong into the use of indentation for block delineation.
I'm not sure that's the case, Haskell uses indentation for block delineation too and doesn't (as far as I know, I might be wrong) impose further restrictions on anonymous functions than on named ones. Though this might have to do with…
You have to […] embed significant whitespace inside an expression rather than only having it between statements.
haskell only dealing with expressions and not with statements, thus "blocks" are expressions and it doesn't have to deal with a mismatch between statements and expressions.
Masklinn <masklinn@masklinn.net> writes:
On 19 Oct 2009, at 22:50 , Ben Finney wrote:
When the code is more complex than a single expression, it's already complex enough that defining it first and then referring to it makes for clearer code.
That sounds quite recursive.
Where's the recursion? I'm not defining complexity in terms of complexity, if that's what you mean; I'm noting that a threshold on one continuum is located around the same place as a threshold on another.
Is it a hard rule or are you allowed to write three consecutive statements or expressions in some cases?
Of course it's not a hard rule; it's a rule of thumb, if you like. -- \ “Either he's dead or my watch has stopped.” —Groucho Marx | `\ | _o__) | Ben Finney
On Tue, 20 Oct 2009 01:04:47 am Oleg Broytman wrote:
On Mon, Oct 19, 2009 at 09:33:06PM +0800, starwing wrote:
current lambda only support single line syntax. it's not very good.
This is where you've made an error. Single-line lambdas are good enough, and if you need more - just create a named function.
Oleg.
Actually, lambda isn't limited to a single line, but to a single expression, and expressions can go over multiple lines:
data = [1, 2, 3, 4] map(lambda n: ( ... n**3 - # comment goes here ... n**2 + ... n + 1), data) [2, 7, 22, 53]
http://docs.python.org/reference/expressions.html#lambda The only limitation is that the lambda syntax is limited to a single expression, which means you can't call statements. If your "anonymous code block" is more complicated than a single short expression, it's too complicated to be "obviously correct" just from looking at it, and so it should be documented and tested. The restriction on lambda forces people to move the code block into a named function, which has the happy consequence of encouraging documentation and testing. -- Steven D'Aprano
On 20 Oct 2009, at 01:06 , Steven D'Aprano wrote:
If your "anonymous code block" is more complicated than a single short expression, it's too complicated to be "obviously correct" just from looking at it, and so it should be documented and tested.
I have the same issue with this as with Oleg's pronouncement (which runs along the same lines): does that mean you never write for or if statements with more than a single line in them? Yet these are also "anonymous code blocks" which you say here are "too complicated to be obviously correct just from looking at [them]". If that's the case, why should compound statements even be allowed? They're breeding grounds for multiline anonymous blocks of code…
On Tue, 20 Oct 2009 07:39:44 pm Masklinn wrote:
On 20 Oct 2009, at 01:06 , Steven D'Aprano wrote:
If your "anonymous code block" is more complicated than a single short expression, it's too complicated to be "obviously correct" just from looking at it, and so it should be documented and tested.
I have the same issue with this as with Oleg's pronouncement (which runs along the same lines): does that mean you never write for or if statements with more than a single line in them?
No, you are correct, my statement is overly strong. Please insert "very likely" between "it's" and "too complicated".
Yet these are also "anonymous code blocks" which you say here are "too complicated to be obviously correct just from looking at [them]".
If that's the case, why should compound statements even be allowed? They're breeding grounds for multiline anonymous blocks of code…
There is at least one difference between compound statements and multi-statement anonymous code blocks: You don't pass compound statements around as input to other functions, so you know the environment that they're being called in, and can more easily reason about their correctness. But even then, compound statements are good candidates for being converted into named functions too. I usually start with something like this: if cond: do this do that do something else fe fi fo fum ... else: one fish two fish red fish blue fish ... and by the time I'm finished I've got something like this: if cond: call_one() else: call_two() The multi-line blocks are split into functions, each with their own documentation and tests. Of course I don't do this literally every single time. There's no hard rule about how many lines are allowed, just like there's no hard rule about how complex a data structure can be before you give it a name. But my point is that the restriction on lambda is not an odious one, or at least not so odious that it deserves the amount of heat that it generates. There are uses for multi-statement anonymous functions, but there is nothing that an anonymous function can do that a named function can't.[1] In my opinion, it simply isn't enough of a burden to define a function before you use it, using a "don't care" name, to deserve the amount of words written about potential multi-statement lambda syntax. If Python had different syntax, then perhaps we'd have anonymous functions like Ruby. But we don't, and frankly I don't think it is much of a restriction. [1] Some way to write an anonymous code block, which isn't a function and simply runs in the local environment where it is called as if it were written in-line, would be more interesting to me. -- Steven D'Aprano
On 20 Oct 2009, at 13:21 , Steven D'Aprano wrote:
You don't pass compound statements around as input to other functions, so you know the environment that they're being called in, and can more easily reason about their correctness.
But unless the language is dynamically scoped (which is getting pretty rare these days, and which Python definitely isn't) the environment in which the block is executed is not quite relevant, since the free variables are bound based on its lexical scope (the environment in which the block is created) and the rest is made of argument (as in every other function).
In my opinion, it simply isn't enough of a burden to define a function before you use it, using a "don't care" name, to deserve the amount of words written about potential multi-statement lambda syntax. If Python had different syntax, then perhaps we'd have anonymous functions like Ruby. But we don't, and frankly I don't think it is much of a restriction.
The biggest (by far) advantages I see to good anonymous functions (note: Ruby's aren't, as far as I'm concerned, because due to their nature they don't easily scale from 1/call to 2+/call) are in flexibility, freedom of experimentation and possibility to keep the core language itself small: had Python had "full-blown" anonymous functions, it wouldn't have been necessary to add the `with` statement to the language. It could just as well have been implemented through a protocol or the stdlib, and people would have been free to toy with it in their projects long before it was added to the core language. It also gives the possibility of making OO much less imperative (right now if one wants customized code paths, one usually has to rely on extracting data from objects, performing imperative operations and then feeding the result back to some other object, but objects could just as well provide "hooks" thought callables), and of creating custom control structures (see `with` above, but it applies to far more stuff). In fact, Smalltalk quite clearly demonstrated that with messages (method calls) and blocks (anonymous functions) you basically didn't need "hard-coded" control structures anymore. Now Smalltalk probably went a bit too far for most people, even 30 years later, but it does show how powerful this combination is, and how it allows the language's users to evolve the language itself, without having to change its core syntax.
On Tue, Oct 20, 2009 at 01:34:11PM +0200, Masklinn wrote:
Now Smalltalk probably went a bit too far for most people, even 30 years later
This is The Reason Number Two - there have to be a balance between what features are accepted in the language and what are rejected. Python developers decided that anonymous code blocks are allowed in a few special places and are forbidden generally. IWBN to have a PEP listing all pro et contra arguments so we don't need to repeat the same arguments over and over. Oleg. -- Oleg Broytman http://phd.pp.ru/ phd@phd.pp.ru Programmers don't die, they just GOSUB without RETURN.
On 20 Oct 2009, at 13:49 , Oleg Broytman wrote:
On Tue, Oct 20, 2009 at 01:34:11PM +0200, Masklinn wrote:
Now Smalltalk probably went a bit too far for most people, even 30 years later
This is The Reason Number Two Erm… what was reason number one?
- there have to be a balance between what features are accepted in the language and what are rejected. Python developers decided that anonymous code blocks are allowed in a few special places and are forbidden generally. Have they? I've seen the decision that anonymous functions generally aren't allowed to be useful, but there are anonymous code blocks everywhere. You just can't pass them around.
On Tue, Oct 20, 2009 at 01:54:59PM +0200, Masklinn wrote:
On 20 Oct 2009, at 13:49 , Oleg Broytman wrote:
On Tue, Oct 20, 2009 at 01:34:11PM +0200, Masklinn wrote:
Now Smalltalk probably went a bit too far for most people, even 30 years later
This is The Reason Number Two Erm? what was reason number one?
http://www.python.org/dev/peps/pep-3099/#core-language "multi-line arguments to function calls, for instance. That is just plain ugly." My argument about anonymous/named functions is a part of the explanation for the ugliness.
- there have to be a balance between what features are accepted in the language and what are rejected. Python developers decided that anonymous code blocks are allowed in a few special places and are forbidden generally. Have they? I've seen the decision that anonymous functions generally aren't allowed to be useful, but there are anonymous code blocks everywhere. You just can't pass them around.
The number of compound statements in Python is pretty low. def, for, if, try, with, while. A PEP, please? Oleg. -- Oleg Broytman http://phd.pp.ru/ phd@phd.pp.ru Programmers don't die, they just GOSUB without RETURN.
On Tue, 20 Oct 2009 15:49:58 +0400 Oleg Broytman <phd@phd.pp.ru> wrote:
This is The Reason Number Two - there have to be a balance between what features are accepted in the language and what are rejected. Python developers decided that anonymous code blocks are allowed in a few special places and are forbidden generally.
They did? Where? The closest I've seen is that multi-line expressions - and in particular function invocations - are ugly, so reject any feature that allows them - which generally includes anonymous code blocks - will probably be rejected. This does leave open the possibility of anonymous code blocks being acceptable providing the syntax avoids that problem area. <mike -- Mike Meyer <mwm@mired.org> http://www.mired.org/consulting.html Independent Network/Unix/Perforce consultant, email for more information. O< ascii ribbon campaign - stop html mail - www.asciiribbon.org
On Tue, 20 Oct 2009 13:34:11 +0200 Masklinn <masklinn@masklinn.net> wrote:
The biggest (by far) advantages I see to good anonymous functions (note: Ruby's aren't, as far as I'm concerned, because due to their nature they don't easily scale from 1/call to 2+/call) are in flexibility, freedom of experimentation and possibility to keep the core language itself small: had Python had "full-blown" anonymous functions, it wouldn't have been necessary to add the `with` statement to the language. It could just as well have been implemented through a protocol or the stdlib, and people would have been free to toy with it in their projects long before it was added to the core language.
Note that this is a two edged sword, in that all those people "toying" with "with"-like constructs might also be publishing code using them, meaning that instead of having one clean construct from the core developers, we'd have to deal with an unknown number of variant idioms from most anybody. A small core language doesn't help a lot when you have to know four or five different ways to build some basic construct because it's not in the core language. <mike -- Mike Meyer <mwm@mired.org> http://www.mired.org/consulting.html Independent Network/Unix/Perforce consultant, email for more information. O< ascii ribbon campaign - stop html mail - www.asciiribbon.org
Mike Meyer wrote:
On Tue, 20 Oct 2009 13:34:11 +0200 Masklinn <masklinn@masklinn.net> wrote:
The biggest (by far) advantages I see to good anonymous functions (note: Ruby's aren't, as far as I'm concerned, because due to their nature they don't easily scale from 1/call to 2+/call) are in flexibility, freedom of experimentation and possibility to keep the core language itself small: had Python had "full-blown" anonymous functions, it wouldn't have been necessary to add the `with` statement to the language. It could just as well have been implemented through a protocol or the stdlib, and people would have been free to toy with it in their projects long before it was added to the core language.
Note that this is a two edged sword, in that all those people "toying" with "with"-like constructs might also be publishing code using them, meaning that instead of having one clean construct from the core developers, we'd have to deal with an unknown number of variant idioms from most anybody.
A small core language doesn't help a lot when you have to know four or five different ways to build some basic construct because it's not in the core language.
Yup, this is certainly one of the concerns with making it too easy for developers to invent their own syntax (and also why Guido has flatly ruled out a macro system for Python). The bar for anonymous blocks is a high one, because: 1. Once an anonymous block syntax is accepted into the language we're pretty much stuck with it 2. While it does exist, the use case gap between anonymous functional expressions (i.e. the current lambda) and full named functions is pretty narrow (especially since the introduction of true conditional expressions on the lambda side). 3. Code is written once and read often. Anonymous blocks run a high risk of getting this back to front by making code easier to write but harder to read. The main point in favour of anonymous blocks of some kind is that having to define the subfunction before using it often *will* get the order of the code as written out of whack with respect to the order that makes the most logical sense. Both decorators and the with statement involved large elements of "don't leave important information trailing at the end where a reader may easily miss it" so it is an argument with some merit. Since it is a valid point that this can happen with arbitrary complex data objects rather than solely with named functions, one past proposal (PEP 359, the 'make' statement) involved attaching a suite to a function call, then providing the contents of that suite as a dictionary argument to the function being invoked. (Using the namespace to provide keyword arguments instead would allow a new construct to be used with existing functions, but would significantly constrain the use of temporary variables that weren't intended for use a arguments to the function (then again, that already happens with normal class definitions, and the del statement seems to handle that just fine). I should note that Guido ended up killing that PEP because he didn't like it, but I still believe some kind of "do this, but only after running this other suite first" out of order execution construct is more likely to gain acceptance than trying to come up with a full anonymous block syntax. However, nobody has suggested a particular nice syntax for that idea either, so, again it is unlikely to go anywhere anytime soon. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia ---------------------------------------------------------------
On Wed, Oct 21, 2009 at 4:38 AM, Nick Coghlan <ncoghlan@gmail.com> wrote:
The main point in favour of anonymous blocks of some kind is that having to define the subfunction before using it often *will* get the order of the code as written out of whack with respect to the order that makes the most logical sense.
I actually don't buy that argument. I believe that the main reason people keep arguing for anonymous blocks (and this will never stop) is simply that there is a certain segment of the programmer population that is used to solving a large variety of problems with anonymous blocks and that they don't want to learn how to solve each of those cases using the existing tools in Python. See also my proposal of a moratorium on language changes. -- --Guido van Rossum (home page: http://www.python.org/~guido/)
Guido van Rossum skrev:
I actually don't buy that argument. I believe that the main reason people keep arguing for anonymous blocks (and this will never stop) is simply that there is a certain segment of the programmer population that is used to solving a large variety of problems with anonymous blocks and that they don't want to learn how to solve each of those cases using the existing tools in Python.
I think anonymous blocks have proven their usefulness in concurrency programming. Just take a look at OpenMP or Apple's GCD. But I'll make an argument against anonymous blocks anyway: We can create "anonymous" blocks by throw-away names like "def _()", but why clutter the scope with names that are never used? So assume we would allow write "def():" to designate an anonymous block. I think 99% would abuse it like this: name = def(): <suite> This could just as well be written: def name(): <suite> Thus, certainly "name = def():" should not be allowed. If that is not allowed then, an anynymous block cannot be called or referenced, as there are no name associated with it. So to be useful, it would always have to be associated with a decorator. That would be the only way to get access to it: @decorator def(): <suite> Now we can see that the use for this anonymous block "def()" simply goes away, as it too is redundant syntax. Then it all comes down to whether or not allow decorators on code blocks: @decorator <suite> Since blocks do not create new scopes, I think the answer should be "no". S.M.
On Thu, 22 Oct 2009 07:49:14 pm Sturla Molden wrote:
If that is not allowed then, an anynymous block cannot be called or referenced, as there are no name associated with it.
That is clearly wrong. You don't need a name to call an object. You just need the object.
(lambda x: x+1)(42) 43 [None, lambda s: s.upper(), None][1]('abc') 'ABC'
So to be useful, it would always have to be associated with a decorator. That would be the only way to get access to it:
@decorator def(): <suite>
That doesn't even make sense to me. I don't understand what the decorator is doing there, or how it helps you access the anonymous function. Under today's semantics (modified to allow anonymous def), that would create an anonymous function containing <suite>, then pass that function to decorator(), and treat the return result as anonymous. Since you're not keeping a reference to the anonymous function, it will then be garbage collected. Passing it into a decorator first won't change that (unless the decorator stores the function somewhere as a side-effect). In other words, the above is just like this: decorator(lambda: <suite>) which is legal but pointless unless you do something with the result.
Now we can see that the use for this anonymous block "def()" simply goes away, as it too is redundant syntax.
Why? Functions aren't the only thing you can apply decorators to. You can also call: @decorator class K: pass in Python 2.6 and better. -- Steven D'Aprano
On Tue, Oct 20, 2009 at 7:34 AM, Masklinn <masklinn@masklinn.net> wrote:
But unless the language is dynamically scoped (which is getting pretty rare these days, and which Python definitely isn't)
err ... current python. I believe that changed around python 2.2. I've wanted a way to reverse that more often than I've wanted a way to avoid naming a function. (I originally wrote "far more", but ... the urge doesn't actually come up most years, so maybe it was a solution finding a problem.)
The biggest (by far) advantages I see to good anonymous functions (note: Ruby's aren't, as far as I'm concerned, because due to their nature they don't easily scale from 1/call to 2+/call) are in flexibility, freedom of experimentation and possibility to keep the core language itself small: had Python had "full-blown" anonymous functions, it wouldn't have been necessary to add the `with` statement to the language.
I'm not sure how the lack of a name buys you any of that. Callables as first-class objects that can be passed around, yes -- but naming them is fine. And to be honest, that flexibility and freedom seem like they would be amplified by dynamic scope, so that you could "tune" library functions by passing in arbitrary callables that could affect the "local" variables. The advantages of lexical scoping seem to be mostly about closures, rather than about extending an existing external function. Could you explain how (even named) multiline functions (as opposed to dynamic scope) would have served in place of "with:"? -jJ
Jim Jewett writes:
On Tue, Oct 20, 2009 at 7:34 AM, Masklinn <masklinn@masklinn.net> wrote:
But unless the language is dynamically scoped (which is getting pretty rare these days, and which Python definitely isn't)
err ... current python. I believe that changed around python 2.2.
I've wanted a way to reverse that more often than I've wanted a way to avoid naming a function.
It's funny ... the language I use most is Emacs Lisp and that has taught me a severe aversion to dynamic scoping by default. Sometimes it's useful, but when I am using say Common Lisp an occasional defvar just isn't that painful. I don't think I've ever missed dynamic scope in Python since my first few days with it.
participants (12)
-
Ben Finney
-
Guido van Rossum
-
Jim Jewett
-
Masklinn
-
Michael Foord
-
Mike Meyer
-
Nick Coghlan
-
Oleg Broytman
-
starwing
-
Stephen J. Turnbull
-
Steven D'Aprano
-
Sturla Molden