LINUX.ORG.RU

Трагедия CommonLisp

 ,


0

3

https://esdiscuss.org/topic/the-tragedy-of-the-common-lisp-or-why-large-langu...

Для Ъ не будет.

Кратко суть:

Once a language gets beyond a certain complexity --- say LaTeX, Common Lisp, C++, PL/1, modern Java --- the experience of programming in it is more like carving out a subset of features for one's personal use out of what seems like an infinite sea of features, most of which we become resigned to never learning. Once a language feels infinite, the specific benefits of a new feature are still apparent. But the general costs in added complexity are no longer apparent. They are no longer felt by those discussing the new feature. Infinity + 1 === Infinity. Even aLargeNumber + 1 === approximatelyAsLargeANumber. This is the death of a thousand cuts that causes these monstrosities to grow without bound.


Ответ на: комментарий от grem

Вроде на первый взгляд должно работать. Не проверил, но похоже. Во всяком случае, на интервью, наверное, пригласили бы. На джуниора. Потому что *(temp+j) вместо temp[j] — это суксь, последний if можно выкинуть (именно if, а не следующую строчку), в предыдущем условие ns > 0 нафиг не нужно и вообще его можно объединить с предшествующим ему (хотя можно выдать это за defensive programming). А так вполне годно.

Miguel ★★★★★
()
Ответ на: комментарий от den73

Наложить ограничения на используемые фичи и стандартизировать их применение.

Это первое что требуется делать в любом серьёзном проекте. Ярчайший пример: C++. А уж в слонобегемотском CL — совершенно естественный шаг.

Сбор метаданных по мере сборки образа

Скорее CLOS и MOP. Проблема в том что никто не понимает что такое CLOS и MOP.

Это же решит проблему «хренового анализа» лисп-кода. Ну, или запиливать свой собственный комонадический фреймворк. Не так сложно, как кажется.

Лисп провоцирует писать код, который трудно статически проанализировать.

Забить и не пытаться скрестить ужа с ежом. Статический анализ, это там где есть изоморфизм Карри-Говарда («мост» между типизированным лямбда-исчислением и логикой). Как можно проводить статический анализ в языке, где нет *самого* базиса для статического анализа? Лучше уж делать так чтобы возможность «совершить мыслепреступление» была бы минимальной.

Хотите статического анализа — юзайте хаскель... Там его хоть обкушайся. Но только мацкать хаскельное дерево... Это как бы сказать... Ниже среднего удовольствие.

Но это всё не так просто и это не сделано.

Правильно. Потому что нужно работать. А кто это хочет? Тяп-ляп, так сойдет. Зачем тратить время на запил метамодели? Даже хотя бы в форме тупо забитого руками CLOS/MOP!!!

Кроме того, как я понимаю, у реализаций CL в этой области ба-а-а-льшие проблемы?

Кстати, CL никогда не обещал интроспекцию/рефлексию «сырых» S-выражений. И, поэтому, бездумное использование макросов способно вообще убить всю управляемость проекта.

Большинство проблем CL упирается в самую обычную «социалку», на самом деле.

Macil ★★★★★
()
Ответ на: комментарий от Miguel

Да, такими темпами я может даже выучу язык, но при попытке научить детей - поскорее бы :) А какой сейчас обычно максимально допустимый возраст для джуниоров? Я понимаю, что зависит от организации, что все хотят молодых и целеустремлённых, чтоб не помер через полгода.

в предыдущем условие ns > 0 нафиг не нужно и вообще его можно объединить с предшествующим ему

то есть так?

int trimRight (char *str)
// Функция должна удалять пробелы в конце строки
{
int j = 0, ns = 0;
char *temp = str;

while (temp[j] != '\0') {
    if (temp[j] == ' ')
        ++ns; // счётчик пробелов
    else
        ns = 0; // обнуление счётчика пробелов
    ++j; // переход к следующему символу в строке
    }

// Отсекание лишних пробелов в конце строки
temp[j-ns] = '\0';

return 0;
}

Да, покромсать функцию удаления лишних пробелов (trimSpace) мне действительно можно было б посильнее, помимо удаления выражений для сдвига элементов внутри массива, чтобы получить данную. Во время отладки trimSpace тогда кучу if'ов понаставил, чтобы проще было отлавливать ошибки.

grem ★★★★★
()
Ответ на: комментарий от Macil

Большинство проблем CL упирается в самую обычную «социалку», на самом деле.

Но корни, опять-таки, технологические.

Лисп (и я не только про CL) вполне годится, если пишет один человек в течение короткого периода времени. Если же нужно взаимодействовать с коллегами, или с самим собой из прошлого, то начинается та самая социалка, к которой Лисп удивительно неприспособлен.

Miguel ★★★★★
()
Ответ на: комментарий от grem

А какой сейчас обычно максимально допустимый возраст для джуниоров?

А фиг знает. Я ж не HR, да и не интересовался такими вещами.

В Reksoft к нам приходил как-то наниматься программистом один дядька, у которого в CV был пункт «владелец сети ресторанов». Я его не видел лично, но подозреваю, что ему не пятнадцать лет было.

Miguel ★★★★★
()
Ответ на: комментарий от dizza

Ничего формулы сами по себе не определяют.

определяют и только они. если вы считаете иначе, значит вы аксиоматику Пеано плохо понимаете.

И отношение длины окружности к диаметру - это не «практический смысл», это основное определение

исторически это определение считается «основным», но это ещё не означает, что оно правильное. прежде, чем дать такое такое определение пи, нужно ещё дать определение диаметру, а оно совершенно, в данном случае, ненужно, т.к. выводится из радиуса.

next_time ★★★★★
()
Ответ на: комментарий от Macil

Статический анализ - это, например, анализ какая функция вызывает какую. Анализ, символы из какого пакета используются в функциях из данного пакета. Есть ещё один вид анализа, важный именно для лиспа: анализ, можно ли собрать данный исходник «с нуля». Например, может быть так, что в данном образе исходник собирается, а в пустом не соберётся, поскольку какая-то функция переименована или просто порядок определений такой, что в этом порядке не соберётся. У меня это на сегодня две основных просадки по производительности труда.

Так что помимо типов есть ещё и другие сущности, которые тоже требуют анализа.

CLOS/MOP - это вещь, от которой я держусь подальше только потому, что CLOS просаживает производительность. Если, не дай бог, производительность просядет ниже питона, мы лишимся одной из киллер-фич. К тому же код становится неоднозначным и менее понятным при чтении. Вообще-то настраиваемая возможность по M-. попасть в определение сущности - это тоже важная фича лиспа. С методами это уже не так.

Правильно. Потому что нужно работать.

Не потому. В java вообще нет макросов. А в лиспе можно во время компиляции выполнять произвольный код. Такая возможность - это преимущество, но у неё есть и оборотная сторона. Т.е., только по ходу реального процесса сборки можно смотреть, что получается. Видимо, это ты и имел в виду под комонадическим фреймворком? Но тут мы уже упираемся в закрытость некоторых реализаций. Такое можно пилить только для свободных реализаций, потому что в несвободной можно в любую секунду огрести конкретную проблему, когда окажется, что ты нельзя повеситься на такое-то событие в системе.

Кстати, CL никогда не обещал интроспекцию/рефлексию «сырых» S-выражений.

Неважно, что он обещал. Мы живём в конкурентной среде. Ну и язык лисп - это не просто S-выражения. Есть ещё ридмакросы, в т.ч. определённые пользователем.

den73 ★★★★★
()
Последнее исправление: den73 (всего исправлений: 1)
Ответ на: комментарий от Miguel

то начинается та самая социалка, к которой Лисп удивительно неприспособлен

Угу. Роль денотационной семантики во взаимодействии больших коллективов разработчиков, не иначе.

Думаю дело совсем не в этом...

Macil ★★★★★
()
Ответ на: комментарий от Macil

Денотационная семантика — это очень на вершине. Хотя бы типизация. Да что там типизация; простой и регулярный синтаксис — это уже было бы за счастье.

Miguel ★★★★★
()
Ответ на: комментарий от den73

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

Стоп! А разве нельзя запилить аналог DBI/DBA на уровне лисп-системы? Добавляем инструментирующий код в интересные места, и работаем с чистым и незамутнённым графом вызовов.

С пакетами — сложнее. Нужно как-то квалифицировать имена символов. Как это делается в CL? После чего квалифицированное имя будет «пробиваться по базе» пакетного менеджера. Какую-то часть базы придётся пихать в образ системы.

Видимо, это ты и имел в виду под комонадическим фреймворком

Если совсем просто: монада — что-то «собирает из примитивных сущностей», комонада — её противоположность — что-то «разбирает на примитивные сущности». Самый простой пример — зиппер.

В терминах лиспа — нужен eval, который позволит пользователю вмешиваться в процесс работы, в том числе и таскать произвольное состояние. Я правильно понимаю что чисто технически это не так сложно?

потому, что CLOS просаживает производительность

Ну, если все и дальше будут продолжать «держаться в стороне», то ситуация не изменится.

Macil ★★★★★
()
Ответ на: комментарий от next_time

Да, но это последствия относительной популярности Emacs, а не каких-то объективных достоинств EmacsLisp. Серьезно, там даже lexical scoping из коробки нет, это костыльный DSL на уровне еще более популярного VimL. На этом фоне отставание более универсального CL в несколько раз выглядит еще интереснее.

nonimous
()
Ответ на: комментарий от Macil

Всё можно, но упирается в трудоёмкость и недостаточность рефлексии местами. По сути задача может свестить к реализации лиспа заново, что не есть маленький объём работы :)

Как это делается в CL?

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

Ну, если все и дальше будут продолжать «держаться в стороне», то ситуация не изменится.

Один я тут ничего не решаю, но тут всё не так просто. В java есть ключевые слова типа final, а в CLOS их нет. Также в CLOS нет статических методов. Поэтому некоторые оптимизации просто физически невозможны. Кроме того, java не подразумевает, что класс может быть в любой момент переопределён, а в лиспе всё может измениться. Это исключает ещё некоторые оптимизации. Конечно, можно и этим заниматься, и возможно всё не так плохо, как мне видится. Но я просто в большинстве случаев успешно обхожусь без CLOS. Благо есть «записи», которые работают гораздо быстрее, чем классы.

den73 ★★★★★
()
Ответ на: комментарий от Oxdeadbeef

не знаю.

Тогда о каких огромных средствах речь?

А что, есть сомнения на этот счет?

Нет сомнений, раз нет информации об огромных средствах. Чайник Рассела же.

Гугол -> ПРОФИТ!

Ага.

korvin_ ★★★★★
()
Ответ на: комментарий от Oxdeadbeef

Щито? Хацкель? Такая же история, как и с другим борщенемэйнстримом.

Ну не скажи, про хаскель даже самые нелюбопытные и «ленивые» слышали. Относительно много знакомых даже изучали. Хаскель явно популярнее, пусть и не в качестве основного инструмента, а «языка для расширения создания», но тем не менее.

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

Я про этот ваш какашкель НИГДЕ за пределами лора не слышал. То, что здесь есть полтора очень активных клоуна, которые какашкель на все лады склоняют, ничего о его популярности за пределами местного междусобойчика не говорит.

anonymous
()
Ответ на: комментарий от anonymous

Я про этот ваш какашкель НИГДЕ за пределами лора не слышал.

Pазумеется, не претендую на объективность, да и выборка не такая большая. Тем не менее, повторюсь - среди знакомых/коллег про хаскель слышало больше народу. Есть и такие, которые изучали и пробовали что-то писать.

Опять же, мне кажется, что СВЕЖИХ книг по хаскелю больше. Есть даже материалы на русском. Понятное дело, что программист должен знать английский, но переводы показывают интерес людей. Причём, переводами дело не ограничивается. По ракету, например, вообще толком книг нет, а диалект вполне живой и развивающийся.

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

P.S. Хаскель не более мой, чем лисп.

DarkEld3r ★★★★★
()
Последнее исправление: DarkEld3r (всего исправлений: 1)
Ответ на: комментарий от den73

CLOS/MOP - это вещь, от которой я держусь подальше только потому, что CLOS просаживает производительность.

Можно конкретный пример юзкейса, где в твоем приложении CLOS «просаживает производительность»? Если я не ошибаюсь, ты используешь LispWorks. Какой версии? 64 бита? Делались ли profiling мест, где есть проседания? Сравнивались ли с не CLOS реализацией? Использовались ли OPTIMIZE в DEFGENERIC и в конкретных DEFMETHOD реализациях? У меня есть довольно большая HFSM реализованная на CLOS с сотнями состояний в одно и тоже время, все операции конечно упираются в IO, но IO у меня довольно активный (~240 звонков одновременно), тормозов с CLOS не заметил. Или у тебя число-молотилка особая?

Oxdeadbeef ★★★
()
Ответ на: комментарий от Oxdeadbeef

Я словами скажу - доступ к слоту класса медленнее, чем доступ к слоту структуры через акссессор структура-поле. Проверял. Вот сейчас себя ещё раз проверил.

> (defclass class-a () ((s1 :accessor class-a-s1)))
> (defstruct struct-a s1)
> (defun measure-time (n)
               (let ((c (make-instance 'class-a))
                     (s (make-struct-a)))
                 (time (dotimes (i n) (setf (class-a-s1 c) 1)))
                 (time (dotimes (i n) (setf (struct-a-s1 s) 1)))))

> (compile 'measure-time)
> (measure-time 10000000)

Timing the evaluation of (dotimes (i n) (setf (class-a-s1 c) 1))
Elapsed time =        0.969
Allocation   = 45964 bytes

Timing the evaluation of (dotimes (i n) (setf (struct-a-s1 s) 1))

Elapsed time =        0.781
Allocation   = 1448 bytes

> (defun measure-time (n)
               (declare (optimize (speed 3) (safety 0) (debug 0)))
               (let ((c (make-instance 'class-a))
                     (s (make-struct-a)))
                 (time (dotimes (i n) (setf (class-a-s1 c) 1)))
                 (time (dotimes (i n) (setf (struct-a-s1 s) 1)))))
> (compile 'measure-time)
> (measure-time 10000000)

Timing the evaluation of (dotimes (i n) (setf (class-a-s1 c) 1))
Elapsed time =        0.375
Allocation   = 41472 bytes

Timing the evaluation of (dotimes (i n) (setf (struct-a-s1 s) 1))
Elapsed time =        0.015
Allocation   = 3068 bytes
den73 ★★★★★
()
Ответ на: комментарий от DarkEld3r

Сравнивать динамику роста в долях за последнее время для нового и для старого языка некорректно. На лиспе существует куча проектов, которые прекратили развиваться до возникновения гитхаба.

den73 ★★★★★
()
Ответ на: комментарий от den73

доступ к слоту класса медленнее, чем доступ к слоту структуры через акссессор структура-поле

Так и должно быть, за абстракцию надо платить как-то. Но мой посыл в том, что действительно ли в твоей задаче CLOS так «проседает», что прям необходимо таки пожертвовать удобством CLOS'a? Или это просто premature optimization?

У меня получились немножко другие результаты, но того же порядка: я измерял raw performance, так как при использовании TIME с SMP есть значительный overhead:

CL-USER> (defclass class-a () ((s1 :accessor class-a-s1)))
#<STANDARD-CLASS CLASS-A 200F5857>
CL-USER> (defstruct struct-a s1)
STRUCT-A
CL-USER> (defun measure-time (n)
           (let ((c (make-instance 'class-a))
                 (s (make-struct-a)))
             (time (sys:with-other-threads-disabled (dotimes (i n) (setf (class-a-s1 c) 1))))
             (time (sys:with-other-threads-disabled (dotimes (i n) (setf (struct-a-s1 s) 1))))))
MEASURE-TIME
CL-USER> (compile *)
MEASURE-TIME
NIL
NIL
CL-USER> (measure-time 10000000)
Timing the evaluation of (SYSTEM:WITH-OTHER-THREADS-DISABLED (DOTIMES (I N) (SETF (CLASS-A-S1 C) 1)))

User time    =        0.414
System time  =        0.000
Elapsed time =        0.415
Allocation   = 192 bytes
0 Page faults
Timing the evaluation of (SYSTEM:WITH-OTHER-THREADS-DISABLED (DOTIMES (I N) (SETF (STRUCT-A-S1 S) 1)))

User time    =        0.084
System time  =        0.000
Elapsed time =        0.084
Allocation   = 0 bytes
0 Page faults
NIL
CL-USER> (defun measure-time-optimized (n)
           (declare (optimize speed (safety 0) (debug 0)))
           (let ((c (make-instance 'class-a))
                 (s (make-struct-a)))
             (time (sys:with-other-threads-disabled (dotimes (i n) (setf (class-a-s1 c) 1))))
             (time (sys:with-other-threads-disabled (dotimes (i n) (setf (struct-a-s1 s) 1))))))
MEASURE-TIME-OPTIMIZED
CL-USER> (compile *)
MEASURE-TIME-OPTIMIZED
NIL
NIL
CL-USER> (measure-time-optimized 10000000)
Timing the evaluation of (SYSTEM:WITH-OTHER-THREADS-DISABLED (DOTIMES (I N) (SETF (CLASS-A-S1 C) 1)))

User time    =        0.385
System time  =        0.000
Elapsed time =        0.387
Allocation   = 0 bytes
0 Page faults
Timing the evaluation of (SYSTEM:WITH-OTHER-THREADS-DISABLED (DOTIMES (I N) (SETF (STRUCT-A-S1 S) 1)))

User time    =        0.023
System time  =        0.000
Elapsed time =        0.023
Allocation   = 0 bytes
0 Page faults
NIL
Oxdeadbeef ★★★
()
Ответ на: комментарий от den73

Я словами скажу - доступ к слоту класса медленнее, чем доступ к слоту структуры через акссессор структура-поле. Проверял.

Да тут уже давно и, возможно, не раз были такие сравнения. Результат ожидаем, ведь аксессор поля структуры является обычной функцией, а не обобщённой.

CL-USER> (symbol-function 'struct-a-s1)
#<Closure 2 subfunction of STRUCTURE::MAKE-SIMPLE-VECTOR-ACCESSOR-FUNCTION {Closed} 21A49AD2>

CL-USER> (symbol-function 'class-a-s1)
#<STANDARD-GENERIC-FUNCTION CLASS-A-S1 21A2E9FA>
CL-USER> (disassemble 'struct-a-s1)
200BE822:
       0:      BF33E80B20       move  edi, 200BE833    ; #(1 #<structure descriptor: STRUCT-A> 0)
       5:      E9CEE31C00       jmp   2028CBFA
{Closed Code} 2028CBFA:
       0:      80FD01           cmpb  ch, 1
       3:      7526             jne   L2
       5:      8B570D           move  edx, [edi+D]
       8:      8B5F09           move  ebx, [edi+9]
      11:      8B4F05           move  ecx, [edi+5]
      14:      89C6             move  esi, eax
      16:      83E603           and   esi, 3
      19:      83FE03           cmp   esi, 3
      22:      7518             jne   L3
      24:      8078FD76         cmpb  [eax-3], 76
      28:      7512             jne   L3
      30:      8B7805           move  edi, [eax+5]
      33:      3BDF             cmp   ebx, edi
      35:      7526             jne   L4
L1:   37:      8B440805         move  eax, [eax+5+ecx]
      41:      FD               std   
      42:      C3               ret   
L2:   43:      E82013E9FF       call  2011DF4A         ; #<Function RUNTIME:BAD-ARGS-OR-STACK 2011DF4A>
L3:   48:      89CF             move  edi, ecx
      50:      83EC04           sub   esp, 4
      53:      FF742404         push  [esp+4]
      57:      89442408         move  [esp+8], eax
      61:      895C2404         move  [esp+4], ebx
      65:      B503             moveb ch, 3
      67:      89F8             move  eax, edi
      69:      FF257CC22820     jmp   [2028C27C]       ; STRUCTURE::STRUCTURE-TYPE-ERROR
L4:   75:      8B7F4D           move  edi, [edi+4D]
      78:      83FF56           cmp   edi, 56
      81:      74DD             je    L3
      83:      395701           cmp   [edi+1], edx
      86:      76D8             jbe   L3
      88:      8B7C1705         move  edi, [edi+5+edx]
      92:      3BDF             cmp   ebx, edi
      94:      75D0             jne   L3
      96:      EBC3             jmp   L1
CL-USER> (disassemble 'class-a-s1)
21A2E9FA:
       0:      BF56000000       move  edi, 56          ; NIL
       5:      E966890100       jmp   21A4736A
21A4736A:
       0:      BFFBBAA521       move  edi, 21A5BAFB    ; #(#<Closure 1 subfunction of (METHOD CLOS::UPDATE-DISCRIMINATOR-CODE (STANDARD-GENERIC-FUNCTION)) {Closed} 2199BA92> #<STANDARD-GENERIC-FUNCTION CLASS-A-S1 21A2E9FA>)
       5:      E93EC216FF       jmp   20BB35B2
{Closed Code} 20BB35B2:
       0:      33DB             xor   ebx, ebx
       2:      E861BE56FF       call  2011F41A         ; #<Function RUNTIME:FIX-REST-ON-STACK 2011F41A>
       7:      55               push  ebp
       8:      89E5             move  ebp, esp
      10:      50               push  eax
      11:      50               push  eax
      12:      50               push  eax
      13:      897DF8           move  [ebp-8], edi
      16:      8B75F8           move  esi, [ebp-8]
      19:      8B7609           move  esi, [esi+9]
      22:      8975FC           move  [ebp-4], esi
      25:      89E0             move  eax, esp
      27:      0DFCFF0F00       or    eax, FFFFC
      32:      0FB73DE8671620   movzw edi, [201667E8]  ; CLOS::*GFS-ON-STACK*
      39:      3978C0           cmp   [eax-40], edi
      42:      7653             jbe   L6
      44:      8B40C4           move  eax, [eax-3C]
      47:      8B0438           move  eax, [eax+edi]
      50:      83F8F6           cmp   eax, -A
      53:      7448             je    L6
L1:   55:      83F836           cmp   eax, 36
      58:      750A             jne   L2
      60:      B8E3671620       move  eax, 201667E3    ; CLOS::*GFS-ON-STACK*
      65:      E8DA8C56FF       call  2011C2D2         ; #<Function SYSTEM::*%SYMBOL-VALUE-STAB 2011C2D2>
L2:   70:      89C3             move  ebx, eax
L3:   72:      89DE             move  esi, ebx
      74:      83E603           and   esi, 3
      77:      83FE01           cmp   esi, 1
      80:      0F84AA000000     je    L10
      86:      83FB56           cmp   ebx, 56
      89:      742C             je    L7
      91:      89D8             move  eax, ebx
      93:      B501             moveb ch, 1
      95:      FF157CEF0320     call  [2003EF7C]       ; CONDITIONS::NOT-A-LIST-ERROR
     101:      83F856           cmp   eax, 56
     104:      741D             je    L7
L4:  106:      8B75F8           move  esi, [ebp-8]
     109:      8B7E05           move  edi, [esi+5]
     112:      8B5DF4           move  ebx, [ebp-C]
     115:      E8B8C556FF       call  2011FBE2         ; #<Function RUNTIME:APPLY0-FUNCTION-REG 2011FBE2>
L5:  120:      C9               leave 
     121:      5E               pop   esi
     122:      5B               pop   ebx
     123:      03E3             add   esp, ebx
     125:      FFE6             jmp   esi
L6:  127:      8B05F4671620     move  eax, [201667F4]  ; CLOS::*GFS-ON-STACK*
     133:      EBB0             jmp   L1
L7:  135:      89E0             move  eax, esp
     137:      0DFCFF0F00       or    eax, FFFFC
     142:      0FB73DE8671620   movzw edi, [201667E8]  ; CLOS::*GFS-ON-STACK*
     149:      3978C0           cmp   [eax-40], edi
     152:      767E             jbe   L11
     154:      8B40C4           move  eax, [eax-3C]
     157:      8B0438           move  eax, [eax+edi]
     160:      83F8F6           cmp   eax, -A
     163:      7473             je    L11
L8:  165:      83F836           cmp   eax, 36
     168:      750A             jne   L9
     170:      B8E3671620       move  eax, 201667E3    ; CLOS::*GFS-ON-STACK*
     175:      E86C8C56FF       call  2011C2D2         ; #<Function SYSTEM::*%SYMBOL-VALUE-STAB 2011C2D2>
L9:  180:      FF75FC           push  [ebp-4]
     183:      E8849F56FF       call  2011D5F2         ; #<Function SYSTEM::*%INTERNAL-CONS subfunction of (COMPILER::DEF-NIL-FUNCTION CONS) 2011D5F2>
     188:      68E3671620       push  201667E3         ; CLOS::*GFS-ON-STACK*
     193:      B502             moveb ch, 2
     195:      FF15EC1B0420     call  [20041BEC]       ; SYSTEM::MULTIPROCESSING-BINDING
     201:      8B45FC           move  eax, [ebp-4]
     204:      B501             moveb ch, 1
     206:      FF155C0E1120     call  [20110E5C]       ; CLOS::UPDATE-DISCRIMINATOR-CODE-2
     212:      89E6             move  esi, esp
     214:      81CEFCFF0F00     or    esi, FFFFC
     220:      8B66A0           move  esp, [esi-60]
     223:      89E0             move  eax, esp
     225:      0DFCFF0F00       or    eax, FFFFC
     230:      8B78C4           move  edi, [eax-3C]
     233:      5B               pop   ebx
     234:      8F041F           pop   [edi+ebx]
     237:      8F40A0           pop   [eax-60]
     240:      8B7DFC           move  edi, [ebp-4]
     243:      8B5DF4           move  ebx, [ebp-C]
     246:      E835C556FF       call  2011FBE2         ; #<Function RUNTIME:APPLY0-FUNCTION-REG 2011FBE2>
     251:      E978FFFFFF       jmp   L5
L10:  256:     8B55FC           move  edx, [ebp-4]
     259:      8B7B03           move  edi, [ebx+3]
     262:      3BD7             cmp   edx, edi
     264:      7516             jne   L12
     266:      83FB56           cmp   ebx, 56
     269:      0F8474FFFFFF     je    L7
     275:      E952FFFFFF       jmp   L4
L11:  280:     8B05F4671620     move  eax, [201667F4]  ; CLOS::*GFS-ON-STACK*
     286:      EB85             jmp   L8
L12:  288:     8B5B07           move  ebx, [ebx+7]
     291:      E920FFFFFF       jmp   L3
     296:      90               nop   
     297:      90               nop   
korvin_ ★★★★★
()
Ответ на: комментарий от den73

Сравнивать динамику роста в долях за последнее время для нового и для старого языка некорректно.

Это хаскел-то новый?

На лиспе существует куча проектов, которые прекратили развиваться до возникновения гитхаба.

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

Кстати, Common Lisp вообще развивается «как язык»? То, что конкретные реализации продолжают совершенствоваться - это понятно. Просто в хаскеле и сам язык развивается.

DarkEld3r ★★★★★
()
Ответ на: комментарий от Oxdeadbeef

Поскольку я избегаю классов, то я сразу пишу код без них и обычно не имею ни возможности, ни нужды проводить сравнительное тестирование. Числодробилка у меня есть, да. Она на структурах. Скорость сносная, не более того. optimize не ставлю, потому что надёжность результата важнее быстроты. Я не считаю CLOS удобным. Например, касаемо функций - нужно листать методы, вместо того, чтобы сразу попасть в единственное тело. Листать методы неудобно.

den73 ★★★★★
()
Ответ на: комментарий от DarkEld3r

Просто в хаскеле и сам язык развивается.

2,5 новых фичи в стандарте за 12 лет - это так себе развитие. «Развивается» он за счет GHC-шных расширений.

ovk48 ★★★
()

По ссылке не ходил, но во всем согласен.

===

ахтунг! похапе!

unt1tled ★★★★
()
Ответ на: комментарий от den73

Я не считаю CLOS удобным.

Для небольших вещей, да overkill. Но если проект большой или нужно заранее продумать архитектуру приложения, которое будет разрастаться в будущем, то CLOS и ООД очень помогают в разработке и последующем сопровождении. Сужу по своему опыту :)

Oxdeadbeef ★★★
()
Ответ на: комментарий от korvin_

Результат ожидаем, ведь аксессор поля структуры является обычной функцией, а не обобщённой.

Зависит от реализации. Может быть, что все сделано через CLOS — детали реализации. Опять же CLOS может быть очень быстрым, есть даже несколько статей на эту тему — опять же детали реализации. Просто забивать на CLOS — «потомучтомедленный», ИМХО нецелесообразно.

Oxdeadbeef ★★★
()
Ответ на: комментарий от DarkEld3r

Кстати, Common Lisp вообще развивается «как язык»?

Он идеален. :) Нужно больше качественных библиотек. Рантаймы с компиляторами улучшаются и портируются на другие архитектуры. Чем не развитие?

Oxdeadbeef ★★★
()
Последнее исправление: Oxdeadbeef (всего исправлений: 2)
Ответ на: комментарий от Oxdeadbeef

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

Т.е., в структурах есть очень много из того, что хотят от классов и даже кое-что из того, что в классах нет. Архитектура может разрастаться и на структурах, хотя невозможность обновить инстансы структуры при переопределении, конечно, неприятна.

Кроме того, есть способ пропатчить не-родовую функцию. В лиспворксе есть defadvice, я в своей библиотеке сделал аналогичную переносимую фичу - decorate-function . Это снижает потребность в around - методах.

За вычетом этого преимущества именно классов CLOS становятся малозаметными.

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

den73 ★★★★★
()
Ответ на: комментарий от anonymous

Именно по этой причине нет языка лучше, чем Java1.6. Ненавижу Oracle, такую вещь испортили!

+1

java 7 уже начала быть стремноватой, а от 8 [с ее лямбдами] тянет блевать как от C#

unt1tled ★★★★
()
Ответ на: комментарий от den73

Наследование (одиночное) есть и у структур.

А мне нужно множественное наследование. Частенько миксинами пользуюсь. Вообщем меня скорость разработки и рантайма CLOS устраивает. Для простых вещей структуры идеальны.

чем листание методов

Что это? М-. в SLIME?

Oxdeadbeef ★★★
()
Ответ на: комментарий от unt1tled

java 7 уже начала быть стремноватой, а от 8 [с ее лямбдами] тянет блевать как от C#

Но многие же хотят «развития». Как же так? Получите и распишитесь.

Oxdeadbeef ★★★
()
Ответ на: комментарий от Oxdeadbeef

Зависит от реализации. Может быть, что все сделано через CLOS — детали реализации.

К сожалению, в HyperSpec нет на этот счёт никакой информации (или она где-то запрятана):

defstruct defines readers for the slots and arranges for setf to work properly on such reader functions.

reader n. 1. a function that reads[1] a variable or slot. 2. the Lisp reader.

поэтому тут мне нечего добавить. Ты встречал реализации CL, где аксессоры к структурным слотам были бы общими функциями?

korvin_ ★★★★★
()
Ответ на: комментарий от ovk48

2,5 новых фичи в стандарте за 12 лет - это так себе развитие.

Ну хоть что-то?

«Развивается» он за счет GHC-шных расширений.

Кстати, наличие, по сути, единственной реализации в этом плане плюс.

DarkEld3r ★★★★★
()
Ответ на: комментарий от Oxdeadbeef

Он идеален. :)

Да ладно? Всегда найдутся корявости, подозреваю, что даже в лиспе, при всей его гибкости, некоторые вещи лучше бы поправить «в самом языке».

Помню вот эту тему на лоре, как минимум, жалоба на отсутствие вложенных пакетов выглядит вполне логичной.

Чем не развитие?

Тем, что разные реализации делают свои расширения стандарта?

DarkEld3r ★★★★★
()
Ответ на: комментарий от korvin_

Ты встречал реализации CL, где аксессоры к структурным слотам были бы общими функциями?

В природе не встречал, хотя досконально не рассматривал кроме ccl, sbcl и lispworks.

Oxdeadbeef ★★★
()
Ответ на: комментарий от DarkEld3r

Корявости везде есть, но не настолько критичные. Вроде в sbcl вложенные пакеты добавили, но я пользуюсь LispWorks. Может кто-то подтвердит на счёт sbcl.

На счёт нестандартных расширений: большие кросплатфоменные приложения это миф. Всегда начинают с одной реализации, потом если успешно зарелизили, портируют на другую платформу/реализацию. Можно найти такие примеры и в мэйнстримных языках.

Oxdeadbeef ★★★
()
Ответ на: комментарий от Oxdeadbeef

На счёт нестандартных расширений: большие кросплатфоменные приложения это миф.

Возможно, это зависит от языка, но мой С++ опыт говорит об обратном.

Всегда начинают с одной реализации, потом если успешно зарелизили, портируют на другую платформу/реализацию.

Одно другому не мешает. Если хоть немного про это задумываться, то «портирование» будет весьма простым. В данный момент работаю над проектом, который стартовал для линукса/иос/андроид, после успешно «портировали» на эмскриптен/винду/тизен. Разный только юзер интерфейс, в ядре ифдефов минимум.

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

в ядре ифдефов минимум.

Если придерживаться кого-нибудь S.O.L.I.D, то ядро бизнес логики должно быть просто-портируемым, а зависимости от ОС можно будет запилить с минимальным усилием без большого переписывания даже с учетом нестандартных интерфейсов в используем ЯП.

Oxdeadbeef ★★★
()
Ответ на: комментарий от DarkEld3r

Возможно, это зависит от языка, но мой С++ опыт говорит об обратном.

Опять же все решается кроссплатформенными библиотеками, а не изменениями в ядре ЯП.

Oxdeadbeef ★★★
()
Ответ на: комментарий от xusrol

асоциальный задрот с гипертрофированным ЧСВ

Как завсегдатай эрланг-пьянок, лиспосходок и прочих скала-митапов, опровергаю это мнение.

Больше всего задротов, по моим наблюдениям, работает с Си и С++

lovesan ★★
()

Вообще, мнение херня. Функциональные языки, все эти Common Lisp, Erlang, Scala, и другие - они же тупо проще, удобнее и стройнее, чем мейнстрим. А еще на них программисты, которые умнее чем в среднем по больнице, попадаются гораздо чаще.

lovesan ★★
()
Ответ на: комментарий от Miguel

Ссылку на пост в пора_валить хотя бы.

Hertz ★★★★★
()
Ответ на: комментарий от lovesan

Сам факт проведения подобных мероприятий - первейший признак задротства тусовки.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.