람다 함수
람다 함수 (Lambda Functions)
DuckDB 람다 함수(일명 'lambda' 또는 'lambda expression')는 인라인 익명 함수를 정의하는 표현식이에요. 람다는 특정 리스트 함수에 인자로 전달되며, 그 리스트 함수는 전달된 람다 표현식을 요소들에 대해 평가해요. 람다 평가의 결과 값은 리스트 함수가 반환 값을 만들도록 더 처리돼요.
출처: 문서
본문
람다는 COLUMNS 절에서도 사용할 수 있어요. 이 맥락에서 람다 함수는 필터로 동작해요: true로 평가되면 컬럼을 유지하고, 그렇지 않으면 버려요. COLUMNS 절 람다는 컬럼 이름을 받는 필수 파라미터가 있어요. 선택적으로 (1-기반) 컬럼 인덱스를 받는 두 번째 파라미터를 선언할 수 있어요.
람다 표현식의 문법은 다음과 같아요.
lambda ⟨parameters⟩ : ⟨expression⟩
⟨parameters⟩은 쉼표로 구분된 파라미터 이름 목록이에요. 파라미터는 어떤 이름이든 가질 수 있고, 그 이름은⟨expression⟩에서 참조될 수 있어요.- 허용되고 요구되는 파라미터 수는 전달되는 리스트 함수에 따라 달라져요.
- 항상 리스트 함수가 리스트의 현재 요소를 전달하는 데 사용하는 필수 파라미터가 있어요. 보통 첫 번째 파라미터예요.
- 항상 리스트 함수가 현재 요소의 (1-기반) 인덱스를 전달하는 데 사용하는 선택적 파라미터가 있어요. 항상 마지막 파라미터예요.
- 표현식은 스칼라 표현식이어야 해요. 또한 서브쿼리, 테이블 함수 등을 포함할 수 없어요.
- 표현식은 매크로 호출을 포함할 수 있어요. 단, 스칼라 매크로만 허용되고 서브쿼리에 의존하지 않아야 해요.
예를 들어 다음은 모두 유효한 람다 함수예요.
lambda param : param > 1lambda s : contains(concat(s, 'DB'), 'duck')lambda acc, x : acc + x
람다 함수는 쿼리에서 더 복잡하고 유연한 표현식을 사용할 수 있게 해 줘요.
람다 함수를 받는 스칼라 함수 (Scalar Functions That Accept Lambda Functions)
| Function | Description |
|---|---|
apply(list, lambda(x)) |
list_transform의 별칭. |
array_apply(list, lambda(x)) |
list_transform의 별칭. |
array_filter(list, lambda(x)) |
list_filter의 별칭. |
array_reduce(list, lambda(x,y)[, initial_value]) |
list_reduce의 별칭. |
array_transform(list, lambda(x)) |
list_transform의 별칭. |
filter(list, lambda(x)) |
list_filter의 별칭. |
list_apply(list, lambda(x)) |
list_transform의 별칭. |
list_filter(list, lambda(x)) |
lambda 함수가 true를 반환하는 입력 list의 요소들로 리스트를 구성. DuckDB는 lambda 함수의 반환 타입을 BOOL로 캐스트할 수 있어야 함. list_filter의 반환 타입은 입력 리스트와 동일. list_filter 예시 참고. |
list_reduce(list, lambda(x,y)[, initial_value]) |
누적 결과와 다음 리스트 요소에 lambda 함수를 실행해 입력 list의 모든 요소를 단일 스칼라 값으로 줄임. lambda 함수에는 선택적 initial_value 인자가 있음. list_reduce 예시 참고. |
list_transform(list, lambda(x)) |
입력 list의 각 요소에 lambda 함수를 적용한 결과인 리스트를 반환. 반환 타입은 lambda 함수의 반환 타입으로 정의됨. list_transform 예시 참고. |
reduce(list, lambda(x,y)[, initial_value]) |
list_reduce의 별칭. |
list_filter(list, lambda(x))
| Description | lambda 함수가 true를 반환하는 입력 list의 요소들로 리스트를 구성. DuckDB는 lambda 함수의 반환 타입을 BOOL로 캐스트할 수 있어야 함. list_filter의 반환 타입은 입력 리스트와 동일. list_filter 예시 참고. |
| Example | list_filter([3, 4, 5], lambda x : x > 4) |
| Result | [5] |
| Aliases | array_filter, filter |
list_reduce(list, lambda(x,y)[, initial_value])
| Description | 누적 결과와 다음 리스트 요소에 lambda 함수를 실행해 입력 list의 모든 요소를 단일 스칼라 값으로 줄임. lambda 함수에는 선택적 initial_value 인자가 있음. list_reduce 예시 참고. |
| Example | list_reduce([1, 2, 3], lambda x, y : x + y) |
| Result | 6 |
| Aliases | array_reduce, reduce |
list_transform(list, lambda(x))
| Description | 입력 list의 각 요소에 lambda 함수를 적용한 결과인 리스트를 반환. 반환 타입은 lambda 함수의 반환 타입으로 정의됨. list_transform 예시 참고. |
| Example | list_transform([1, 2, 3], lambda x : x + 1) |
| Result | [2, 3, 4] |
| Aliases | apply, array_apply, array_transform, list_apply |
람다 함수 중첩 (Nesting Lambda Functions)
모든 스칼라 함수는 임의로 중첩할 수 있어요. 예를 들어 짝수 리스트 요소의 제곱을 모두 얻는 중첩 람다 함수:
SELECT list_transform(
list_filter([0, 1, 2, 3, 4, 5], lambda x: x % 2 = 0),
lambda y: y * y
);
[0, 4, 16]
첫 번째 리스트의 각 요소를 두 번째 리스트의 합에 더하는 중첩 람다 함수:
SELECT list_transform(
[1, 2, 3],
lambda x :
list_reduce([4, 5, 6], lambda a, b: a + b) + x
);
[16, 17, 18]
스코핑 (Scoping)
람다 함수는 다음 순서로 스코핑 규칙을 따르고 있어요.
- 내부 람다 파라미터
- 외부 람다 파라미터
- 컬럼 이름
- 매크로 파라미터
CREATE TABLE tbl (x INTEGER);
INSERT INTO tbl VALUES (10);
SELECT list_apply(
[1, 2],
lambda x: list_apply([4], lambda x: x + tbl.x)[1] + x
)
FROM tbl;
[15, 16]
파라미터로서의 인덱스 (Indexes as Parameters)
모든 람다 함수는 현재 요소의 인덱스를 나타내는 선택적 추가 파라미터를 받아요. 이것은 항상 람다 함수의 마지막 파라미터(예: (x, i)의 i)이고 1-기반이에요(즉, 첫 요소의 인덱스는 1).
자신의 인덱스보다 큰 모든 요소를 얻기:
SELECT list_filter([1, 3, 1, 5], lambda x, i: x > i);
[3, 5]
예시 (Examples)
list_transform 예시
각 리스트 요소를 1씩 증가:
SELECT list_transform([1, 2, NULL, 3], lambda x: x + 1);
[2, 3, NULL, 4]
문자열 변환:
SELECT list_transform(['Duck', 'Goose', 'Sparrow'], lambda s: concat(s, 'DB'));
[DuckDB, GooseDB, SparrowDB]
람다 함수를 다른 함수와 결합:
SELECT list_transform([5, NULL, 6], lambda x: coalesce(x, 0) + 1);
[6, 1, 7]
list_filter 예시
음수 값 필터링:
SELECT list_filter([5, -6, NULL, 7], lambda x: x > 0);
[5, 7]
2와 5로 나누어떨어지는 값:
SELECT list_filter(
list_filter([2, 4, 3, 1, 20, 10, 3, 30], lambda x: x % 2 = 0),
lambda y: y % 5 = 0
);
[20, 10, 30]
리스트를 구성하기 위한 range(...)와의 결합:
SELECT list_filter([1, 2, 3, 4], lambda x: x > #1) FROM range(4);
[1, 2, 3, 4]
[2, 3, 4]
[3, 4]
[4]
list_reduce 예시
모든 리스트 요소의 합:
SELECT list_reduce([1, 2, 3, 4], lambda acc, x: acc + x);
10
2보다 큰 리스트 요소만 더하기:
SELECT list_reduce(
list_filter([1, 2, 3, 4], lambda x: x > 2),
lambda acc, x: acc + x
);
7
모든 리스트 요소 연결:
SELECT list_reduce(['DuckDB', 'is', 'awesome'], lambda acc, x: concat(acc, ' ', x));
DuckDB is awesome
초기값 없이 인덱스와 요소 연결:
SELECT list_reduce(
['a', 'b', 'c', 'd'],
lambda x, y, i: x || ' - ' || CAST(i AS VARCHAR) || ' - ' || y
);
a - 2 - b - 3 - c - 4 - d
초기값으로 인덱스와 요소 연결:
SELECT list_reduce(
['a', 'b', 'c', 'd'],
lambda x, y, i: x || ' - ' || CAST(i AS VARCHAR) || ' - ' || y, 'INITIAL'
);
INITIAL - 1 - a - 2 - b - 3 - c - 4 - d
제한사항 (Limitations)
-
람다 표현식의 서브쿼리는 현재 지원되지 않아요. 예를 들어:
SELECT list_apply([1, 2, 3], lambda x: (SELECT 42) + x);Binder Error: subqueries in lambda expressions are not supported -
표현식은 매크로 호출을 포함할 수 있지만 매크로가 스칼라 매크로인 경우에만 가능하고, 매크로는 서브쿼리를 포함하거나 서브쿼리를 포함하는 다른 매크로에 의존하면 안 돼요.
-
람다 함수는 리스트 함수의 인자로 인라인으로 정의되어야 해요. 매크로에서 람다 함수를 반환할 수는 없어요(하지만 람다의 표현식에서 매크로를 호출할 수는 있어요).
사용 중단된 문법 (Deprecated Syntax)
DuckDB v1.3은 이전의 단일 화살표 람다 문법(
x -> x + 1)을 Python 스타일 문법(lambda x : x + 1)을 위해 사용 중단 처리했어요.DuckDB v1.3은 람다 문법을 구성하는 새 설정도 도입했어요.
SET lambda_syntax = 'DEFAULT'; SET lambda_syntax = 'ENABLE_SINGLE_ARROW'; SET lambda_syntax = 'DISABLE_SINGLE_ARROW';현재
DEFAULT는 두 문법 스타일(이전 단일 화살표 문법과 Python 스타일 문법)을 모두 활성화해요.DuckDB v1.5는 단일 화살표 문법을 명시적으로 활성화하지 않고 지원하는 마지막 릴리스예요.
DuckDB v2.0은 기본적으로 단일 화살표 문법을 비활성화할 거예요.
DuckDB v2.1은
lambda_syntax플래그를 제거하고 단일 화살표 문법을 완전히 사용 중단 처리해서, 이전 동작은 더 이상 불가능해질 거예요.