?

Log in

No account? Create an account

Стой под стрелой

Поступки и мысли, о которых могу вспомнить не краснея

Previous Entry Поделиться Next Entry
Баттл
усы2
tonsky
Тут недавно возник такой вопрос — а чем, собственно, по существу отличаются Scala и Clojure?

У меня такие соображения:

  • static vs dynamic typing
  • компилятор найдет больше ошибок
  • но зато писать дольше — за это время можно и юнит-тест наговнякать
  • ориентированность на concurrency (иммутабельные структуры, STM) — в Clojure из коробки, в Scala через Akka
  • ленивые вычисления vs ?
  • большой, сложный язык (классы, объекты, типы, наследование, микс ФП и ООП, сидит сразу на всех стульях — Scala) vs маленький, компактный, открытый, композабельный (данные, функции, неймспейсы, только ФП — Clojure)
  • принципиальная академичность (Scala) vs прагматичность (Clojure)
  • расширяемость — макросы в Clojure, в Scala что есть, то есть
  • примат данных (Clojure) vs примат системы типов (Scala)
  • единый семантически богатый формат обмена данными (edn) vs выбери сам
  • eval и там, и там (в Scala используется редко)
  • REPL и там, и там
  • долгая промышленная разработка, большая команда vs быстрое прототипирование
  • ни то, ни то не отдать [junior] developers в энтерпрайз.
  • многоплатформенность (Clojure переносится на js, .net, python) vs только jvm
  • оба потихоньку где-то используются, но killer apps ни у кого нет
  • interop в clojure хороший, в скале вроде неплохой (но коллекции надо конвертировать)
  • про производительность Scala я слышал много хорошего by default, а в Clojure надо спускаться к java-примитивам в узких местах

Прошу высказаться, что вам кажется важным, поправить если я где ошибся, и уточнить пропуски по Scala, если знаете.

А вообще Clojure побеждает по всем фронтам.


  • 1
Аргументы такие — кто-то где-то (в библиотеке, коллега-разрабтчик, etc) может сделать имплисит, даже так, ВНЕЗАПНО сделать имплисит, который применится вообще говоря по всей программе в совершенно неожиданных местах, которые никак не найти.

Т.е. найти нельзя, защититься нельзя, управлять областью применения имплисита нельзя.

У макросов этой проблемы нет — вызов макроса всегда явный.

В смысле нельзя управлять областью применения имплисита? Еще как можно.

Давай для начала определимся с терминологией. Я полагаю, твои претензии относятся к implicit views ака implicit conversions, ибо implicit values подставляются только в параметры, которые явно отмечены как implicit. Теперь касательно views. Детали есть в SLS 7.3, я постараюсь изложить на пальцах.

Implicit search запускается в двух ситуациях: А) написано x.foo, но у типа X нет мембера foo, Б) выражение x стоит в месте, где требуется тип Y (например, при вызове метода), но X не совместим с Y.

Следствие номер 1. Если программа компилируется без имплисит вьюшек, то она будет точно так же компилироваться и с вьюшками.

Где именно ищет implicit search? Во-первых, среди идентификаторов, которые видны из точки поиска (т.е. находятся в том же пакете или явным образом заимпортированы). Во-вторых, в implicit scope исходного типа X, в который, в случае Б, объединяется с implicit scope целевого типа Y. Что такое implicit scope? Это набор имплиситов, объявленных в компаньоне типа X.

Следствие номер 2. Весьма понятно, где искать имплисит вьюшки в каждом конкретном случае. "Где-то" и "внезапно", мне кажется, тут не совсем применимы. Кроме того, видимостью вьюшек можно управлять при помощи импортов, а при желании им можно сделать unimport.

Edited at 2012-06-28 15:01 (UTC)

По-моему это не ответ на проблемы, а подгон под имеющееся состояние дел.

> Следствие номер 1. Если программа компилируется без имплисит вьюшек, то она будет точно так же компилироваться и с вьюшками.

Получается, что они как-то мешают всей этой прекрасной строгой типизации. Она должна показать ошибки при рефакторинге, а она не покажет, потому что в некоторых местах включатся имплиситы. Ведь все эти типы, они нужны не тогда, когда программа работает (см. динамическую типизацию), а тогда, когда она не работает. Разве нет?

> Следствие номер 2. Весьма понятно, где искать имплисит вьюшки в каждом конкретном случае. "Где-то" и "внезапно", мне кажется, тут не совсем применимы. Кроме того, видимостью вьюшек можно управлять при помощи импортов, а при желании им можно сделать unimport.

Вопрос не в том, где искать его определение. Вопрос в том, что ты не поймешь, в каких местах он сработал.

Ни разу не слышал, чтобы у кого-то (или у меня) в результате рефакторинга случайно включился имплисит, который предоставлял метод как раз с таким именем, которое было не нужно. Я уже не говорю, что сигнатура такого случайного метода тоже должна случайно подойти, чтобы обмануть программиста. Мне кажется, этот довод надуманный.

Касательно кто кому мешает. Вьюшки нужны для решения expression problem, причем позволяя не только ретроспективно добавлять методы, но и реализовывать интерфейсы. Само собой, для динамической типизации expression problem не существует, но такими темпами мы скатимся в срач static vs dynamic, от чего я бы хотел воздержаться.

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

Edited at 2012-06-28 15:45 (UTC)

Насчет имплиситов я тебя убедил?

Не очень. Если всё так всегда понятно, как ты говоришь, непонятно, почему просто явно их не вызывать? Если же явно неудобно, потому что они применяются не тупо-прямолинейно, а как-то умно-магически, то всё еще опасность.

Может ими просто не пользуется никто, и мы зря переживаем?

Edited at 2012-06-29 11:32 (UTC)

Да не, все просто. Вьюшки тупо превращают x в wrap(x), где wrap - имя имплисита. Просто явно вызывать получается больше букаф, иногда гораздо больше.

Тут как с extension-методами в сишарпе (хотя имплиситы могут гораздо больше). В принципе, можно написать Enumerable.Select(Enumerable.Where(foo, blah), blah) вместо foo.Where(blah).Select(blah), но это неудобно.

Почему не пользуются? Пользуются, иногда даже слишком. Но абьюзить можно что угодно, главное, чтобы можно было пользоваться с умом.

А, я кажется понял что они такое. Примерно что и Protocols в Кложе, и там та же проблема — тип в одном месте, реализация в другом, а связь в третьем и сделать ее может кто угодно. Да, проблема пока надуманная, коллизий еще не было серьезных.

  • 1