Use def instead.
def d(x):
if x:
return 1
else:
return 2
All python functions are first order objects (they can be assigned to variables and passed around as arguments), lambda is just a convenient way to make short ones. In general, you are better off using a normal function definition if it becomes anything beyond one line of simple code.
Even then, in fact, if you are assigning it to a name, I would always use def over lambda (something PEP 8 explicitly recommends as it improves debugging). lambda is really only a good idea when defining short functions that can be placed inline into the function call, for example key functions for use with sorted().
Note that, in your case, a ternary operator would do the job (lambda x: 1 if x else 2), but I'm presuming this is a simplified case and you are talking about cases where it's not reasonable to use a single expression.
(As a code golf note, this could also be done in less code as lambda x: 2-bool(x) - of course, that's highly unreadable and a bad idea.)
Use def instead.
def d(x):
if x:
return 1
else:
return 2
All python functions are first order objects (they can be assigned to variables and passed around as arguments), lambda is just a convenient way to make short ones. In general, you are better off using a normal function definition if it becomes anything beyond one line of simple code.
Even then, in fact, if you are assigning it to a name, I would always use def over lambda (something PEP 8 explicitly recommends as it improves debugging). lambda is really only a good idea when defining short functions that can be placed inline into the function call, for example key functions for use with sorted().
Note that, in your case, a ternary operator would do the job (lambda x: 1 if x else 2), but I'm presuming this is a simplified case and you are talking about cases where it's not reasonable to use a single expression.
(As a code golf note, this could also be done in less code as lambda x: 2-bool(x) - of course, that's highly unreadable and a bad idea.)
lambda construct in Python is limited to an expression only, no statements are allowed
While keeping the above mentioned constraint, you can write an expression with multiple lines using backslash char, of course:
>>> fn = lambda x: 1 if x \
else 2
>>> fn(True)
>>> 1
>>> fn(False)
>>> 2
codec abuse, part 2. https://github.com/dankeyy/superlambda.py
gl hf hope you like it
Why doesn't Python allow multi-line lambdas? - Software Engineering Stack Exchange
syntax - How can multiline lambdas be designed in indent based languages? - Programming Language Design and Implementation Stack Exchange
syntax - No Multiline Lambda in Python: Why not? - Stack Overflow
Returning a multi-line lambda function inside an outer function
Videos
Guido van van Rossum answered it himself:
But such solutions often lack "Pythonicity" -- that elusive trait of a good Python feature. It's impossible to express Pythonicity as a hard constraint. Even the Zen of Python doesn't translate into a simple test of Pythonicity...
In the example above, it's easy to find the Achilles heel of the proposed solution: the double colon, while indeed syntactically unambiguous (one of the "puzzle constraints"), is completely arbitrary and doesn't resemble anything else in Python...
But I'm rejecting that too, because in the end (and this is where I admit to unintentionally misleading the submitter) I find any solution unacceptable that embeds an indentation-based block in the middle of an expression. Since I find alternative syntax for statement grouping (e.g. braces or begin/end keywords) equally unacceptable, this pretty much makes a multi-line lambda an unsolvable puzzle.
http://www.artima.com/weblogs/viewpost.jsp?thread=147358
Basically, he says that although a solution is possible, it's not congruent with how Python is.
it's perfectly fine to do a multi line lambda in python: see
>>> f = lambda x: (
... x**x)
>>> f
<function <lambda> at 0x7f95d8f85488>
>>> f(3)
27
the real lambda limitation is the fact that lambda must be a single expression; it can't contains keyword (like python2's print or return).
GvR choose to do so to limit the size of the lambda, as they normally are used as parameters.
If you want a real function, use def
In "indent-based languages" such as Python, indentation is needed at the statement level to determine the nesting of blocks. On the other hand, the nesting of expressions is defined without reference to indentation or any other whitespace, so there is no need to enforce any rules about indentation at the expression level, and arbitrary indentation is allowed when splitting expressions across multiple lines, either using backslash \ to ignore a line ending or writing inside brackets.
Both of these can be implemented directly in the lexer:
- Recognise
\\\n\s*(i.e. a literal backslash followed by a newline followed by any whitespace) as a whitespace token. It will then be ignored when parsing the expression, just like any other whitespace, and it won't get processed by the algorithm which tracks indentation at newlines because the newline character is part of the token. - The lexer counts the nesting level of brackets (increment a counter on each
(,[or{token, decrement on),]or}), and the algorithm which tracks indentation and insertsINDENTandDEDENTtokens ignores newlines when the counter is greater than zero. (A simple counter is enough, because if they don't match up correctly the parser will notice and report the error.)
This is all enough for lambda functions to span multiple lines when the body of the lambda is an expression ─ the user just has to ensure that either the lambda or its body is wrapped in parentheses, then it can span multiple lines. (Of course, this applies to every expression, not just lambdas.)
Lambda functions whose body is a block of statements, on the other hand, are considerably more difficult. Python's solution is to just not allow such lambdas; instead, you are supposed to declare a named function and then you can refer to it by name in an expression. There's a lot to be said for this approach ─ it means that expressions never contain statements, making the language grammatically simpler. It also results in more useful stack traces on runtime errors, because the lines have meaningful names instead of just saying <lambda>.
On the other hand, if you do want statements inside expressions, there's probably no way around having some kind of delimiters (like the braces in Rust), otherwise there will be nothing but whitespace separating the end of the last statement from the continuation of the expression that the lambda occurred in. Here's what it looks like without delimiters:
foo(lambda:
print('hello world')
do_something_else()
, 3.5)
Without block delimiters, the comma is required to be in this ugly position at the start of the line, and moreover the indentation of the expression matters on that line ─ it must be less indented than the lambda body ─ when indentation inside expressions doesn't matter anywhere else. These problems both disappear when you require delimiters; if you don't like braces in an indentation-based language, you could use Lua-style do/end keywords instead:
foo(lambda: do
print('hello world')
do_something_else()
end, 3.5)
So I think you have to just bite the bullet and use block delimiters, at least for statements that occur inside expressions. You don't need to require delimiters on every block, and you can still enforce the language's indentation rules between those delimiters; they're not there to define the nesting level of statements, they're there to separate the statements from the expression which contains them.
Implementation-wise, the lexer now needs to maintain a stack of those counters, so that when you see a do token it pushes a 0 to the stack, and when you see end it pops the counter from the stack. (No need to check that it's zero; the parser will ensure correct nesting of brackets.) This way you effectively "reset" the counter so that the lexer can insert the correct INDENT and DEDENT tokens inside the lambda body, while still being able to restore the old counter for the nesting level of the expression that the lambda occurs in.
Koka's trailing lambda syntax
The Koka language has an interesting feature called trailing lambdas: when the last argument of a function is a lambda, it can be written outside of the parentheses.
Let's take a look at this example (based on the example in kaya3's answer):
foo(3.5, fn()
println('hello world')
do_something_else()
)
The final right-parenthesis is ugly. Koka allows us to write this instead:
foo(3.5) fn()
println('hello world')
do_something_else()
Since this lambda doesn't take any arguments, the fn() can be omitted:
foo(3.5)
println('hello world')
do_something_else()
I think this is an elegant syntax sugar. There are some other languages that have similar feature, such as Julia and some early version of Rust, but those languages are not indent based.
Guido van Rossum (the inventor of Python) answers this exact question himself in an old blog post.
Basically, he admits that it's theoretically possible, but that any proposed solution would be un-Pythonic:
"But the complexity of any proposed solution for this puzzle is immense, to me: it requires the parser (or more precisely, the lexer) to be able to switch back and forth between indent-sensitive and indent-insensitive modes, keeping a stack of previous modes and indentation level. Technically that can all be solved (there's already a stack of indentation levels that could be generalized). But none of that takes away my gut feeling that it is all an elaborate Rube Goldberg contraption."
Look at the following:
map(multilambda x:
y=x+1
return y
, [1,2,3])
Is this a lambda returning (y, [1,2,3]) (thus map only gets one parameter, resulting in an error)? Or does it return y? Or is it a syntax error, because the comma on the new line is misplaced? How would Python know what you want?
Within the parens, indentation doesn't matter to python, so you can't unambiguously work with multilines.
This is just a simple one, there's probably more examples.
I am trying to return a multi-line function that takes one parameter inside an outer function. I cant use a lambda function since the body of the inner function spans across many lines.
def outer(a,b,c):
return lambda x : <multi-line function (uses a,b,c,x)> // not possible
I am also not allowed to create a new function for the inner function
Any suggestions?