Вопрос

После просмотра Интервью с Рич Хикки на Протоколы В Clojure 1.2, и очень мало зная о Clojure, у меня есть несколько вопросов по протоколам Clojure:

  • Они предназначены для того, чтобы сделать то же самое, что и Структурные типы в Скале? Какие преимущества имеют протоколы над структурными типами (производительность, гибкость, ясность кода и т. Д.)? Они реализованы через размышления?
  • Вопросы о совместимости со Scala: можно ли использовать протоколы вместо структурных типов в Scala? Могут ли они быть расширены (если можно применить к «расширению» термины к протоколам) в Scala?
Это было полезно?

Решение

Совершенно не связан.

Скала - это статически напечатанный язык. Clojure - это динамически напечатанный язык. Эта разница формирует оба они в основном.

Структурные типы являются статическими типами, период. Они просто способ, чтобы компилятор доказал, что у объекта будет определенная структура (я говорю, докажу здесь, но кастинг может вызвать поддельные доказательства, как всегда).

Протоколы в Clojure - это способ создать динамическую диспетчерскую, которая намного быстрее, чем размышления или искать вещи на карте. В семантическом смысле они на самом деле не расширяют возможности Clojure, но оперативно они значительно быстрее, чем механизмы, используемые ранее.

Черты Scala немного ближе к протоколам, как и Java -интерфейсы, но опять же, есть статическая динамическая проблема. Черты Scala должны быть связаны с классом во время компиляции, аналогично интерфейсам Java. Протоколы Clojure могут быть добавлены в дат данных во время выполнения после факта даже третьей стороной.

Что -то вроде протоколов Clojure возможно в Java и Scala с помощью механизмов, таких как паттерны обертки/прокси или динамические прокси ( http://download.oracle.com/javase/1.4.2/docs/guide/reflection/proxy.html ) Но это будет чертовски неуклюжее, чем протоколы Clojure, и правильно, что идентификация объекта также сложно.

Другие советы

Целью протоколов в Clojure является эффективное решение проблемы выражения.

Видеть: Простое объяснение протоколов Clojure.]

Решение Скалы в отношении проблемы выражения является последствием. Итак, семантически, что является наиболее близким эквивалентом протоколов Clojure в Scala. (В Haskell это были бы типичные или, возможно, типовые семьи.)

Как я понял из этого Вступительный блог, Протоколы закрытия ближе к чертам Scala, а не к структурным типам (и, таким образом, не могут использоваться в качестве замены для них, отвечая на мой второй вопрос):

/* ----------------------- */
/* --- Protocol definition */
/* ----------------------- */

(defprotocol Fly
  "A simple protocol for flying"
  (fly [this] "Method to fly"))

/* --- In Scala */    
trait Fly{
    def fly: String
}

/* --------------------------- */
/* --- Protocol implementation */
/* --------------------------- */

(defrecord Bird [nom species]
  Fly
  (fly [this] (str (:nom this) " flies..."))

/* --- In Scala */    
case class Bird(nom: String, species: String) extends Fly{
    def fly = "%s flies..." format(nom)
}

/* --------------------- */
/* --- Dynamic extension */
/* --------------------- */

(defprotocol Walk
  "A simple protocol to make birds walk"
  (walk [this] "Birds want to walk too!"))

(extend-type Bird
  Walk
  (walk [this] (str (:nom this) " walks too..."))

/* --- In Scala */    
trait Walk{
    def walk = "Birds want to walk too!"
}

implicit def WalkingBird(bird: Bird) = new Walk{
    override def walk = "%s walks too..." format(bird.nom)
}

/* --------------- */
/* --- Reification */
/* --------------- */

(def pig (reify
                Fly (fly [_] "Swine flu...")
                Walk (walk [_] "Pig-man walking...")))

/* --- In Scala */    
object pig extends Fly with Walk{
    def fly = "Swine flu..."
    override def walk = "Pig-man walking..."
}

Другие ответы говорят о других частях вашего вопроса лучше, но:

Они реализованы через размышления?

Нет - протоколы скомпилируются в интерфейсы JVM. Вещи, которые реализуют протоколы (Reify, DefRecord и т. Д.) Скомпилированы в классах JVM, которые реализуют интерфейс протокола, поэтому вызовы к функциям протокола совпадают с стандартными вызовами метода JVM, под капотом.

На самом деле это был один из мотиваторов протоколов - многие внутренние структуры данных Clojure были написаны на Java по причинам скорости, потому что не было никакого способа выполнить полно скоростную полиморфную диспетчерскую в чистом виде. Протоколы предоставляют это. У Clojure все еще есть много Java в своем исходном коде, но теперь все это может быть переписано в Clojure без потери производительности.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top