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.