C #, Java 및 Scala에서 Closures / Lambdas /…에 대한 접근 방식의 장점과 단점은 무엇입니까?


30

C #과 Scala의 기술적 구현 차이점이 무엇인지, 그리고 두 솔루션이 구현 아이디어와 어떻게 비교되는지 , Brian Goetz 의 이메일 Peek Past lambda 에서 프로젝트 Lambda (JSR 335) 의 메일 링리스트로 전송 된 우려 사항에 대해 어떻게 생각 하십니까?

이메일에서 :

"어쩌면 람다는 내면의 실체가되어야하는데 실제로는 단순 할 것입니다."

그리고 더 :

세상에 대한 람다-물체 관점은이 가능한 미래와 충돌합니다. 세계에 대한 람다-함수 관점은 그렇지 않으며, 이러한 유연성을 유지하는 것은 객관의 출현으로 람다에게 부담을주지 않는 점 중 하나입니다.

결론:

Lambdas 기능은 문을 엽니 다. 람다는 개체를 닫습니다.
우리는 그 문이 열린 채로있는 것을 선호합니다.

그리고 Reddit 스레드 에 대한 사람의 의견 은 다음과 같습니다.

실제로 Neal Gafter에게 전자 메일을 보냈고 그의 설명 C #에 대한 제한된 이해와 현재 Java 디자인은 대의원이 실제로 객체 유형이 아니라 기능 유형이 아니라는 점에서 매우 유사합니다. 그는 Java가 C #의 람다의 단점에서 배우고 피해야한다고 생각합니다 (C #이 Java의 단점에서 배우고 처음에는 피했던 것처럼).

"Lambdas-are-functions"접근 방식이 "Lambdas-are-objects"보다 미래에 더 많은 기회를 제공하는 이유는 무엇입니까? 어떤 차이점이 있으며 코드 작성 방법에 어떤 차이점이 있는지 설명 할 수 있습니까?

스칼라의 것들이 "정상 작동"한다는 것을 알면서 C # / Java (8)에서 취했거나 제안 된 접근 방식에 대해 무언가를 놓치고 있다고 생각합니다. 아마도 하위 호환성에 대한 우려와 관련이 있습니까?


1
이건 재미 있네. Javas 유형 시스템에는 현재 기능 개념이 없으므로 이것을 먼저 소개해야합니다. 이로 인해 언어가 너무 복잡해질 수 있습니다.
Ingo

함수가 일부 인터페이스의 인스턴스가 아니어야합니까? 그들에게 특별한 점은 무엇입니까?
soc

Lisp / Scheme / Clojure는 객체를 모델링 할 수 있지만 Java / C #은 임의의 중첩 함수를 모델링 할 수 없습니다. 그러나 파이썬은 두 세계에서 가장 좋은 것 같습니다.
직업

답변:


15

객체 대 기능에 대한 논의는 빨간 청어라고 생각합니다. 질문이 "람다는 함수입니까 아니면 객체입니까?" 대답은 ' 예' 여야합니다 .

이것이 일급 기능의 요점입니다. 다른 유형과 다르게 취급되지 않습니다. Java는 이미 Object와 프리미티브 유형의 차이점을 무시하고 (Scala가 더 우수합니다) 람다는 Object의 하위 클래스인지 또는 새로운 프리미티브 유형인지 또는 실제로 언어에 중요하지 않은 항목인지 여부를 결정합니다. 중요한 것은 람다를 컬렉션에 넣고 호출하여 호출하고 호출하거나 객체 또는 메서드로 할 수있는 다른 작업을 수행 할 수 있다는 것입니다.

스칼라 apply는 그냥 호출 할 수 있는 메소드가있는 랩퍼 오브젝트를 사용하여이를 수행합니다.() 하여 메소드 호출처럼 보이게합니다. 이것은 훌륭하게 작동합니다. 대부분의 경우 메소드가 있거나 함수 객체의 적용을 호출하는지 여부를 신경 쓸 필요가 없습니다.


9

내가 이해 한 바에 따르면, 람다는 어떻게 기본 언어 수준에서 고려 것입니다. 이메일에서 알 수 있듯이

현재 디자인이 람다 (SAM 유형)의 개체 상자와 밀접하게 연결되어 있다고 생각할 수도 있습니다. 그러나 이것은 미래에 '네이 키드'람다를 고려하거나 람다에 대한 다른 변환 컨텍스트를 고려하거나 람다를 제어 구조에 더 밀접하게 통합 할 수 있도록 표면 영역에서 조심스럽게 숨겨져 있습니다. 우리는 지금 그렇게하지 않고 있으며,이를위한 구체적인 계획조차 가지고 있지 않지만, 앞으로 그렇게 할 수있는 능력은 디자인의 중요한 부분입니다.

나는 그것이 당신의 질문을 아주 잘 요약한다고 생각합니다. "lambdas는 객체"라고 선언하면 특정 클래스의 객체 일뿐입니다. 반면에 "lambdas는 함수"라고 선언하면 의미 적으로 하면 훨씬 더 풍부한 경기장이 있습니다. Java 1.7은 객체로 컴파일 할 수 있으므로 그 시점에서 실질적으로 동일합니다.

그러나 Java 1.8 또는 1.9는 훨씬 더 유연한 방식으로 함수를 사용할 수있게하는 것보다 언어 (예 : 구조화 된 유형)가 변경 될 수 있습니다. "lambdas가 객체"인 경우 이러한 변경 사항은 이전 버전과 호환되지 않으며 사람들의 기존 코드를 어 기지 않도록 새로운 개념을 도입해야합니다. 그러나 javac조용히 람다를 장면 뒤의 객체로 조용히 변환 했다면 새로운 javac의미 체계는 여전히 의미가 유지되는 한 원하는 것으로 변환 할 수 있습니다.


C #의 lamdas! = 델리게이트 컴파일러는 델리게이트 또는 표현식 트리로 컴파일 할 수 있습니다. 모두 실제로 객체 그래프하지만 그들은 컴파일되지 않습니다 "특정 클래스"도 특정 상속 트리의 경우에도 클래스
룬 FS를

올바르게 이해하면 람다를 객체의 내부 클래스로 컴파일하여 객체와 관련시킵니다. 따라서 앞으로 Java가 고차 함수 (동일한 레벨의 객체에서 함수)를 도입한다면 내부 클래스 구현을 사용할 수 없으며 불일치가 있습니다. Java가 곧 고차 함수를 가질 것이라고 생각하지 않습니다.
mwolfetech

@ mwolfetech : 내가 아는 한, 그들은 이미 방어자 방법으로 Java 8을 계획하고 있습니다. 그들은 같은 것들을 추가 할 foreach, map, filter컬렉션에.
soc

@soc 좋은 지적, JSR의 수와 그들이 실제로 JDK의 목표 버전을 완성하고 만들 것인지 여부를 따라 잡기가 어렵다. 방어자 방법이 동일한 JSR의 일부인 것 같습니다. 이 JSR 과 관련하여 Brian Goetz의 Lambda 주 게시물이 도움이되었습니다. SAM 유형과 람다 식 구현에 대한 현재 생각을 설명합니다.
mwolfetech

"현재 생각"mhhh, 2010 년 이후의 게시물은 이제 쓸모 없습니까?
soc

5

대부분, 그는 단지 너무 빨리 무언가에 헌신하고 싶지 않습니다. 그가 제시 한 소거를 넘어서는 이유는 보이지 않지만 실제로는 매우 강력한 이유입니다.

함수 유형이 마음에 들지 않습니다. 함수 유형이 마음에 들지만, Java 유형 시스템의 기존 측면 인 삭제와 관련하여 해당 함수 유형이 심하게 싸웠습니다. 지워진 함수 유형은 두 세계에서 최악입니다.

스칼라에서 다음 방법을 고려하십시오 Regex.

def replaceAllIn (target: CharSequence, replacer: (Match)  String): String
def replaceSomeIn (target: CharSequence, replacer: (Match)  Option[String]): String

그들이 단순히 이것이라면 더 간단 할 것입니다 :

def replace (target: CharSequence, replacer: (Match)  String): String
def replace (target: CharSequence, replacer: (Match)  Option[String]): String

불행히도,이 두 기능 은 지워도 동일 하기 때문에 불가능합니다 . 그러나 이러한 기능은 다소 다른 기능을 수행하므로 다른 이름으로도 충분할 수 있습니다.

그러나 a Match는 매우 유용하지만 대부분 일치 String하거나 하위 그룹 목록을 원합니다 . 우리는 이것을 원합니다 :

def replaceAllIn (target: CharSequence, replacer: (String)  String): String
def replaceAllIn (target: CharSequence, replacer: (Seq[String])  String): String
def replaceAllIn (target: CharSequence, replacer: (Match)  String): String

삭제로 인해 불가능합니다. 나는이 특정 예제를 직접 선택했기 때문에이 예제를 선택했지만, 사람들이이 정확한 문제로 인해 과부하가 왜 불법인지 묻는 질문에 스택 오버플로에 대해 적어도 6 가지 질문을 보았습니다.

그런 다음 스칼라의 패턴 일치와 Java instanceof는 삭제 때문에 효과적으로 쓸모가 없다고 생각하십시오.

이 문제가 해결 될 때까지 함수 유형을 지연시키는 것이 공정하다고 생각합니다. 결국 JVM에는 많은 언어가 있으며 Java가 빠르게 진화하는 언어와 다릅니다.


글쎄, 만약 유형 삭제가 그들이 가진 유일한 문제라면, 그들은 무엇을 할 계획입니까? 이 행성의 모든 코드를 깨는 것은 이미 Java 5에 대한 옵션이 아닌 것으로 판명되었습니다 ...
soc

@ soc 나는 그들의 신발에 없어서 기쁘다! 그러나 그것은 Sun이었습니다. 이것은 Oracle입니다. 오라클은 주요 제품의 주요 버전과 마이너 버전 사이에서 주요 변경 사항을 적용한 적이 없습니다.
Daniel C. Sobral

어쩌면 그들은 언어의 이름을 바꾸고 새로운 언어를 개발하여 호환성을 떨어 뜨려야 할 것입니다. 따라서 오래되고 잘 정립 된 언어를 가지고 놀 필요없이 새로운 언어의 이점을 누릴 수 있습니다. 결국, 이것이 Scala와 Clojure가 한 일입니다.
Giorgio

@Giorgio 그것은 무의미 할 것입니다. 당신이 말한대로 음, 자바 오늘 무엇인지를 담당하는 사람들 중 일부는, 그했지만, 거기에 있는 대안. 그러나 Java를 담당하는 사람들 은 Java 자체를 개선해야 합니다. 결국 Java에 대한 책임 이 있습니다. 유일한 대안은 단순히 Java를 삭제하고 Java를 제어함으로써 발생하는 모든 이점을 포기하는 것입니다.
Daniel C. Sobral

@Daniel C. Sobral : IMO 프로그래밍 언어는 일종의 소프트웨어와 비슷합니다. 처음에는 깨끗하고 잘 디자인 될 수 있지만 더 많이 사용할수록 더 복잡해집니다. 따라서 개발자는 Java를 언어로 고정하고 (1) 새 라이브러리를 만들거나 기존 라이브러리를 개선하고, (2) 가능한 경우 JVM을 개선하고 (3) 새로운 언어를 개발하는 데 집중해야합니다. . 그러나 당신이 말했듯이 Java를 책임지고 업그레이드 판매를 계속하려는 사람들이 있습니다. 그래서 그들은 그것을 "시원하게"유지하기 위해 확장 할 것입니다. 그냥 내 2 센트.
조르지오
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.