완화된 람다 문법
완화된 람다 문법 (Relaxed Lambda Syntax)
함수 리터럴을 더 유연한 방식으로 쓸 수 있게 해주는 여러 작은 개선을 합친 실험적 추가 기능이에요. 한 줄 람다, 커리된 람다, 괄호 안/최상위 case 표현식 등을 지원해요.
본문
이 실험적 추가 기능은 함수 리터럴을 더 유연한 방식으로 쓰기 위한 작은 개선 몇 가지를 결합해요. 이 개선들은 SIP 74와 SIP 75에 명세되어 있어요. 실험적 언어 import로 활성화됩니다:
import language.experimental.relaxedLambdaSyntax
한 줄 람다 (Single Line Lambdas)
: 뒤에 같은 줄에 오는 람다 표현식이 이제 지원돼요. 이전에는 화살표 뒤에 줄바꿈과 들여쓰기가 필요했어요. 예를 들어:
xs.map: x =>
x + 1
이제 람다를 한 줄에 쓸 수도 있어요:
xs.map: x => x + 1
이 경우 람다는 줄 끝까지 확장돼요.
이 문법은 모든 종류의 함수 리터럴에서 동작해요. 하나 이상의 파라미터로 시작하거나, 타입 파라미터로 시작하거나, case로 시작하는 부분 함수일 수 있어요.
Seq((1, 2), (3, 4)).map: (a, b) => a + b
Seq((1, 2), (3, 4)).map: (a: Int, b: Int) => a + b
Seq((1, 2), (3, 4)).collect: case (a, b) if b > 2 = a
(1, true).map: [T] => (x: T) => List(x)
이 문법은 =>나 ?=>를 담지 않은 함수 값에는 동작하지 않아요. 예를 들어 다음은 불법이에요.
Seq((1, 2), (3, 4)).map: _ + _ // error
Seq(1, 2, 3).map: plus1 // error
한 줄 람다는 중첩될 수 있어요. 다음과 같이요:
xs.map: x => x.toString + xs.dropWhile: y => y > 0
상세 명세 (Detailed Spec)
:는 다음 중 하나가 뒤따르면 애플리케이션(적용)을 뜻해요:
- 줄 끝과 들여쓰기된 블록,
- 파라미터 섹션, 그다음
=>또는?=>, 줄 끝과 들여쓰기된 블록, - 파라미터 섹션, 그다음
=>또는?=>와 한 줄에 있는 표현식, - 단일 case 부분 함수를 나타내는 case 절.
(1)과 (2)는 현행 상태이고, (3)과 (4)가 새로워요.
제약: (3)과 (4)는 괄호로 즉시 둘러싸인 코드에는 적용되지 않아요(더 가깝게 중괄호나 들여쓰기로 묶이지 않은 경우). 이는 타입 애스크립션(타입 지정)과의 모호성을 피하기 위해서예요. 예를 들어
(
x: Int => Int
)
는 여전히 타입 애스크립션을 뜻하고, 함수 애플리케이션으로 해석하려 시도하지 않아요.
커리된 여러 줄 람다 (Curried Multi-Line Lambdas)
이전에는 들여쓰기된 블록 앞에 단일 파라미터 섹션과 화살표만 허용했어요. 이제 여러 개의 그런 섹션도 허용합니다. 그래서 다음이 이제 합법적이에요:
def fun(f: Int => Int => Int): Int = f(1)(2)
fun: (x: Int) => y =>
x + y
위 상세 명세에서 항목 (2)는 다음과 같이 수정됩니다:
- 하나 이상의 파라미터 섹션, 각각
=>또는?=>가 뒤따르고, 마지막으로 줄 끝과 들여쓰기된 블록.
case 표현식 (Case Expressions)
이전에는 부분 함수를 구성하는 case 절이 중괄호나 들여쓰기된 블록 안에 쓰여야 했어요. 단일 case 절만 있으면, 이제 괄호 안이나 최상위 표현식으로도 쓸 수 있게 허용합니다.
예시:
case class Pair(x: Int, y: Int)
Seq(Pair(1, 2), Pair(3, 4)).collect(case Pair(a, b) if b > 2 => a)
Seq(Pair(1, 2), Pair(3, 4)).collect(
case (a, b) =>
println(b)
a
)
val partial: PartialFunction[(Int, Int), Int] = case (a, b) if b > 2 => a
문법 변경 (Syntax Changes)
Expr ::= ...
| ExprCaseClause
ColonArgument ::= colon {LambdaStart} indent (CaseClauses | Block) outdent
| colon LambdaStart {LambdaStart} expr ENDlambda
| colon ExprCaseClause
여기서 ENDlambda는 프로덕션을 시작하는 토큰 뒤에 오는 줄의 다음 줄 끝(다음 행 끝)에서 합성되는 토큰이에요.
ExprCaseClause는 이미 문법에 존재해요. 다음과 같이 정의됩니다:
ExprCaseClause ::= ‘case’ Pattern [Guard] ‘=>’ Expr