Option [T] 클래스의 요점은 무엇입니까?


83

나는 Option[T]Scala에서 수업 의 요점을 이해할 수 없습니다 . 내 말은, 나는 Noneover의 어떤 이점도 볼 수 없다는 것을 의미 null합니다.

예를 들어 다음 코드를 고려하십시오.

object Main{
  class Person(name: String, var age: int){
    def display = println(name+" "+age)
  }

  def getPerson1: Person = {
    // returns a Person instance or null
  }

  def getPerson2: Option[Person] = {
    // returns either Some[Person] or None
  }

  def main(argv: Array[String]): Unit = {
    val p = getPerson1
    if (p!=null) p.display

    getPerson2 match{
      case Some(person) => person.display
      case None => /* Do nothing */
    }
  }
}

이제 방법, 가정 getPerson1반환 null후 전화가 만든 display의 첫 번째 줄에 main실패 할 수밖에 없다 NPE. 마찬가지로 getPerson2returns None이면 display유사한 오류와 함께 호출이 다시 실패합니다.

그렇다면 왜 Scala Option[T]는 Java에서 사용되는 간단한 접근 방식을 따르는 대신 새로운 값 래퍼 ( )를 도입하여 문제를 복잡하게 만들 까요?

최신 정보:

@Mitch 의 제안에 따라 코드를 편집했습니다 . 나는 여전히의 특별한 이점을 볼 수 없습니다 Option[T]. 예외적 인 경우 null또는 None두 경우 모두 테스트해야합니다 . :(

@Michael의 회신 에서 올바르게 이해했다면 유일한 장점은 이 메서드가 None을 반환 할 수 있다고Option[T] 프로그래머에게 명시 적으로 알려주는 것입니다 . 이것이이 디자인 선택의 유일한 이유입니까?


23
실제로 Option [T]의 "get"메서드는 "대체 패턴이 일치하지 않는 이유는 무엇입니까?"라고 발음됩니다.
Mitch Blevins

2
미치 말이 맞아. 사용하지 않고 예를 바꿔보십시오 get, 당신은 것입니다 를. :-)
Daniel C. Sobral

당신은 java .. .try val p = ... 인 Person p ..를 가지고 있습니다. 또한 아래의 Daniel과 Synesso가 보여주는 Option에 더 많은 것이 있습니다-여기에 몇 가지 훌륭한 답변이 있습니다.
Michael Neale 2010-01-17

@Michael : 죄송합니다! 지적 해 주셔서 감사합니다. 수정했습니다.
missingfaktor

답변:


72

Option절대로 절대 .NET을 사용하지 않도록 강요하면 더 나은 점을 얻을 수 있습니다 get. 그 이유 get는 "ok, 나를 null-land로 돌려 보내줘"와 동일 하기 때문 입니다.

그래서 당신의 예를 들어보십시오. display사용하지 않고 어떻게 전화 get하겠습니까? 다음은 몇 가지 대안입니다.

getPerson2 foreach (_.display)
for (person <- getPerson2) person.display
getPerson2 match {
  case Some(person) => person.display
  case _ =>
}
getPerson2.getOrElse(Person("Unknown", 0)).display

이 대안 중 display어떤 것도 존재하지 않는 것을 호출하도록 허용 하지 않습니다.

get존재 하는지에 관해서 Scala는 코드 작성 방법을 알려주지 않습니다. 그것은 당신을 부드럽게 자극 할 수 있지만, 안전망이없는 상태로 돌아가고 싶다면 그것은 당신의 선택입니다.


여기에 못 박았습니다.

Option [T]의 유일한 장점은이 메서드가 None을 반환 할 수 있다는 것을 프로그래머에게 명시 적으로 알려주는 것입니다.

"전용"을 제외하고. 그러나 다른 방식으로 다시 말씀 드리겠습니다 . over 의 주요 이점 은 형식 안전성입니다. 컴파일러가 허용하지 않으므로 존재하지 않을 수있는 객체에 메서드를 전송 하지 않도록합니다.Option[T]TT

두 경우 모두 null 허용 여부를 테스트해야한다고 말했지만 잊어 버렸거나 모르는 경우 null을 확인해야합니다. 컴파일러가 알려줄까요? 아니면 사용자가?

물론 Java와의 상호 운용성 때문에 Scala는 Java와 마찬가지로 null을 허용합니다. 따라서 Java 라이브러리를 사용하거나 잘못 작성된 Scala 라이브러리를 사용하거나 잘못 작성된 개인 Scala 라이브러리 를 사용하는 경우 여전히 널 포인터를 처리해야합니다.

Option제가 생각할 수있는 다른 두 가지 중요한 이점 은 다음과 같습니다.

  • 문서 : 메소드 유형 서명은 객체가 항상 반환되는지 여부를 알려줍니다.

  • 모나 딕 구성 가능성.

후자는 완전히 이해하는 데 훨씬 오래 걸리며 복잡한 코드에서만 강점을 보여주기 때문에 간단한 예제에는 적합하지 않습니다. 그래서 아래에 예를 들어 보 겠지만, 이미받은 사람들을 제외하고는 거의 의미가 없다는 것을 잘 알고 있습니다.

for {
  person <- getUsers
  email <- person.getEmail // Assuming getEmail returns Option[String]
} yield (person, email)

5
"절대, 절대로 사용하지 않도록 강요 get"-> 그래서, 즉 "당신은 그렇지 않습니다 get!" :)
fredoverflow 2013

31

비교:

val p = getPerson1 // a potentially null Person
val favouriteColour = if (p == null) p.favouriteColour else null

와:

val p = getPerson2 // an Option[Person]
val favouriteColour = p.map(_.favouriteColour)

스칼라에서 함수 로 나타나는 모나 딕 속성 bind를 사용하면 객체가 'null'인지 여부에 대한 걱정없이 객체에 대한 작업을 연결할 수 있습니다.

이 간단한 예를 좀 더 살펴 보겠습니다. 사람들 목록에서 가장 좋아하는 색상을 모두 찾고 싶다고 가정 해 보겠습니다.

// list of (potentially null) Persons
for (person <- listOfPeople) yield if (person == null) null else person.favouriteColour

// list of Options[Person]
listOfPeople.map(_.map(_.favouriteColour))
listOfPeople.flatMap(_.map(_.favouriteColour)) // discards all None's

또는 아버지의 어머니의 여동생 이름을 찾고 싶을 수도 있습니다.

// with potential nulls
val father = if (person == null) null else person.father
val mother = if (father == null) null else father.mother
val sister = if (mother == null) null else mother.sister

// with options
val fathersMothersSister = getPerson2.flatMap(_.father).flatMap(_.mother).flatMap(_.sister)

나는 이것이 옵션이 어떻게 삶을 좀 더 쉽게 만들 수 있는지에 대한 약간의 빛을 비추 길 바랍니다.


마지막 예에서 사람의 아버지가 null이면 어떻게됩니까? map반환 None되고 일부 오류와 함께 호출이 실패합니다. null접근 방식 보다 어떻게 낫 습니까?
missingfaktor

5
아니요. 사람이 없음 (또는 아버지, 어머니 또는 자매)이면 fathersMothersSister는 None이되지만 오류는 발생하지 않습니다.
패러다임

6
지도가 아니라 flatMap을 의미한다고 생각합니다.
retronym

편집 Daniel 주셔서 감사합니다. 나는 그것을 게시하기 전에 코드를 시도하지 않았습니다. 다음에 더 잘할 것입니다.
Synesso

2
val favouriteColour = if (p == null) p.favouriteColour else null // 정확히 Option이 방지하는 데 도움이되는 오류! 이 대답은 아무도이 오류를 발견하지 않고 수년간 여기에있었습니다!
Mark Lister 2013

22

차이는 미묘합니다. 진정한 함수라는 점을 명심하십시오 . 값을 반환 해야합니다. null은 그런 의미에서 실제로 "일반 반환 값"으로 간주되지 않으며 더 낮은 유형의 / nothing입니다.

그러나 실질적인 의미에서 선택적으로 무언가를 반환하는 함수를 호출하면 다음을 수행합니다.

getPerson2 match {
   case Some(person) => //handle a person
   case None => //handle nothing 
}

물론, null과 비슷한 것을 할 수 있습니다. 그러나 이것은 getPerson2그것이 반환된다는 사실로 인해 호출의 의미를 분명 하게 만듭니다 Option[Person](다른 사람이 문서를 읽고 NPE를 읽지 않기 때문에 NPE를 얻는 것 외에는 좋은 실용적인 것입니다. 문서).

나는 내가 할 수있는 것보다 더 엄격한 대답을 줄 수있는 기능적인 프로그래머를 찾으려고 노력할 것이다.


1
이것은 옵션에 대한 나의 이해이기도합니다. 그것은 프로그래머에게 우리가 None을 얻을 수 있다는 것을 명시 적으로 알려줍니다. 만약 여러분이 Some (T)를 기억할만큼 충분히 어리석지 만 None을 잡지 못한다면 문제에 처한 것입니다.
cflewis

1
Lewisham-Some / None이 대수적 데이터 유형 (추상 봉인 된 특성 ...)을 형성하므로 컴파일러가 경고를 줄 것이라고 생각합니다.
Michael Neale

6
옵션 유형을 사용하는 대부분의 언어에서 옵션 유형의 요점은 런타임 널 예외 대신 컴파일 시간 유형 오류가 발생한다는 것입니다. 컴파일러는 데이터를 사용할 때 없음 조건에 대한 조치가 없음을 알 수 있습니다. 유형 오류입니다.
Justin Smith

15

나에게 옵션은 이해 구문으로 처리 할 때 정말 흥미 롭습니다. 촬영 synesso 앞의 예 :

// with potential nulls
val father = if (person == null) null else person.father
val mother = if (father == null) null else father.mother
val sister = if (mother == null) null else mother.sister

// with options
val fathersMothersSister = for {
                                  father <- person.father
                                  mother <- father.mother
                                  sister <- mother.sister
                               } yield sister

할당 중 하나가 None인 경우 fathersMothersSisterNone이지만 no NullPointerException는 발생합니다. 그런 다음 fathersMothersSister걱정없이 Option 매개 변수를 사용하는 함수에 안전하게 전달할 수 있습니다 . 그래서 당신은 null을 확인하지 않고 예외를 신경 쓰지 않습니다. 이것을 synesso 예제에 제시된 Java 버전과 비교하십시오 .


3
Scala에서 <-구문이 "list comprehension syntax"에 국한되어 있다는 것은 부끄러운 일입니다. doHaskell 의보다 일반적인 구문이나 domonadClojure의 모나드 라이브러리의 형식 과 실제로 동일하기 때문 입니다. 목록에 묶으면 짧게 팔립니다.
seh

11
Scala의 "For comprehensions"는 본질적으로 Haskell의 "do"입니다. 목록에 국한되지 않고 다음을 구현하는 모든 것을 사용할 수 있습니다. def map [B] (f : A => B) : C [B] def flatMap [B] (f : A => C [B]) : C [B] def filter (p : A => Boolean) : C [A]. IOW, 모든 모나드
GClaramunt

2
@seh @GClaramunt의 의견을 찬성했지만 그의 요점을 충분히 강조 할 수는 없습니다. Scala에서 for-comprehensions와 목록 사이 에는 연결 이 없습니다. 단, 후자는 전자와 함께 사용할 수 있습니다. stackoverflow.com/questions/1052476/…을 참조하십시오 .
Daniel C. Sobral

예, 저는 관계가 없다는 것을 알고 있지만 지적 할 가치가 있다는 데 동의합니다. 패러다임에서 "목록 이해 구문"을 언급하는이 답변의 첫 번째 줄에 대해 언급했습니다. 언어 디자인 문제가 아니라 교육 문제입니다.
seh

9

Option을 사용하면 매우 강력한 구성 기능이 있습니다.

def getURL : Option[URL]
def getDefaultURL : Option[URL]


val (host,port) = (getURL orElse getDefaultURL).map( url => (url.getHost,url.getPort) ).getOrElse( throw new IllegalStateException("No URL defined") )

이것을 완전히 설명해 주시겠습니까?
Jesvin Jose

8

다른 누군가가 이것을 지적했을 수도 있지만 나는 그것을 보지 못했습니다.

Option [T] 대 null 검사를 사용한 패턴 일치의 한 가지 장점은 Option이 봉인 된 클래스이므로 Some 또는 None 케이스를 코딩하지 않으면 Scala 컴파일러가 경고를 발행한다는 것입니다. 경고를 오류로 바꾸는 컴파일러 플래그가 컴파일러에 있습니다. 따라서 런타임이 아닌 컴파일 타임에 "존재하지 않음"사례를 처리하지 못하는 것을 방지 할 수 있습니다. 이것은 null 값을 사용하는 것보다 큰 이점입니다.


7

null 검사를 피하는 데 도움이되는 것이 아니라 강제로 null 검사를 수행하는 것입니다. 클래스에 10 개의 필드가 있고 그 중 2 개는 null 일 수있을 때 요점이 분명해집니다. 그리고 시스템에는 50 개의 다른 유사한 클래스가 있습니다. Java 세계에서는 정신적 기능, 명명 규칙 또는 주석을 조합하여 해당 필드에서 NPE를 방지하려고합니다. 그리고 모든 Java 개발자는이 점에서 상당한 수준으로 실패합니다. Option 클래스는 코드를 이해하려는 개발자에게 "nullable"값을 시각적으로 명확하게 할뿐만 아니라 컴파일러가 이전에 말하지 않은이 계약을 시행 할 수 있도록합니다.


6

[복사 이 댓글 에 의해 다니엘 스피 웍 ]

사용하는 유일한 방법 Option이 값을 얻기 위해 패턴 일치 를 사용하는 것이라면 예, 나는 그것이 null을 통해 전혀 개선되지 않는다는 데 동의합니다. 그러나 기능의 * 거대한 * 클래스가 누락되었습니다. 사용하는 유일한 이유 Option는 고차 유틸리티 기능 을 사용 하는 경우입니다. 효과적으로, 당신은 모나 딕 특성을 사용해야합니다. 예를 들어 (일정량의 API 트리밍을 가정) :

val row: Option[Row] = database fetchRowById 42
val key: Option[String] = row flatMap { _ get “port_key” }
val value: Option[MyType] = key flatMap (myMap get)
val result: MyType = value getOrElse defaultValue

거기, 멋지지 않았나요? for-comprehensions 를 사용하면 실제로 훨씬 더 잘할 수 있습니다 .

val value = for {
row <- database fetchRowById 42
key <- row get "port_key"
value <- myMap get key
} yield value
val result = value getOrElse defaultValue

null, None 또는 ilk를 명시 적으로 확인하지 * 않습니다 *. Option의 요점은 이러한 검사를 피하는 것입니다. 문자열 계산을 수행하고 * 정말 * 값을 얻을 필요가있을 때까지 아래로 이동합니다. 이 시점에서 명시 적 검사를 수행할지 여부를 결정할 수 있습니다. 하지 않아도되는 작업) 기본값을 제공하고 예외를 throw하는 등의 작업을 수행 할 수 있습니다.

나는 절대로에 대해 명시적인 매칭을하지 않으며, Option같은 배에있는 다른 스칼라 개발자를 많이 알고 있습니다. 데이비드 폴락은 그가 그러한 명시 적 일치를 사용하는 것이 바로 일전에 나에게 언급 Option(또는 Box 은 코드를 작성한 개발자가 언어와 표준 라이브러리를 완전히 이해하지 못한다는 신호로 Lift의 경우)를 .

나는 트롤 망치가되는 것을 의미하지는 않지만 실제로 언어 기능이 실제로 사용되는 방식을 살펴보고 쓸모없는 것으로 간주하기 전에 살펴 봐야합니다. 나는 Option이 * 당신 *이 그것을 사용했기 때문에 상당히 매력적이지 않다는 것에 절대적으로 동의하지만, 당신은 그것이 설계된 방식으로 사용하고 있지 않습니다.


여기에 슬픈 결과가 있습니다. 점프 기반 단락이 없으므로 연속적인 모든 명령문 OptionNone다시 for를 테스트 합니다. 문이 중첩 된 조건문으로 작성 되었다면 각 잠재적 "실패"는 한 번만 테스트되고 조치됩니다. 귀하의 예에서의 결과는 의 초기화 를 안내하기 위해 한 번 , 's에 대해, 마지막으로 's에 대해 fetchRowById효과적으로 검사 됩니다. 작성하는 우아한 방법이지만 런타임 비용이없는 것은 아닙니다. keyvalueresult
seh

4
스칼라의 이해를 오해하신 것 같습니다. 두 번째 예는 루프가 아니라 컴파일러에 의해 일련의 flatMap 연산으로 변환됩니다.
Kevin Wright

여기에 댓글을 쓴 지 오래되었지만 방금 Kevin 's를 봤습니다. Kevin, "당신은 오해"라고 썼을 때 누구를 언급 했습니까? 나는 수 있었다 표시되지 않습니다 나에게 내가 루프에 대해 아무것도 언급하지로.
seh

6

여기에서 아무도 제기하지 않은 한 가지 요점은 null 참조를 가질 수 있지만 Option에 의해 도입 된 구별이 있다는 것입니다.

그것은 당신이 할 수있다 Option[Option[A]]거주 될 수있는 None, Some(None)그리고 Some(Some(a))어디 a의 일반적인 주민 중 하나입니다 A. 즉, 어떤 종류의 컨테이너가 있고 그 안에 널 포인터를 저장하고 꺼내고 싶다면 실제로 값을 얻었는지 알기 위해 추가 부울 값을 다시 전달해야합니다. 이와 같은 사마귀 는 자바 컨테이너 API에 풍부 하며 일부 잠금없는 변형은이를 제공 할 수도 없습니다.

null 일회성 구조로, 자체적으로 구성되지 않고 참조 유형에만 사용할 수 있으며 전체가 아닌 방식으로 추론하도록 강요합니다.

예를 들어,

if (x == null) ...
else x.foo()

당신은 else지점 전체에 걸쳐 당신의 머릿속을 가지고 다녀야 x != null하고 이것은 이미 확인되었습니다. 그러나 옵션과 같은 것을 사용할 때

x match {
case None => ...
case Some(y) => y.foo
}

당신 y가 None건설에 의한 것이 아니라는 것을 알고 있습니다. 그리고 null그것이 Hoare의 10 억 달러 실수 가 아니었다면 그것도 아니었다는 것을 알고있을 것 입니다.


3

Option [T]는 모나드로, 값을 조작하기 위해 고차 함수를 사용할 때 매우 유용합니다.

아래에 나열된 기사를 읽을 것을 제안 할 것입니다.이 기사는 Option [T]가 왜 유용한 지, 어떻게 기능적으로 사용할 수 있는지를 보여주는 좋은 기사입니다.


추천 읽기 목록에 추가하겠습니다 Tony Morris의 최근 게시 된 자습서 "모나드는 무엇을 의미합니까?": projects.tmorris.net/public/what-does-monad-mean/artifacts/1.0/…
Randall Schulz

3

Randall의 답변 티저에 추가 하여 값의 잠재적 부재가로 표현되는 이유를 Option이해하려면 OptionScala의 다른 많은 유형, 특히 유형 모델링 모나드와 공유 하는 내용을 이해해야합니다 . 하나가 null로 값이 없음을 나타내는 경우 해당 부재-존재 구별은 다른 모나드 유형이 공유하는 계약에 참여할 수 없습니다.

모나드가 무엇인지 모르거나 스칼라 라이브러리에서 모나드가 어떻게 표현되는지 알지 못한다면, 무엇이 Option함께 작동하는지 볼 수없고 놓치고있는 것을 볼 수 없습니다. Option모나드 개념이없는 경우에도 주목할만한 null 대신 사용 하는 많은 이점이 있습니다 (여기에 "Cost of Option / Some vs null" 스칼라 사용자 메일 링 목록 스레드 에서 일부 논의). 격리는 특정 연결 목록 구현의 반복자 유형에 대해 이야기하는 것과 비슷합니다. 필요한 이유를 궁금해하는 동시에보다 일반적인 컨테이너 / 반복자 / 알고리즘 인터페이스를 놓치고 있습니다. 여기에도 더 광범위한 인터페이스가 있습니다.Option


링크 주셔서 감사합니다. 정말 유용했습니다. :)
missingfaktor

스레드에 대한 귀하의 의견은 너무 간결하여 요점을 거의 놓쳤습니다. 나는 null이 금지 될 수 있기를 정말로 바란다.
Alain O'Dea

2

나는 키가 Synesso의 대답에서 발견된다고 생각합니다. Option은 주로 null의 성가신 별칭으로 유용 하지 않지만 논리를 도울 수있는 완전한 객체로 유용합니다.

null의 문제는 는 객체 없다는 것 입니다. 이 문제를 처리하는 데 도움이 될 수있는 방법이 없습니다 (언어 디자이너로서 실제로 원하는 경우 개체를 에뮬레이트하는 언어에 점점 더 긴 기능 목록을 추가 할 수 있음).

Option이 할 수있는 한 가지는 null을 에뮬레이트하는 것입니다. 그런 다음 특별 값 "null"대신 특별 값 "None"을 테스트해야합니다. 두 경우 모두 잊어 버리면 나쁜 일이 일어납니다. 옵션은 "get"을 입력해야하므로 우연히 발생할 가능성이 적습니다 . null 일 , 어, 없음을 의미합니다). 이것은 여분의 래퍼 객체를 대신하여 작은 이점입니다. .

Option이 실제로 그 힘을 보여주기 시작하는 곳은 내가 원하지만 실제로는 가지고 있지 않다는 개념을 다루는 데 도움이됩니다.

null 일 수있는 작업으로 수행 할 수있는 작업을 고려해 봅시다.

null이 있으면 기본값을 설정하고 싶을 수도 있습니다. Java와 Scala를 비교해 보겠습니다.

String s = (input==null) ? "(undefined)" : input;
val s = input getOrElse "(undefined)"

다소 번거로운? : 구조 대신에 "내가 null 인 경우 기본값 사용"이라는 아이디어를 다루는 메서드가 있습니다. 이렇게하면 코드가 약간 정리됩니다.

실제 가치가있는 경우에만 새 개체를 만들고 싶을 수도 있습니다. 비교:

File f = (filename==null) ? null : new File(filename);
val f = filename map (new File(_))

Scala는 약간 더 짧고 다시 오류의 원인을 피합니다. 그런 다음 Synesso, Daniel 및 paradigmatic의 예에 표시된 것처럼 여러 항목을 함께 연결해야 할 때의 누적 이점을 고려하십시오.

광대 하지 않다 개선,하지만 당신은 모든 것을 추가하는 경우 (당신이 어떤 (x)의 래퍼 객체를 생성 심지어 작은 오버 헤드를 피하기 위해 원하는 곳), 그것은 어디에서나 매우 높은 성능의 코드를 저장 잘 가치가있다.

일치 사용은 null / None 케이스에 대해 경고하는 장치를 제외하고는 그다지 도움이되지 않습니다. 정말 도움이되는 경우는 연결을 시작할 때입니다. 예를 들어 옵션 목록이있는 경우 :

val a = List(Some("Hi"),None,Some("Bye"));
a match {
  case List(Some(x),_*) => println("We started with " + x)
  case _ => println("Nothing to start with.")
}

이제 None 사례와 List-is-empty 사례를 모두 원하는 값을 정확하게 끌어내는 하나의 편리한 문으로 접을 수 있습니다.


2

Null 반환 값은 Java와의 호환성을 위해서만 존재합니다. 다른 방법으로 사용해서는 안됩니다.


1

정말 프로그래밍 스타일의 질문입니다. Functional Java를 사용하거나 자체 헬퍼 메소드를 작성하면 Option 기능을 사용할 수 있지만 Java 언어를 포기할 수는 없습니다.

http://functionaljava.org/examples/#Option.bind

Scala에 기본적으로 포함되어 있다고해서 특별하지는 않습니다. 기능적 언어의 대부분의 측면은 해당 라이브러리에서 사용할 수 있으며 다른 Java 코드와 잘 공존 할 수 있습니다. 널로 Scala를 프로그래밍하도록 선택할 수있는 것처럼 널없이 Java를 프로그래밍하도록 선택할 수 있습니다.


0

그것이 glib 대답이라는 것을 미리 인정하면 Option은 모나드입니다.


나는 그것이 모나드라는 것을 압니다. 문제에 "monad"태그를 추가해야하는 이유는 무엇입니까?
missingfaktor

^ 위의 문장이 모나드가 무엇인지 이해한다는 의미는 아닙니다. : D
missingfaktor

4
모나드는 멋지다. 당신이 이해하는 척하지 않는 그들 또는 적어도를 사용하지 않는 경우에 당신은 ;-) 냉각되지 않습니다
패러다임

0

사실 나는 당신과 의심을 공유합니다. 옵션에 대해 1) 성능 오버 헤드가 있다는 사실이 정말 괴롭습니다. 2) 코드에서 Some과 Option을 많이 사용해야합니다.

따라서이 언어 디자인 결정의 장단점을 확인하려면 대안을 고려해야합니다. Java는 null 가능성 문제를 무시하기 때문에 대안이 아닙니다. 실제 대안은 Fantom 프로그래밍 언어를 제공합니다. nullable 및 non-nullable 유형이 있으며?. ? : Scala의 map / flatMap / getOrElse 대신 연산자. 비교에서 다음 글 머리 기호를 볼 수 있습니다.

옵션의 장점 :

  1. 더 간단한 언어-추가 언어 구성이 필요하지 않습니다.
  2. 다른 모나드 유형과 균일

Nullable의 장점 :

  1. 일반적인 경우 더 짧은 구문
  2. 더 나은 성능 (새 Option 객체와 map, flatMap 용 람다를 만들 필요가 없기 때문에)

따라서 여기에는 명백한 승자가 없습니다. 그리고 한 가지 더. Option 사용에 대한 주요 구문상의 이점은 없습니다. 다음과 같이 정의 할 수 있습니다.

def nullableMap[T](value: T, f: T => T) = if (value == null) null else f(value)

또는 일부 암시 적 변환을 사용하여 점이있는 간단한 구문을 얻습니다.


현대 VM의 성능 저하에 대한 확실한 벤치 마크를 수행 한 사람이 있습니까? 이스케이프 분석은 많은 임시 옵션 객체를 스택에 할당 할 수 있으며 (힙보다 훨씬 저렴) 세대 별 GC는 임시 객체를 약간 덜 효율적으로 처리합니다. 물론 NPE를 피하는 것보다 프로젝트에서 속도가 더 중요하다면 옵션이 적합하지 않을 수 있습니다.
Justin W

백업 할 숫자없이 성능 오버 헤드를 언급하지 마십시오. 이것은 Option과 같은 추상화에 반대 할 때 매우 흔한 실수입니다. 벤치 마크를 가리 키거나 게시하거나 성능 주석을 제거하면 기꺼이 내 반대표를 되돌릴 것입니다. :)
Alain O'Dea

0

명시 적 옵션 유형을 갖는 진짜 장점은 당신이 할 수 있다는 것입니다 없는 모든 장소의 98 %에서 사용, 따라서 정적으로 배제 널 예외. (그리고 나머지 2 %에서는 유형 시스템이 실제로 액세스 할 때 제대로 확인하도록 상기시킵니다.)


-3

Option이 작동하는 또 다른 상황은 유형이 널값을 가질 수없는 상황입니다. Int, Float, Double 등의 값에는 null을 저장할 수 없지만 Option을 사용하면 None을 사용할 수 있습니다.

Java에서는 이러한 유형의 박스형 버전 (Integer, ...)을 사용해야합니다.

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