почему это компилируется? - PullRequest
       2

почему это компилируется?

1 голос
/ 08 августа 2011

Почему этот компилятор:

scala> def last[A](a : List[A] ) : A =     
 | a match {                           
 |   case head :: Nil => Some(head) get
 |   case _ :: tail => last(tail)      
 |   case Nil => None get              
 | }                   

last: [A](a: List[A])A

Хотя это явно не так:

scala> None get

java.util.NoSuchElementException: None.get
at scala.None$.get(Option.scala:262)
at .<init>(<console>:6)
at .<clinit>(<console>)
at RequestResult$.<init>(<console>:9)
at RequestResult$.<clinit>(<console>)
at RequestResult$scala_repl_result(<console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$17.apply(Interpreter.scala:988)
at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$17.apply(Interpreter.scala:988)
at scala.util.control.Exception$C...

1 Ответ

12 голосов
/ 08 августа 2011

Последний код компилируется и завершается с ошибкой только в время выполнения - то, что вы видите, является исключением, а не ошибкой компилятора.None наследуется от Option и поэтому должно определять метод get.

РЕДАКТИРОВАТЬ: вопрос можно перефразировать как «почему компилятор принимает явно глупый вызов None.get?».На этот вопрос действительно нетривиально ответить, поэтому я потрачу еще несколько слов на разных уровнях.

  • Сначала уточнение: чтобы понять разницу между ошибками во время компиляции и во время выполнения,Вероятно, полезно создать программу Scala, содержащую код, который вы хотите протестировать, скомпилировать и протестировать его.Если вы запускаете код только по приглашению, начинающему становится сложнее оценить разницу между ошибкой времени компиляции и ошибкой времени выполнения.Тем не менее, опытный пользователь научится распознавать другой формат ошибок.
  • Разве метод не похож на get глупый, так как он может дать сбой во время выполнения? Действительно, когда выиметь значение v типа Option[T], вы обычно должны использовать сопоставление с шаблоном или использовать такие методы, как getOrElse, map и т. д.: методы, которые работают, даже если v пусто.Но иногда у вас есть такое значение и вы уже уверены, что v должно быть Some(q): get следует использовать только тогда.
  • Почему, учитывая определение None, компилятор не может датьошибка времени компиляции? Компилятор выдает ошибку при вызове метода, который не определен в объекте-получателе, но get определен в классе Option и, следовательно, в его двух подклассах, Someи None.Только его тело содержит призыв к ошибке.
  • Почему имеют смысл определенные определения Option? Для того, чтобы пользователь вызывался для вызова get, когда он хочетк, это должно быть определено на Option.В противном случае перед вызовом нужно будет выполнить приведение типа - в этот момент будет проще выполнить сопоставление с шаблоном.
  • Почему компилятор до сих пор не распознает, что код выполняетсяпотерпеть неудачу во время выполнения? Потому что распознать нетривиальные случаи сложно.Например, в функции, которую вы разместили выше, неясно, будет ли когда-либо выполняться None.get;более того, код, который вы дали, выдаст ошибку во время выполнения, если вы передадите пустой список;поэтому это правильная реализация обычной спецификации последней.В общем, у вас может быть v get, и может быть нетривиально понять, может ли v быть или не быть None.Существуют и другие инструменты, которые пытаются найти ошибки такого рода (пока не уверены, есть ли они в Scala), но они также имеют тенденцию давать либо ложные отрицательные, либо ложные положительные результаты: они могут сообщать о проблемах, которые не могут возникнуть, или пропустить соответствующие проблемы.В конце концов, вы действительно не хотите, чтобы их выходные данные были вместе с выходными данными компилятора Scala.Выполнение некоторых простых простых проверок в компиляторе может иметь смысл, но у вас есть технический вопрос: неясно, стоит ли дополнительный код своей стоимости.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...