Java 8에서 2 개의 화살표가있는 람다는 무엇을 의미합니까?


118

전에 몇 가지 Java 8 자습서를 읽었습니다.

바로 지금 다음 주제를 만났습니다. Java는 Currying을 지원합니까?

여기에 다음 코드가 있습니다.

IntFunction<IntUnaryOperator> curriedAdd = a -> b -> a + b;
System.out.println(curriedAdd.apply(1).applyAsInt(12));

이 예제에는 2 개의 요소가 합산되어 있음을 이해하지만 구성을 이해할 수 없습니다.

a -> b -> a + b;

표현식의 왼쪽 부분에 따르면이 행은 다음 기능을 구현해야합니다.

R apply(int value); 

그 전에는 화살 하나만으로 람다를 만났습니다.


6
커링이 무엇을 의미하는지 이해합니까? 이것은이 질문에 매우 중요합니다.
BlueRaja-Danny Pflughoeft

12
람다를 반환하는 람다 일뿐입니다.
Ilmari Karonen 2015 년

답변:


118

이것을 축약이 아닌 람다 구문 또는 사전 람다 Java 익명 클래스 구문으로 표현하면 무슨 일이 일어나고 있는지 더 분명합니다.

원래 질문입니다. 왜 두 개의 화살이 있습니까? 간단합니다. 정의되는 두 가지 함수가 있습니다 ... 첫 번째 함수는 함수 정의 함수이고 두 번째 함수는 함수의 결과입니다. 각각 ->을 정의 하려면 연산자가 필요 합니다.

비 속기

IntFunction<IntUnaryOperator> curriedAdd = (a) -> {
    return (b) -> {
        return a + b;
    };
};

Java 8 이전의 Pre-Lambda

IntFunction<IntUnaryOperator> curriedAdd = new IntFunction<IntUnaryOperator>() {
    @Override
    public IntUnaryOperator apply(final int value) {
        IntUnaryOperator op = new IntUnaryOperator() {
            @Override
            public int applyAsInt(int operand) {
                return operand + value;
            }
        };
        return op;
    }
};

1
pre-lambda는 a가 필요합니다final int value
njzk2 2015 년

8
예, 맞습니다.하지만 "효과적으로 최종적인"것을 사용할 수있는 Java 8 컴파일러를 사용하여 작성했습니다
Adam

1
예 @gstackoverflow,하지만 자바 8은 아니다pre-lambda
njzk2

1
Java 8에서도 pre-lambda 스타일을 사용할 수 있습니다. 나는 JFY 쓴
gstackoverflow

3
그래서 사람들이 점수를 얻을 수 있도록 람다가 수행되지 않았습니까? :-)
Stephane 2016

48

IntFunction<R> 은 함수 int -> R입니다. An IntUnaryOperator은 함수 int -> int입니다.

따라서 IntFunction<IntUnaryOperator>int 파라미터로하고을 취하는 함수 리턴 int파라미터로하고을 반환이 int.

a -> b -> a + b;
^    |         |
|     ---------
|         ^
|         |
|         The IntUnaryOperator (that takes an int, b) and return an int (the sum of a and b)
|
The parameter you give to the IntFunction

익명 클래스를 사용하여 람다를 "분해"하는 것이 더 분명 할 수 있습니다.

IntFunction<IntUnaryOperator> add = new IntFunction<IntUnaryOperator>() {
    @Override
    public IntUnaryOperator apply(int a) {
        return new IntUnaryOperator() {
            @Override
            public int applyAsInt(int b) {
                return a + b;
            }
        };
    }
};

29

괄호를 추가하면 더 명확해질 수 있습니다.

IntFunction<IntUnaryOperator> curriedAdd = a -> (b -> (a + b));

또는 중간 변수가 도움이 될 수 있습니다.

IntFunction<IntUnaryOperator> curriedAdd = a -> {
    IntUnaryOperator op = b -> a + b;
    return op;
};

24

더 명확하게하기 위해 괄호로 람다 식을 다시 작성해 보겠습니다.

IntFunction<IntUnaryOperator> curriedAdd = a -> (b -> (a + b));

그래서 우리는를 int반환 하는를 취하는 함수를 선언하고 있습니다 Function. 더 구체적으로, 반환 된 함수는를 취하고 (두 요소의 합)을 int반환합니다 int. 이것은 IntUnaryOperator.

따라서를 curriedAdd취하고 int를 반환하는 함수 IntUnaryOperator이므로 IntFunction<IntUnaryOperator>.


9

두 개의 람다 식입니다.

IntFunction<IntUnaryOperator> curriedAdd = 
  a -> { //this is for the fixed value
    return b -> { //this is for the add operation
      return a + b;
    };
  }

IntUnaryOperator addTwo = curriedAdd.apply(2);
System.out.println(addTwo.applyAsInt(12)); //prints 14

8

당신이 보면 IntFunction그것은 명확하게 될 수 있습니다 IntFunction<R>입니다 FunctionalInterface. 를 취하고 int유형 값을 반환 하는 함수를 나타냅니다 R.

이 경우 반환 유형 RFunctionalInterface, 즉 IntUnaryOperator. 따라서 첫 번째 (외부) 함수 자체는 함수를 반환합니다.

이 경우 :에 적용하면 int, curriedAdd다시받는 함수 반환하도록되어 int(다시 되돌아 int가 무엇 때문에, IntUnaryOperator않습니다).

함수형 프로그래밍에서는 함수 유형을 다음 param -> return_value과 같이 작성하는 것이 일반적 이며 여기에서 정확히 볼 수 있습니다. 따라서 유형 curriedAddint -> int -> int(또는 int -> (int -> int)더 나은 경우)입니다.

Java 8의 람다 구문은 이와 함께 진행됩니다. 이러한 함수를 정의하려면

a -> b -> a + b

실제 람다 미적분과 매우 유사합니다.

λa λb a + b

λb a + b단일 매개 변수를 취하고 b값 (합계)을 리턴 하는 함수입니다 . λa λb a + b단일 매개 변수를 받아들이고 단일 매개 변수의 a다른 함수를 반환하는 함수입니다. 매개 변수 값 으로 설정된 상태로 λa λb a + b반환 λb a + b됩니다 a.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.