видно, что structure-class не является standard-class.
Ну да, и что? В стандарте явно сказано, что каждому типу соответствует класс, а значит можно получить слоты, конструктор структурного класса и собрать новый объект на основе существующего без необходимости определять новый метод для каждого структурного типа.
Не хватает пруфов. Кроме того, только второй пункт можно признать хоть на что-то годным. Остальное можно писать на чем угодно и никакие преимущества/недостатки лиспа не повлияют.
Haskell неоправданно переусложнен. К тому же там нет объекто-ориентированной парадигмы, и как следствие невозможность отделение интерфейса от реализации.
каждому типу соответствует класс, а значит можно получить слоты
А на http://www.alu.org/mop/dictionary.html написано, что список слотов для класса, не являющегося standard-class должен быть пустым (а для forward-referenced-class обязан возвращать ошибку).
Причем в определении class-slots: This method returns the value associated with the class metaobject by finalize-inheritance (standard-class) or finalize-inheritance (funcallable-standard-class).
Можешь попробовать сделать finalize-inheritance на структуру... хотя хз, может в SBCL и это переопределили.
Я тебе скажу в чем у меня была проблема с хацкелем. Он выдает сообщение об ошибке в том месте, где он ее встретил. Хотя на самом деле ошибка локализована за 1350 строк в другом месте. Я потратил 4 дня на эту хрень, пока местный гуру по хацкелю не объяснил мне эту особенность компилятора. Ну и нахрен такой язык нужен, когда у тебя 4 миллиона строк в проекте? Той же хренью страдает boost. Сообщение об ошибке - 8 экранов.
А вот Lisp всегда выдает весьма осмысленную диагностику, хоть при компиляции, и даже при при исполнении кода ошибку выкидывает в дебаггер, и дает возможность понять проблему в текущем контексте, без разкрутки стека, который может сложиться раз в 10 лет.
ФП, как я его понимаю, это значит, что функция, при совпадающем множестве значений параметров, вернет один и тот же результат, не зависящий от контекста исполнения.
Строго говоря, функция детерминирована и не влияет на enviroment (нет побочных эффектов).
Хаскель в файлы и на консоль пишет весьма извращенным образом, посредством морганатического выкидыша (монады), созданного бесовской силой, соединившей прелесть и чистоту непорочной девы Лямбды и вонючего верблюда Боба (весь остальной мир).
вернет один и тот же результат, не зависящий от контекста исполнения.
Но вы хотите не только вернуть какой-то результат, но и изменить сам контекст исполнения. У вашей функции есть т.о. побочный эффект (она делает что-то еще, кроме возврата результата). Это уже не ФП.
ФП, как я его понимаю, это значит, что функция, при совпадающем множестве значений параметров, вернет один и тот же результат, не зависящий от контекста исполнения.
Такие функции на лиспе писать легко. Просто не используй деструктивные функции. Технически даже можно написать статический анализатор, проверяющий это.
А можно пример неосмысленной диагностики? Потому как пока удобней всего SBCL. Есть полный стектрейс, текущие значения переменных, возможность выполнить любую команду в этом месте.
ФП, как я его понимаю, это значит, что функция, при совпадающем множестве значений параметров, вернет один и тот же результат, не зависящий от контекста исполнения.
А как теперь, например, время узнать без морганатических выкидышей?
Я тебе скажу в чем у меня была проблема с хацкелем. Он выдает сообщение об ошибке в том месте, где он ее встретил. Хотя на самом деле ошибка локализована за 1350 строк в другом месте. Я потратил 4 дня на эту хрень, пока местный гуру по хацкелю не объяснил мне эту особенность компилятора. Ну и нахрен такой язык нужен, когда у тебя 4 миллиона строк в проекте? Той же хренью страдает boost. Сообщение об ошибке - 8 экранов.
Подозреваю, что в схожей ситуации лисп не выдаст никакой ошибки вообще. Будешь отлавливать в рантайме.
Нужно лишь немного времени, чтобы привыкнуть к сообщениям об ошибках хаскеля. На самом деле, он довольно точно говорит, в чем проблема
А никак. Та же самая монада - жалкая попытка решать реальные задачи средствами чистых функциональных языков. Это как принцип детерминизма в классической механике, «дайте мне начальные импульсы и координаты всех частиц, и я опишу будущее МИРА». Ага, хрен ты там чего опишешь, понты дешевые только, как и с хаскелем.
И очень хорошо, просто чудесно. Весь контекст возникновения ошибки мне доступен. Ты попробуй в C++ отладить такие вещи, когда надо долго думать, что надо сделать, чтобы воспроизвести эту ошибку.
А никак. Та же самая монада - жалкая попытка решать реальные задачи средствами чистых функциональных языков. Это как принцип детерминизма в классической механике, «дайте мне начальные импульсы и координаты всех частиц, и я опишу будущее МИРА». Ага, хрен ты там чего опишешь, понты дешевые только, как и с хаскелем.
Тем не менее, концепция монад оказалась очень полезной при реализации практичного F# async workflow. Писать ввод-вывод через async в silverlight было сплошным удовольствием, тогда как шарписты очень мучались.
Тогда уж сразу continuation/CPS вспоминать надо, который был раньше монад и решал ту же задачу не хуже (а в варианте поддержки continuation в рантайме даже лучше).
Объективно, надо сравнивать с python, ruby, scala...
В целом скорость разработки примерно одинаковая.
Ну вот и я о чем :) Lisp выруливает на достаточно специфических задачах или огромных масштабах проекта, по сравнению с другими высокоуровневыми языками. Хотя, языки, ориентированные на конкретную платформу (java, net) все равно останутся в преимущества, если весовая доля обратной совместимости, батареек, возможности прототип на той же clojure отдать на доработку в аутсорсовую софтовую компанию индусов итд. Т.е. языки с платформой потенциально лучше подходят для т.н. интерпрайза. А разработка на CL с вероятностью 99% на нем же и останется на весь свой жизненный цикл, если его не решат «отдать на аутсорс в...». Это и хорошо, и плохо.
Ты попробуй в C++ отладить такие вещи, когда надо долго думать, что надо сделать, чтобы воспроизвести эту ошибку.
стоит заметить, что этот вид ошибок в компилируемом языке со статической типизацией не возникнет.
Да ну? У тебя для функции f(x) := 1 / x статическая типизация сделает тип «всё, кроме нуля»?. И при работе с FFI сможет статически дать гарантию, что внешняя функция не испортит память?
Для float x эта функция просто вернёт +inf или -inf.
Подход а-ля JS, конечно, имеет право на жизнь. Но это ещё хуже. Если при вызове исключения есть контекст, в котором произошло деление на 0, то при таком подходе ошибка будет заметна только когда половина зависимых переменных получат в качестве значений Inf и NaN.
Ещё нормальная система проверок позволяет ограничивать область значений. Например для вероятности осмысленными являются значения только в промежутке 0..1. Но может быть получено невозможное значение при некорректных экспериментальных данных (количество событий различных видов). И как мне может помочь статическа типизация?
Зависит от. Компилятор должен потребовать проверку от тебя(примерно как kotlin для null). Тут нужны или зависимые типы(agda, но я не возьмусь это выразить на ней) или проверяемые во время компиляции контракты(пока видел только в виде тулзовен для шарпа и явы).
Компилятор должен потребовать проверку от тебя(примерно как kotlin для null)
И опять же. Пусть он заставляет написать ветку if(total>x) ...
Но что в этой ветке делать? Никакого разумного значения вероятности дать нельзя. Надо бросать исключение или использовать какой-то другой механизм, позволяющий или запустить отладчик или сообщить пользователю, что «при чтении файла ... в строке ... встретились неверные данные: ...».
Вот пример из Хаскеля:
import System.IO
main = do
z <- readLn
print (z+1)
запускаю.
monk@veles:~/languages/haskell$ ./Err
fail
Err: user error (Prelude.readIO: no parse)
ну и какая мне польза от статической типизации, если ошибка ввода рушит программу и компилятор никак не предупреждает, что эта ситуация необработана (в Java хоть throw заставляют описать)?
Ещё нормальная система проверок позволяет ограничивать область значений. Например для вероятности осмысленными являются значения только в промежутке 0..1. Но может быть получено невозможное значение при некорректных экспериментальных данных (количество событий различных видов). И как мне может помочь статическа типизация?
Диапазон можно было задавать еще в Ada-83. Хотя, конечно, статическая типизация весьма ограничена. Ничего, приспосабливаются люди :)
Некоторым на лиспе просто интереснее программировать. Этот фактор тоже надо учитывать. Программирование - далеко не рационально, как и очень многое из того, чем занимается человек. Человек, вообще, существо очень иррациональное по своей природе, даже флегматики ;)
Но при этом просто возникала ошибка времени выполнения на входе в функцию. А по-другому сделать нельзя, иначе рушиться вся арифметика. x : 0..100, y: 1..100, c = x/y : 0..1.0 должно скопилироваться?