Repository navigation
Deprecate lambda arrow (->) and replace it with LAMBDA x : x + 1 - #17235
Conversation
|
Related issue: https://github.com/duckdblabs/duckdb-internal/issues/4524. I've duplicated many old lambda tests in a subdirectory and enabled |
lnkuiper
left a comment
There was a problem hiding this comment.
Awesome! The changes seem good to me, we discussed these already. I like that you have a very descriptive error message.
I was also not expecting you to fully change all tests already! Looks great, thanks!
Looking forward to v1.4.0 when we can fully deprecate this and allow proper arrow precedence for JSON.
|
Great change, great work 👍 |
|
I would add some tests around mixing syntaxes AND around macro definitions (since those are not parser time but bind time). Like: CREATE OR REPLACE function transpose(lst) AS (
SELECT list_transform(range(1, 1 + length(lst[1])),
j -> list_transform(range(1, length(lst) + 1),
LAMBDA i : lst[i][j]
)
)
);
SELECT transpose('123');(currently INTERNAL Error) Plus there is also some possible problem with serialization, like: (unsure what's the path here, does this need to be actually visible to storage serialization?) And I would say WITH tbl AS (SELECT l :'lambda')
FROM tbl
SELECT list_transform(range(1, length(l) + 1), a := lambda i : l[0:i]); |
|
This makes me a tiny bit sad, I liked the -> syntax and found it more readable and less esoteric than lambda. On the other hand, I'm excited for more reliable binding with macros. Do you know if this fixes this discussion? |
|
@carlopi, the output of this one looks correct to me - I am not sure what the WITH tbl AS (SELECT l :'lambda')
FROM tbl
SELECT list_transform(range(1, length(l) + 1), a := lambda i : l[0:i]); |
If we don't expose it, then we'll get different results for the verification runs. |
|
@taniabogatsch |
|
@carlopi, I added some changes and all of these should pass now. Thanks a lot for your detailed comments! statement error
CREATE OR REPLACE function transpose(lst) AS (
SELECT list_transform(range(1, 1 + length(lst[1])),
j -> list_transform(range(1, length(lst) + 1),
LAMBDA i : lst[i][j]
)
)
);
----
<REGEX>:Binder Error.*Deprecated lambda arrow.*
statement error
CREATE OR REPLACE FUNCTION transpose(lst) AS (
SELECT list_transform(range(1, 1 + length(lst[1])),
j -> list_transform(range(1, length(lst) + 1),
i -> lst[i][j]
)
)
);
----
<REGEX>:Binder Error.*Deprecated lambda arrow.*
statement ok
SET allow_deprecated_lambda_syntax=true
statement ok
CREATE OR REPLACE FUNCTION transpose(lst) AS (
SELECT list_transform(range(1, 1 + length(lst[1])),
j -> list_transform(range(1, length(lst) + 1),
i -> lst[i][j]
)
)
);
statement ok
ATTACH '__TEST_DIR__/deprecated_syntax.db';
statement ok
CREATE OR REPLACE FUNCTION deprecated_syntax.transpose(lst) AS (
SELECT list_transform(range(1, 1 + length(lst[1])),
j -> list_transform(range(1, length(lst) + 1),
i -> lst[i][j]
)
)
);
statement ok
DETACH deprecated_syntax;
statement ok
ATTACH '__TEST_DIR__/deprecated_syntax.db'; |
|
@eaubin - I haven't looked into that discussion, yet. But I am planning to fix the remaining open issues around lambda binding after this has been merged. |
|
@hmeriann, I adjusted the regression tests to have the new syntax. From my understanding, they will break for this PR, and once merged, work again? |
|
@taniabogatsch yes, this sounds right! Thank you for letting me know! |
|
Great on the bind-time checks!!
I am not sure I understand, I was thinking that if this is checked at creation, then stuff should just work from there (either 1 more or both are allowed, but downstream it does not matter and whatever entered the system has to keep working). To me exposing this to serialization adds complexity for future us /adds failures mode I am not really sure we are interested in. I am not sure of the details, could you expand on what fails differently? |
It is checked during the binding phase, which is after we've created a Currently, the And if we decide to not have the string LambdaExpression::ToString() const {
if (deprecated) {
return "(" + lhs->ToString() + " -> " + expr->ToString() + ")";
}
return "(LAMBDA " + lhs->ToString() + " : " + expr->ToString() + ")";
}Because depending on which representation we choose, we either 1. start throwing invalid syntax for originally valid expressions, or turn a JSON arrow into a lambda expression... |
|
Yes that will work as well (spaces are nops in SQL). @taniabogatsch maybe we can update the tests to follow the syntax commonly used in Python instead? (e.g. |
|
I've implemented all suggestions and review requests, so this is ready for review again. |
|
The regression failure is expected, and the Python failure seems unrelated. |
|
Thanks! |
|
Nightly Regression had failed with syntax error - it should go away tomorrow |
Deprecate lambda arrow (->) and replace it with LAMBDA x : x + 1 (duckdb/duckdb#17235)
Deprecate lambda arrow (->) and replace it with LAMBDA x : x + 1 (duckdb/duckdb#17235)
Deprecate lambda arrow (->) and replace it with LAMBDA x : x + 1 (duckdb/duckdb#17235)
Deprecate lambda arrow (->) and replace it with LAMBDA x : x + 1 (duckdb/duckdb#17235)
Changes
Currently, one way to specify lambda functions is by using the arrow operator syntax:
x -> x + 1This PR deprecates that syntax and replaces it with Python-style lambda syntax:
lambda x: x + 1You can enable the old behavior with:
SET allow_deprecated_lambda_syntax=true(default value is alsotrue).On default, it is currently still possible to use both the old and the new syntax.
Timeline
Starting with this PR / 1.3.0, we introduce the new syntax, and the
allow_deprecated_lambda_syntaxsetting.Starting with 1.4.0, we intend to print some kind of warning when using the old behavior and
allow_deprecated_lambda_syntaxis on the default setting.Starting with 1.5.0, we intend to default
allow_deprecated_lambda_syntaxtono allowed.Starting with 1.6.0, we'll disable using the deprecated lambda syntax, and remove the setting.
Motivation
The same arrow operator is also used in the JSON extension. The decision to deprecate it for lambda functions stems from many issues that arise from using the same operator for both cases. Binding this operator is a lot of trouble, as we must resolve ambiguity conflicts and precedence issues. The operator precedence that is necessary for the lambda arrow to work as expected causes weird behavior for the JSON arrow operator (
->and->>).Since Postgres uses the arrow operator for JSON operations, we modified the lambda functions so that the arrow operator can no longer be used to reconcile this problem.