PEP 312 – 간단한 암시적 람다
- Author:
- Roman Suzi <rnd at onego.ru>, Alex Martelli <aleaxit at gmail.com>
- Status:
- Deferred
- Type:
- Standards Track
- Created:
- 11-Feb-2003
- Python-Version:
- 2.4
- Post-History:
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 문법적으로 모호하지 않은 일부 경우에 인자 없는 람다 키워드를 선택적으로 만들 것을 제안합니다.
보류
BDFL은 단항 콜론 구문을 싫어합니다. 이 PEP는 원점으로 돌아가 더 파이썬다운 구문(아마도 대안적인 단항 연산자)을 찾아야 합니다. 2005년 6월 17일자 python-dev 논의를 참조하십시오 [1].
또한, 전혀 가능성이 없는 대안 제안들을 제거하는 것이 아마도 좋은 생각일 것입니다. 예제 섹션은 훌륭하며 가독성 개선을 잘 보여줍니다. 추상화된 더미 호출인 :A와 :B 대신 추가 예제와 실제 사례를 사용한다면 더 설득력이 있을 것입니다.
동기
람다는 익명 함수를 정의하는 데 유용합니다. 예를 들어 콜백이나 (유사) 지연 평가 방식으로 사용할 때입니다. 종종 “lambda”라는 키워드가 코드를 복잡해 보이게 만든다는 이유만으로, 람다가 적절할 때조차 사용되지 않는 경우가 있습니다. 일부 특수한 경우에 람다를 생략하는 것은, 문법에 대한 작고 하위 호환성을 유지하는 변경을 통해 가능하며, 이러한 “람다 공포증”에 대한 저렴한 해결책을 제공합니다.
근거
사람들은 때때로 이론적 배경을 가진 용어를 도입하는 것이 두려워 람다를 사용하지 않습니다. 이 제안은 “lambda” 키워드 자체를 생략함으로써 인자 없는 람다를 더 쉽게 도입할 수 있게 합니다. 구현은 문법을 단순히 변경하여, 잘 알려진 몇 가지 경우에 “lambda” 키워드가 암시되도록 함으로써 이루어질 수 있습니다. 특히, 주변에 괄호를 추가하면 어디서든 인자 없는 람다를 지정할 수 있습니다.
구문
다음과 같은 경우에는 인자 없는 “lambda” 키워드를 생략할 수 있습니다:
- 명명된 매개변수 할당이나 기본값 할당에서 “=” 바로 다음;
- 임의의 표현식에서 “(” 바로 다음;
- 함수 인자 목록에서 “,” 바로 다음;
- 딕셔너리 리터럴에서 “:” 바로 다음; (미구현)
- 대입문에서; (미구현)
사용 예제
- 인라인
if:def ifelse(cond, true_part, false_part): if cond: return true_part() else: return false_part() # old syntax: print ifelse(a < b, lambda:A, lambda:B) # new syntax: print ifelse(a < b, :A, :B) # parts A and B may require extensive processing, as in: print ifelse(a < b, :ext_proc1(A), :ext_proc2(B))
- 잠금:
def with(alock, acallable): alock.acquire() try: acallable() finally: alock.release() with(mylock, :x(y(), 23, z(), 'foo'))
구현
구현하려면 파이썬 소스의 Grammar/Grammar 파일을 어느 정도 손봐야 하며, 구문적·실용적 변경을 위해 Modules/parsermodule.c도 일부 조정해야 합니다.
(전체 구현을 하려면 문법/파서 전문가가 필요합니다.)
다음은 암시적 람다를 허용하기 위해 Grammar에 필요한 변경 사항입니다:
varargslist: (fpdef ['=' imptest] ',')* ('*' NAME [',' '**'
NAME] | '**' NAME) | fpdef ['=' imptest] (',' fpdef ['='
imptest])* [',']
imptest: test | implambdef
atom: '(' [imptestlist] ')' | '[' [listmaker] ']' |
'{' [dictmaker] '}' | '`' testlist1 '`' | NAME | NUMBER | STRING+
implambdef: ':' test
imptestlist: imptest (',' imptest)* [',']
argument: [test '='] imptest
새로운 논터미널 세 개가 필요합니다: 암시적 람다가 나타날 수 있는 위치를 나타내는 imptest, 암시적 람다 정의 자체를 나타내는 implambdef, imptest들이 나타날 수 있는 위치를 나타내는 imptestlist입니다.
이 구현은 완전하지 않습니다. 첫째, Parser 모듈의 일부 파일을 갱신해야 하기 때문입니다. 둘째, 몇몇 추가적인 위치가 구현되지 않았으므로 위의 Syntax 절을 참고하십시오.
논의
이 기능은 가시성이 높은 기능이 아닙니다(유일하게 새로운 부분은 람다가 없다는 점입니다). 이 기능은 무항(null-ary) 람다를 구문상 더 매력적으로 만들어, 일부 단순한 경우에 표현식의 지연 평가(lazy evaluation)를 제공하기 위한 것입니다. 이 제안은 (람다에 인자를 요구하는) 더 고급 사례를 대상으로 하지 않습니다.
암시적 람다에 대한 대안적 제안이 있습니다: 사용되지 않는 인자를 갖는 암시적 람다입니다. 이 경우 그러한 람다로 정의된 함수는 임의의 매개변수를 받을 수 있으며, 즉 lambda *args: expr과 동등합니다. 이 형태가 더 강력할 것입니다. 표준 라이브러리를 grep해 본 결과, 그러한 람다가 실제로 사용되고 있음이 드러났습니다.
또 다른 확장으로 암시적 람다로 정의된 함수에 전달되는 매개변수 목록을 가질 수 있는 방법을 제공할 수 있습니다. 하지만 이러한 매개변수는 접근하기 위해 특별한 이름이 필요하며, 언어에 포함될 가능성은 낮습니다. 이러한 매개변수에 사용할 수 있는 지역 이름으로는 _, __args__, __가 있습니다. 예를 들면:
reduce(:_[0] + _[1], [1,2,3], 0)
reduce(:__[0] + __[1], [1,2,3], 0)
reduce(:__args__[0] + __args__[1], [1,2,3], 0)
이러한 형태는 그다지 보기 좋지 않으며, 이 PEP 작성자의 견해로는 이런 경우에 lambda 키워드를 제거하는 것을 정당화하지 못합니다.
감사의 말
lambda를 없애자는 아이디어는 “For review: PEP 308 - If-then-else expression” [2] 스레드를 논의하던 중 2003년 2월 8일 16:39:30 -0800에 Paul Rubin이 comp.lang.python에서 처음 제안했습니다.
참고 문헌
Copyright
This document has been placed in the public domain.