복붙노트

[SCALA] 클래스 옵션 [T]의 점은 무엇입니까?

SCALA

클래스 옵션 [T]의 점은 무엇입니까?

나는 스칼라에서 옵션 [T] 클래스의 점을 이해할 수 없습니다입니다. 내가 널 이상 없음의 advanages을 볼 수 없습니다 오전 의미한다.

예를 들어, 코드를 살펴 보자 :

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 */
    }
  }
}

이제, null를 돌려 getPerson1 방법을 가정, 다음 호출은 메인이 NPE와 함께 실패 할 수밖에 없다의 첫 번째 줄에 표시했다. getPerson2 없음을 반환 마찬가지로 경우, 디스플레이 호출은 다시 몇 가지 유사한 오류로 실패합니다.

그렇다면, 왜 스칼라는 자바에서 사용하는 방법을 간단하게 예를 들어 새 값 래퍼 (옵션 [T]를) 도입 대신에 따라 일을 복잡하게 하는가?

최신 정보:

나는 미치의 제안 @ 따라 내 코드를 편집했습니다. 나는 아직도 옵션의 특정 장점 [T]를 볼 수 없습니다입니다. 나는 두 경우 모두에서 뛰어난 null 또는 없음을 테스트해야합니다. :(

나는 마이클의 답변 @에서 제대로 이해 한 경우, 옵션의 유일한 장점은 [T]를 명시 적으로이 방법은 None을 반환 할 수있는 프로그래머를 알 수 있다는 것입니다? 이것은이 디자인 선택 뒤에있는 유일한 이유인가?

해결법

  1. ==============================

    1.당신이 결코, 이제까지 얻을 사용하지 않는 자신을 강제하는 경우 당신은 더 나은 옵션의 포인트를 얻을 수 있습니다. GET은 동등한이기 때문 "확인이 널 땅에 다시 나를 보내"입니다.

    당신이 결코, 이제까지 얻을 사용하지 않는 자신을 강제하는 경우 당신은 더 나은 옵션의 포인트를 얻을 수 있습니다. GET은 동등한이기 때문 "확인이 널 땅에 다시 나를 보내"입니다.

    그래서, 당신의 예를 취할. 당신은 어떻게 GET을 사용하지 않고 디스플레이를 부를 것이다? 여기에 몇 가지 대안은 다음과 같습니다 :

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

    이 대안 중 어느 것도 존재하지 않는 무언가에 표시를 호출 할 수 없습니다.

    GET이 존재하는 이유에 관해서는, 스칼라는 코드를 작성하는 방법을 알려하지 않습니다. 그것은 부드럽게 당신을 자극 할 수 있지만 더 안전망으로 폴백하려는 경우, 그것은 당신의 선택입니다.

    당신은 여기에 못을 박았다 :

    은 "전용"을 제외하고. 그러나 나를 다른 방법으로 그것을 다시 언급하자 : T를 통해 옵션의 가장 큰 장점 [T]는 안전을 입력합니다. 이 컴파일러는 당신을 못하게 당신이, 존재하지 않을 수 있습니다 개체에 T 방법을 발송하지 않습니다 보장합니다.

    또는 모르는 - - 당신이 널 (null)를 확인해야합니다, 컴파일러는 당신을 말할 것이다 당신은 당신이 두 경우 모두에서 Null 허용 여부를 테스트해야하지만, 당신이 잊어 버린 경우 말했다? 또는 사용자를 할 것인가?

    물론, 때문에 자바와의 상호 운용성, 스칼라는 자바가하는 것처럼 널 (null)을 할 수 있습니다. 당신이 잘못 기록 된 스칼라 라이브러리를 사용한다면 당신은 자바 라이브러리를 사용하는 경우, 또는 잘못 기록 된 개인 스칼라 라이브러리를 사용하는 경우, 당신은 여전히 ​​널 포인터를 처리해야합니다.

    내가 생각할 수있는 옵션의 다른 두 가지 중요한 장점은 다음과 같습니다

    후자는 더 이상 완벽에 소요 주셔서 감사 드리며, 그것은 단지 복잡한 코드에 그것의 힘을 보여줍니다으로는, 간단한 예제에 적합하지 않습니다. 그래서, 아래의 예를 줄 것이다, 그러나 나는 거의 이미 그것을 얻을 사람들을 제외하고 아무 의미가없는 것 잘 알고 있어요.

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

    2.비교:

    비교:

    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)
    

    지도 함수로 스칼라에 나타나는 모나드 속성 바인딩은, 그들이 '널 (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)
    

    나는이 옵션은 인생을 좀 더 쉽게 할 수있는 방법에 많은 도움이 되길 바랍니다.

  3. ==============================

    3.차이는 미묘하다. 진정한 함수가 값을 반환해야 될 명심 - 널 ​​정말 그런 의미에서 "정상적인 반환 값」, 더 바닥 형 / 아무것도로 간주되지 않습니다.

    차이는 미묘하다. 진정한 함수가 값을 반환해야 될 명심 - 널 ​​정말 그런 의미에서 "정상적인 반환 값」, 더 바닥 형 / 아무것도로 간주되지 않습니다.

    그러나, 실제적인 의미에서, 당신은 선택적으로 뭔가를 반환하는 함수를 호출 할 때, 당신은 할 것이다 :

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

    허락하신다면, 당신은 널 (null)와 비슷한 작업을 수행 할 수 있습니다 -하지만이는 문서를 읽는 사람에 의존하고 NPE을 얻는 것보다 옵션 [사람] (멋진 실용적인 것, 다른 반환 사실의 덕분으로 getPerson2 분명 호출의 의미를 만드는 그들이 있기 때문에 )이 문서를 읽을 수 없습니다.

    내가 노력하고 내가 할 수있는보다 엄격한 답을 줄 수있는 기능 프로그래머를 발굴합니다.

  4. ==============================

    4.이해 구문으로 처리 할 때 나를 위해 옵션은 정말 재미있다. 앞의 예 synesso 촬영 :

    이해 구문으로 처리 할 때 나를 위해 옵션은 정말 재미있다. 앞의 예 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
    

    대입 중 하나가 아무도없는 경우, fathersMothersSister은 아무도 없을 것입니다하지만 NullPointerException이가 발생되지 않습니다. 그런 다음 안전하게 걱정없이 옵션 매개 변수를 복용하는 기능을 fathersMothersSisterto 전달할 수 있습니다. 그래서 당신은 널 (null)을 확인하지 않고 당신은 예외의 상관하지 않습니다. synesso 예에서 제시 한 자바 버전이 비교.

  5. ==============================

    5.당신은 옵션 꽤 강력한 구성 기능이 :

    당신은 옵션 꽤 강력한 구성 기능이 :

    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") )
    
  6. ==============================

    6.어쩌면 다른 사람이이 점을 지적,하지만 난 그것을 보지 못했다 :

    어쩌면 다른 사람이이 점을 지적,하지만 난 그것을 보지 못했다 :

    옵션 [T] 대 널 체크 패턴 매칭의 장점 중 하나는 당신이 중 하나를 일부 또는 없음 경우 코드를 게을리하면 스칼라 컴파일러가 경고를 발행 할 수 있도록하는 옵션, 봉인 클래스입니다. 오류로 경고를 켜집니다 컴파일러 컴파일러 플래그가있다. 그래서 컴파일 타임이 아닌 런타임에 "존재하지 않는"경우를 처리 할 수있는 오류를 방지 할 수 있습니다. 이것은 null 값의 사용에 엄청난 장점이다.

  7. ==============================

    7.그것은 널 체크를 강제로있다, 널 체크를 피할 수 있도록이 아니다. 클래스 10 개 필드, 널 (null)이 될 수 중 두 개있을 때 요점은 분명해진다. 그리고 당신의 시스템은 50 개 다른 유사한 클래스를 가지고있다. 자바 세계에서, 당신은 정신 horesepower의 조합을 사용하여 해당 필드에 NPEs, 명명 규칙, 또는 어쩌면 주석을 방지하려고합니다. 그리고 모든 자바 dev에 상당한 정도이에 실패합니다. 옵션 클래스뿐만 아니라 코드를 이해하려고 모든 개발자들에게 "널 (NULL)"값을 시각적으로 명확하게,하지만 이전에 무언의 계약을 시행 할 수있는 컴파일러를 할 수 있습니다.

    그것은 널 체크를 강제로있다, 널 체크를 피할 수 있도록이 아니다. 클래스 10 개 필드, 널 (null)이 될 수 중 두 개있을 때 요점은 분명해진다. 그리고 당신의 시스템은 50 개 다른 유사한 클래스를 가지고있다. 자바 세계에서, 당신은 정신 horesepower의 조합을 사용하여 해당 필드에 NPEs, 명명 규칙, 또는 어쩌면 주석을 방지하려고합니다. 그리고 모든 자바 dev에 상당한 정도이에 실패합니다. 옵션 클래스뿐만 아니라 코드를 이해하려고 모든 개발자들에게 "널 (NULL)"값을 시각적으로 명확하게,하지만 이전에 무언의 계약을 시행 할 수있는 컴파일러를 할 수 있습니다.

  8. ==============================

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

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

  9. ==============================

    9.여기 아무도 제기 한 것 같다 한 가지 점은 null 참조를 가질 수 있지만, 옵션으로 도입 구별 있다는 것입니다.

    여기 아무도 제기 한 것 같다 한 가지 점은 null 참조를 가질 수 있지만, 옵션으로 도입 구별 있다는 것입니다.

    즉,이 옵션을 가질 수있다 [옵션 [A], 없음, 일부 (없음) 및 거주 될 수있는 일부 (일부의 (a)) 여기서 A는 A의 일반 주민 중 하나입니다 이것은 당신이있는 경우에 어떤 의미 용기의 종류, 그 안에 널 포인터를 저장하고, 그들을 밖으로 얻을 수 있도록하려면, 당신은 당신이 실제로 값을 가지고 있는지 알고 몇 가지 추가 부울 값을 다시 전달해야합니다. 이 같은 사마귀는 자바 컨테이너 API를 풍성 일부 잠금이없는 변형도를 제공 할 수 없습니다.

    널 (null)은 참조 형식에만 사용할 수 있습니다, 그 자체로 구성하지 않는, 일회성 건설이며, 그것은 당신이 아닌 총 방식으로 추론하기 위하여 강제로.

    예를 들어, 당신은 때를 확인

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

    당신은! = NULL을 X 사용 다른 지점을 통해 당신의 머리에 들고 다니기가이 이미 확인되었습니다. 그러나, 옵션 같은 것을 사용하는 경우

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

    당신은 y는 Noneby 건설 아니라는 것을 알고 - 그것은 호어의 억 달러 실수가 아니었다면 당신은이 중 null이 아니 었 알 것입니다.

  10. ==============================

    10.옵션 [의 T]를 값을 조작하는 상위 기능을 사용할 때 정말 유용한 모나드이다.

    옵션 [의 T]를 값을 조작하는 상위 기능을 사용할 때 정말 유용한 모나드이다.

    나는 그들이 옵션 [T]를 유용하고 기능적인 방법으로 어떻게 사용할 수있는 이유를 보여 정말 좋은 기사, 당신은 아래 기사를 읽어 제안합니다.

  11. ==============================

    11.값의 잠재적 부재가 옵션으로 표시되는 이유를 이해 응답의 랜달의 티저에에 추가 스칼라 - 특별히 많은 다른 종류의 모나드를 모델링 유형을 이해 무엇 옵션 주식을 필요로한다. 하나가 널 (null)에 값이 없음을 나타내는 경우, 그 부재 - 존재의 구별은 다른 모나드 유형에 의해 공유 계약에 참여할 수 없습니다.

    값의 잠재적 부재가 옵션으로 표시되는 이유를 이해 응답의 랜달의 티저에에 추가 스칼라 - 특별히 많은 다른 종류의 모나드를 모델링 유형을 이해 무엇 옵션 주식을 필요로한다. 하나가 널 (null)에 값이 없음을 나타내는 경우, 그 부재 - 존재의 구별은 다른 모나드 유형에 의해 공유 계약에 참여할 수 없습니다.

    당신이 모르는 경우 어떤 모나드, 또는 당신은 그들이 스칼라의 라이브러리로 표현하고 방법을 통지하지 않는 경우, 당신과 함께 재생 어떤 옵션이 표시되지 않습니다, 그리고 당신이 놓치고있는 당신이 볼 수 없습니다 . 대신 심지어 어떤 모나드 개념의 부재에서 주목할만한 것 널의 옵션을 사용하여 많은 혜택이 있습니다 (I는 "옵션의 비용 / 널 (null) 대 일부"여기에 스칼라 사용자 메일 링리스트 스레드를 그들 중 일부 논의), 그러나 이야기 그것에 대해 격리 종류의 것이 필요 왜 궁금 특정 링크리스트의 구현의 반복자 타입에 대해 이야기처럼, 더 일반적인 컨테이너 / 반복자 / 알고리즘 인터페이스를 놓치게 모든 동안. 이 직장에서 폭 넓은 인터페이스는 여기에 너무, 그리고 옵션은 인터페이스의 존재 앤없는 모델을 제공합니다.

  12. ==============================

    12.옵션 널위한 성가신 별칭으로 주로 유용하지 않습니다,하지만 당신의 논리와 함께 당신을 도울 수있는 본격적인 객체로 : 나는 키가 Synesso의 대답에서 찾을 수 있습니다 생각합니다.

    옵션 널위한 성가신 별칭으로 주로 유용하지 않습니다,하지만 당신의 논리와 함께 당신을 도울 수있는 본격적인 객체로 : 나는 키가 Synesso의 대답에서 찾을 수 있습니다 생각합니다.

    널 (null)의 문제는 객체의 부족 때문이다. 그것은 (언어 디자이너로 당신은 당신이 정말로 기분이 경우 객체를 에뮬레이트 언어로 기능 점점 더 긴 목록을 추가 할 수 있습니다하지만) 당신이 그것을 다루는 도움이 될 수 있습니다 어떤 방법이 없습니다.

    당신이 증명 한대로 옵션, 할 수있는 한 가지가 null을 모방하는 것입니다; 당신은 특별한 값 "없음"대신 특별한 값 "널 (null)"을 테스트해야합니다. 당신이 잊어 버린 경우, 두 경우 모두에 좋지 않은 일이 발생할 것이다. 옵션 (I가 없음을 의미하지, 어, 그것은 null이 될 수 있음을 알려해야하는) 당신이 "수"입력 할 필요가 있기 때문에, 사고가 일어날 가능성이 줄어 듭니다 않지만,이 여분의 래퍼 객체에 대한 대가로 작은 혜택입니다 .

    옵션 정말 당신이 I-구인 뭔가-하지만-I-안되 실제로 -이 - 하나의 개념을 다룰 수 있도록되어 전원을 표시하기 시작 경우.

    의 당신이 null이 될 수있는 것들로 수행 할 수 있습니다 몇 가지를 살펴 보자.

    어쩌면 당신은 당신이 널 (null)이있는 경우 기본 값을 설정합니다. 의 자바와 스칼라를 비교해 보자 :

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

    ? 다소 성가신 대신에 : 구조 우리는 "내가 널 해요 경우 기본값을 사용"의 아이디어를 다루는 방법이있다. 이 코드를 조금 정리합니다.

    어쩌면 당신은 당신이 진정한 가치가있는 경우에만 새 개체를 만들려고합니다. 비교:

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

    스칼라는 약간 짧은 다시 오류의 원인을 방지 할 수 있습니다. Synesso, 다니엘, 그리고 패러다임에 의해 예에서와 같이 함께 체인 것들을 필요로 할 때 그리고 누적 이익을 고려한다.

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

    경기의 사용은 널 (null) / 없음 사건에 대해 사용자에게 알려주는 장치로 제외하고는 그 자체로 정말 도움이되지 않습니다. 정말 도움이 때 옵션 목록이있는 경우, 예를 들어, 그것을 체인 시작할 때입니다 :

    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.")
    }
    

    지금 당신은 당신이 원하는 정확하게 값을 꺼내서 하나 명의 편리한 성명에서 모두 함께 없음 케이스와 목록 - 인 - 빈 케이스를 접어 얻을.

  13. ==============================

    13.널 리턴 값은 자바와의 호환성 만 존재한다. 당신은 그렇지 않으면 사용하지 않아야합니다.

    널 리턴 값은 자바와의 호환성 만 존재한다. 당신은 그렇지 않으면 사용하지 않아야합니다.

  14. ==============================

    14.정말 프로그래밍 스타일의 문제이다. 기능 자바를 사용하여, 또는 자신의 헬퍼 메소드를 작성하여, 당신은 당신의 옵션 기능을 가지고 있지만 자바 언어를 포기하지 못했습니다 :

    정말 프로그래밍 스타일의 문제이다. 기능 자바를 사용하여, 또는 자신의 헬퍼 메소드를 작성하여, 당신은 당신의 옵션 기능을 가지고 있지만 자바 언어를 포기하지 못했습니다 :

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

    스칼라를 포함해서 기본적으로는 특별하지 않습니다. 함수형 언어의 대부분의 측면은 해당 라이브러리에서 사용할 수 있으며 다른 자바 코드와 잘 공존 할 수 있습니다. 당신이 null로 스칼라 프로그램을 선택할 수있는 것처럼 당신은 그들없이 자바 프로그램을 선택할 수 있습니다.

  15. ==============================

    15.이 입심이 대답이라고 미리 시인, 옵션은 모나드이다.

    이 입심이 대답이라고 미리 시인, 옵션은 모나드이다.

  16. ==============================

    16.사실은 내가 당신과 함께 의심을 공유 할 수 있습니다. 옵션에 대해 정말 everywehre을 만들어 "일부"래퍼의 LOR이있는 한 1) 성능 오버 헤드가 있다는 것을 나를 귀찮게. 2) 나는 내 코드에서 일부 및 옵션을 많이 사용합니다.

    사실은 내가 당신과 함께 의심을 공유 할 수 있습니다. 옵션에 대해 정말 everywehre을 만들어 "일부"래퍼의 LOR이있는 한 1) 성능 오버 헤드가 있다는 것을 나를 귀찮게. 2) 나는 내 코드에서 일부 및 옵션을 많이 사용합니다.

    그래서 우리는 고려의 대안으로해야이 언어 디자인 결정의 장점과 단점을 볼 수 있습니다. 자바 그냥 Null 허용의 문제를 무시, 그것은 대안이 아니다. 실제 대안은 팬텀 프로그래밍 언어를 제공한다. 이 널 (NULL)이 아닌 null 허용 종류가 있습니다와?. ? : 연산자를 대신 스칼라의지도 / flatMap / getOrElse. 나는 비교에 다음 총알을 참조하십시오

    옵션의 장점 :

    null 허용의 장점 :

    그래서 여기 명백한 승자는 없다. 그리고 하나 더 참고. 옵션을 사용하여에 대한 주요 구문 장점이 없다. 당신은 뭔가를 정의 할 수 있습니다 :

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

    또는 점으로 pritty 구문을 얻기 위해 몇 가지 암시 적 변환을 사용합니다.

  17. ==============================

    17.명시 적 옵션 유형을 갖는 진짜 장점은 모든 장소의 98 %에서 사용하지 할 수있다, 따라서 정적으로 널 (null) 예외를 배제한다는 것입니다. (그리고 다른 2 %에서 타입 시스템은 실제로 액세스 할 때 제대로 확인시켜줍니다.)

    명시 적 옵션 유형을 갖는 진짜 장점은 모든 장소의 98 %에서 사용하지 할 수있다, 따라서 정적으로 널 (null) 예외를 배제한다는 것입니다. (그리고 다른 2 %에서 타입 시스템은 실제로 액세스 할 때 제대로 확인시켜줍니다.)

  18. ==============================

    18.옵션이 작동하는 또 다른 상황은 유형이 null 값을 가질 수없는 상황이다. INT, 플로트, 더블 등의 값에 null을 저장하는 것은 불가능하지만, 옵션으로 당신은 없음을 사용할 수 없습니다.

    옵션이 작동하는 또 다른 상황은 유형이 null 값을 가질 수없는 상황이다. INT, 플로트, 더블 등의 값에 null을 저장하는 것은 불가능하지만, 옵션으로 당신은 없음을 사용할 수 없습니다.

    자바에서는 이러한 종류의 박스 버전 (정수, ...)를 사용해야합니다.

  19. from https://stackoverflow.com/questions/2079170/what-is-the-point-of-the-class-optiont by cc-by-sa and MIT license