Common Lisp
От: dsorokin Россия  
Дата: 18.09.12 05:55
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Достаточно встроить интерпретатор в исполняемый код. Как делают все компиляторы динамики.


Common Lisp так не делает. Там научились компилировать честный натив, с декларациями типов — даже быстрый натив.

20.09.12 11:16: Ветка выделена из темы 1 или 2?
Автор: pzhy
Дата: 17.09.12
— VladD2
20.09.12 11:17: Перенесено модератором из 'Nemerle' — VladD2
Re: Common Lisp
От: WolfHound  
Дата: 18.09.12 08:40
Оценка:
Здравствуйте, dsorokin, Вы писали:

D>Common Lisp так не делает. Там научились компилировать честный натив,

А еще ты, наверное, веришь в вечный двигатель и Кощея бессмертного.
От того что интерпретатор размазали ровным слоем по коду он не перестал быть интерпретатором.

D>с декларациями типов — даже быстрый натив.

Кто бы сомневался, что для статически типизированного языка можно генерировать быстрый код.
... << RSDN@Home 1.2.0 alpha 5 rev. 62>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[2]: Common Lisp
От: dsorokin Россия  
Дата: 18.09.12 10:41
Оценка:
Здравствуйте, WolfHound, Вы писали:

D>>Common Lisp так не делает. Там научились компилировать честный натив,

WH>А еще ты, наверное, веришь в вечный двигатель и Кощея бессмертного.
WH>От того что интерпретатор размазали ровным слоем по коду он не перестал быть интерпретатором.

CL-USER 1 > (defun wolf-hound-hobby ()
              :nemerle)
WOLF-HOUND-HOBBY

CL-USER 2 > (disassemble 'wolf-hound-hobby)
21BE5822:
       0:      89E6             move  esi, esp
       2:      81CEFCFF0F00     or    esi, FFFFC
       8:      3966D0           cmp   [esi-30], esp
      11:      7310             jnb   L1
      13:      80FD00           cmpb  ch, 0
      16:      750B             jne   L1
      18:      55               push  ebp
      19:      89E5             move  ebp, esp
      21:      B8570D7121       move  eax, 21710D57    ; :NEMERLE
      26:      FD               std   
      27:      C9               leave 
      28:      C3               ret   
L1:   29:      E83E4A53FE       call  2011A282         ; #<Function RUNTIME:BAD-ARGS-OR-STACK 2011A282>

CL-USER 3 > (defun wolf-hound-hobby-p (hobby)
              (eql hobby :nemerle))
WOLF-HOUND-HOBBY-P

CL-USER 4 > (disassemble 'wolf-hound-hobby-p)
219C8EEA:
       0:      89E6             move  esi, esp
       2:      81CEFCFF0F00     or    esi, FFFFC
       8:      3966D0           cmp   [esi-30], esp
      11:      7317             jnb   L2
      13:      80FD01           cmpb  ch, 1
      16:      7512             jne   L2
      18:      55               push  ebp
      19:      89E5             move  ebp, esp
      21:      3D570D7121       cmp   eax, 21710D57    ; :NEMERLE
      26:      750D             jne   L3
      28:      B803400020       move  eax, 20004003    ; T
L1:   33:      FD               std   
      34:      C9               leave 
      35:      C3               ret   
L2:   36:      E86F1375FE       call  2011A282         ; #<Function RUNTIME:BAD-ARGS-OR-STACK 2011A282>
L3:   41:      B856000000       move  eax, 56
      46:      EBF1             jmp   L1
      48:      90               nop   
      49:      90               nop   
NIL
Re[2]: Common Lisp
От: dsorokin Россия  
Дата: 18.09.12 12:33
Оценка:
Здравствуйте, WolfHound, Вы писали:

D>>с декларациями типов — даже быстрый натив.

WH>Кто бы сомневался, что для статически типизированного языка можно генерировать быстрый код.

Я имел в виду опциональные декларации типов для лиспа (declare (type ...)). Ты, вообще, с коммон-лиспом-то знаком? А то складывается впечатление, что если и знаком, то поверхностно.
Re[3]: Common Lisp
От: WolfHound  
Дата: 18.09.12 13:02
Оценка:
Здравствуйте, dsorokin, Вы писали:

D>
хъ
D>

А еще меньше кода написать не мог?
Локальный вывод типов в примитивных случаях не новость.
Только это не отменяет тормозов там, где о типы вывести не может.
... << RSDN@Home 1.2.0 alpha 5 rev. 62>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[3]: Common Lisp
От: WolfHound  
Дата: 18.09.12 13:02
Оценка:
Здравствуйте, dsorokin, Вы писали:

D>Я имел в виду опциональные декларации типов для лиспа (declare (type ...)). Ты, вообще, с коммон-лиспом-то знаком? А то складывается впечатление, что если и знаком, то поверхностно.

Я просто знаю, что вечных двигателей и быстро работающих динамически типизированных языков не бывает.
В данном случае ты задаешь типы статически, и компилятор генерирует быстрый код.
Иногда компилятор может вывести типы даже там где ты их не написал.
Но в общем случае это всё работать не будет.
... << RSDN@Home 1.2.0 alpha 5 rev. 62>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[4]: Common Lisp
От: dsorokin Россия  
Дата: 18.09.12 16:26
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Я просто знаю, что вечных двигателей и быстро работающих динамически типизированных языков не бывает.

WH>В данном случае ты задаешь типы статически, и компилятор генерирует быстрый код.
WH>Иногда компилятор может вывести типы даже там где ты их не написал.
WH>Но в общем случае это всё работать не будет.

Зависит от типа приложения. Если много вычислений, то из-за боксинга (точнее говоря, "приведения к указателю") будут тормоза. Но если в основном идет интенсивный ввод-вывод, то динамический язык типа лиспа может быть не медленнее статического с навороченным компилятором. Примерно то же справедливо для десктопных приложений, где основное время — ожидание реакции пользователя, а ответ выполняется в заданных рамках, например, обновление графики. Потом, никто не отменял правила 80/20. К тому же, для лиспа существуют замечательные профайлеры. Так что, серебряной пулей, конечно, лисп не является, но для реальных задач его вполне может хватить.

А в приведенном куске кода всего четыре строки. Основное занимает вывод дизассемблера. Там две функции, скомпилированные в натив.

Возращаясь к исходному, я лишь хочу сказать, что в динамическом языке может не быть интерпретатора. В SBCL, например, все компилируется, даже то, что вводится во время сеанса REPL.
Re[5]: Common Lisp
От: Ziaw Россия  
Дата: 18.09.12 17:08
Оценка:
Здравствуйте, dsorokin, Вы писали:

D>Возращаясь к исходному, я лишь хочу сказать, что в динамическом языке может не быть интерпретатора. В SBCL, например, все компилируется, даже то, что вводится во время сеанса REPL.


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

В частных случаях интерпретатора может и не быть. Я говорю об общих, eval ты никуда не денешь ведь. Потому и компилятор для первого руби будет отличаться от остальных только границей, за которой приходится прибегать к интерпретации в рантайме.
Re[6]: Common Lisp
От: dsorokin Россия  
Дата: 19.09.12 06:20
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>В частных случаях интерпретатора может и не быть. Я говорю об общих, eval ты никуда не денешь ведь.


Так как раз eval и может работать через компилятор (см. пост про REPL). В чем проблема?
Re[7]: Common Lisp
От: Ziaw Россия  
Дата: 19.09.12 07:36
Оценка:
Здравствуйте, dsorokin, Вы писали:

D>Так как раз eval и может работать через компилятор (см. пост про REPL). В чем проблема?


Можно увидеть результат компиляции функции типа:
(defun my-eval (code)
               (eval code)
)

лисп не помню уже, но смысл должен быть понятен.
Re[8]: Common Lisp
От: hardcase Пират http://nemerle.org
Дата: 19.09.12 07:39
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Можно увидеть результат компиляции функции типа:

Z>
Z>;(defun my-eval (code)
Z>;               (eval code)
Z>;)
Z>;

Z>лисп не помню уже, но смысл должен быть понятен.

Элементарно, Ватсон. Линкуется статически библиотека с компилятором, далее компилятору скармливается code и при успехе результат исполняется
/* иЗвиНите зА неРовнЫй поЧерК */
Re[8]: Common Lisp
От: dsorokin Россия  
Дата: 19.09.12 13:35
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>Можно увидеть результат компиляции функции типа:

Z>
Z>;(defun my-eval (code)
Z>;               (eval code)
Z>;)
Z>;

Z>лисп не помню уже, но смысл должен быть понятен.

А что в этой функции особенного? Eval — это обычная функция. Вот результат (раньше был LispWorks, теперь — SBCL):

* (defun my-eval (code) (eval code))

MY-EVAL
* (disassemble 'my-eval)

; disassembly for MY-EVAL
; 245C8C0F:       850500000021     TEST EAX, [#x21000000]     ; no-arg-parsing entry point
;       15:       8BD6             MOV EDX, ESI
;       17:       8B05D88B5C24     MOV EAX, [#x245C8BD8]      ; #<FDEFINITION object for EVAL>
;       1D:       B904000000       MOV ECX, 4
;       22:       FF7504           PUSH DWORD PTR [EBP+4]
;       25:       FF6005           JMP DWORD PTR [EAX+5]
;       28:       CC0A             BREAK 10                   ; error trap
;       2A:       02               BYTE #X02
;       2B:       18               BYTE #X18                  ; INVALID-ARG-COUNT-ERROR
;       2C:       4F               BYTE #X4F                  ; ECX
NIL


Честно говоря, не очень понимаю непонимания Если забить на формы верхнего уровня (top level forms), такие как defvar, defparameter, defun и т.п., то функцию eval можно реализовать через компилятор напрямую, т.е. без интерпретации:

(defun my-eval-2 (code)
  (funcall 
    (compile nil `(lambda () ,code))))


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

Теперь проверка:

* (my-eval-2 '(+ 1 2 3))

6
Re[9]: Common Lisp
От: dsorokin Россия  
Дата: 19.09.12 13:40
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Элементарно, Ватсон. Линкуется статически библиотека с компилятором, далее компилятору скармливается code и при успехе результат исполняется


Близко к этому. Только мы работаем с образом (почти как в Smalltalk), а потому компилятор никуда не девается, а просто остается в образе. Но всякие умные коммерческие реализации типа LispWorks и Allegro CL умеют изгонять компилятор из образа как и все ненужное по желанию, значительно уменьшая образ в размере. Зовется это tree shaker.
Re[9]: Common Lisp
От: Ziaw Россия  
Дата: 20.09.12 03:06
Оценка:
Здравствуйте, dsorokin, Вы писали:

D>Честно говоря, не очень понимаю непонимания Если забить на формы верхнего уровня (top level forms), такие как defvar, defparameter, defun и т.п., то функцию eval можно реализовать через компилятор напрямую, т.е. без интерпретации:


То есть ты хочешь показать, что встраивание интерпретатора в исполняемый файл можно заменить на встраивание компилятора. Ок, принято.
Re[10]: Common Lisp
От: dsorokin Россия  
Дата: 20.09.12 05:51
Оценка:
Здравствуйте, Ziaw, Вы писали:

Z>То есть ты хочешь показать, что встраивание интерпретатора в исполняемый файл можно заменить на встраивание компилятора. Ок, принято.


Ну, в общем, да. SBCL примерно так и делает. Могу наврать, но по-моему у него, вообще, нет интерпретатора. Однако, многие другие лиспы сочетают оба подхода. Они содержат одновременно и компилятор, и интерпретатор для eval и load. Видимо, есть какие-то резоны. Тем не менее, SBCL считается самым быстрым из всех лиспов, несмотря на то, что он открыт и бесплатен для использования.

Думаю, на этом можно офтопик по лиспу считать законченным по достижении согласия сторон
Re: Common Lisp
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.09.12 07:13
Оценка:
Здравствуйте, dsorokin, Вы писали:

Z>>Достаточно встроить интерпретатор в исполняемый код. Как делают все компиляторы динамики.


D>Common Lisp так не делает. Там навчились компилировать честный натив, с декларациями типов — даже быстрый натив.


Завязывал бы ты с пропагандой лиспа в этом форуме. Здесь многие с ним знакомы. И раз это форум соуществет, значит здешним посетителям лисп не интересен.

Сказки про быстрый нативный код тоже рассказывать не надо. Язык не имеющий целых с фиксированной длинной генерировать быстрый код не может в принципе. Любимый тобой SBCL 10 лет не может из состояния альфа-версии выйти. При этом он на пол века отстал от полноценных типизированных языков, так как вывода типов там нет, а указывать типы всегда и везде — это та еще гадость. Даже в С++ такой фигней не страдают. Ну, а без типов — это будет все тот же тормозной интерпретатор, не смотря на перекомпиляцию и прочую бесполезную ерунду, так как со значениями типы которых известны только в рантайме работать можно тоже только в рантайме.

В общем, хочешь обсудить лисп? У тебя есть сразу два варианта на выбор: 1. Создать тему в Декларативном программировании. 2. Создать тему в философии. Второе будет предпочтительнее, так как разговор пойдет о пенесометри, а не о практических вопросах.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Common Lisp
От: dsorokin Россия  
Дата: 20.09.12 07:26
Оценка: 1 (1)
Здравствуйте, VladD2, Вы писали:

VD>Сказки про быстрый нативный код тоже рассказывать не надо. Язык не имеющий целых с фиксированной длинной генерировать быстрый код не может в принципе. Любимый тобой SBCL 10 лет не может из состояния альфа-версии выйти. При этом он на пол века отстал от полноценных типизированных языков, так как вывода типов там нет, а указывать типы всегда и везде — это та еще гадость. Даже в С++ такой фигней не страдают. Ну, а без типов — это будет все тот же тормозной интерпретатор, не смотря на перекомпиляцию и прочую бесполезную ерунду, так как со значениями типы которых известны только в рантайме работать можно тоже только в рантайме.


VD>В общем, хочешь обсудить лисп? У тебя есть сразу два варианта на выбор: 1. Создать тему в Декларативном программировании. 2. Создать тему в философии. Второе будет предпочтительнее, так как разговор пойдет о пенесометри, а не о практических вопросах.


Нет, не хочу даже обсуждать, но я думаю, что ты не прав, сильно не прав по ряду пунктов. Добавлю, что о лиспе многие имеют весьма посредственное представление, что этот топик и демонстрирует, но да бог с этим. Мне все равно. На этом предлагаю закончить тему. Можно даже закрыть.

з.ы. Для целых есть тип fixnum. Кстати, он сделан намеренно таким, чтобы его значения влезали в размер "указателя". Для скорости в том числе.
Re[3]: Common Lisp
От: VladD2 Российская Империя www.nemerle.org
Дата: 20.09.12 16:40
Оценка:
Здравствуйте, dsorokin, Вы писали:

D>з.ы. Для целых есть тип fixnum. Кстати, он сделан намеренно таким, чтобы его значения влезали в размер "указателя". Для скорости в том числе.


А зачем людям типы зависяцие от реализации компилятора/итерпретатора? Вот что про него пишут здесь:

The DECLARE form in INT-ADD1 includes two kinds of advice. (FIXNUM N) declares that the function parameter N is a small integer. (The range depends upon your Lisp implementation, but you'll typically get 29-bit fixnums on a 32-bit processor; the remaining three bits are often used by the Lisp system to encode type information.)


Ну, и потом где double, float?

Но это все мелочи. Главная проблема в том, что лисп с натыканными типами сразу перестает быть лиспом. Он превращается в уродливый и не повортливый язык.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Common Lisp
От: dsorokin Россия  
Дата: 21.09.12 04:36
Оценка: 1 (1) :)
Не думал, продолжать, но на пару моментов отвечу.

Здравствуйте, VladD2, Вы писали:

VD>А зачем людям типы зависяцие от реализации компилятора/итерпретатора? Вот что про него пишут здесь:

VD>

VD>The DECLARE form in INT-ADD1 includes two kinds of advice. (FIXNUM N) declares that the function parameter N is a small integer. (The range depends upon your Lisp implementation, but you'll typically get 29-bit fixnums on a 32-bit processor; the remaining three bits are often used by the Lisp system to encode type information.)


И что здесь плохого написано? Выше я уже отметил, что тип fixnum намеренно выбран таким, чтобы его значения могли использоваться как "указатели". Поэтому первые биты являются тегом (не помню, но там, кажется, нули для fixnum). Это значит, что когда мы пишем (+ 1 2 3) при вычислении не происходит выделения памяти: ячейки cons не создаются. А это больше всего влияет на производительность.

VD>Ну, и потом где double, float?


Есть типы single-float и double-float. Есть и другие. Причем, на некоторых 64-битных лиспах значение single-float укладывается в указатель, т.е. такими значениями можно оперировать без выделения памяти. Но как я выше писал, вычисления не являются сильной стороной коммон-лиспа. Когда мы вычисляем что-то внутри функции, то можно обложиться типами, и все будет быстро. Но если нам нужно вернуть, скажем, double-float из функции, то тогда такое значение должно быть преобразовано к указателю, и произойдет так называемый boxing. Есть средства борьбы с этим, но они работают не всегда. В общем, интенсивные вычисления — не самая сильная сторона, как я уже признал ранее.

VD>Но это все мелочи. Главная проблема в том, что лисп с натыканными типами сразу перестает быть лиспом. Он превращается в уродливый и не повортливый язык.


Есть правило 80/20. Часто работает. Буквально это значит, что декларации могут понадобиться для 20% кода или меньше, если таковая необходимость, вообще, возникнет.

Еще раз остановлюсь на важном моменте. Во многих приложениях основное время уходит на ожидание ввода-вывода. Сюда можно отнести огромное количество десктопных приложений, серверных приложений. Здесь везде лисп может быть уместен, и разница в скорости по сравнению со статически типизированными языками будет незаметна. Как минимум, лисп не медленнее питона, а питон применяется очень часто, хотя, может быть, это не так видно для закоренелых пользователей windows.

VD> Любимый тобой SBCL 10 лет не может из состояния альфа-версии выйти. При этом он на пол века отстал от полноценных типизированных языков, так как вывода типов там нет, а указывать типы всегда и везде — это та еще гадость.


Во-первых, мне больше нравится LispWorks. Во-вторых, в SBCL локальный вывод типов таки есть, но он ограничен особенностями языка. Уж что-что, но SBCL называть тормозным и древним у меня язык не повернется. Потом, не понимаю, о какой альфа-версии ты говоришь. Может быть, имеешь в виду порт для windows? Так его никто и не обещал. SBCL разрабатывается в первую очередь для Linux/Unix, включая OS X. Для windows есть Clozure CL, LispWorks, Allegro CL. Можно посмотреть и на крошку CLisp, завязанный на яву ABCL и, возможно, на новенький MKCL. Т.е. выбор есть.

VD> Ну, а без типов — это будет все тот же тормозной интерпретатор, не смотря на перекомпиляцию и прочую бесполезную ерунду, так как со значениями типы которых известны только в рантайме работать можно тоже только в рантайме.


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

Наконец, вспомним, как Аристотель опровергал Зенона. Вот, есть замечательное кросс-платформенное приложение InspireData. На 99,99% написано на Common Lisp, используя LispWorks.


З.Ы. Боюсь, у меня не будет много времени дискутировать. Не вижу большого смысла.
Re[5]: Common Lisp
От: Cyberax Марс  
Дата: 21.09.12 04:52
Оценка:
Здравствуйте, dsorokin, Вы писали:

D>Ну, опять типы, типы, ... Не понимаю этого пристрастия. Словно восточная религия какая-то. Нет, конечно, есть сильные стороны, например, язык с типами удобен для коллективной разработки с большим количеством быдлокодеров, но мне кажется, что типы переоценивают.

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

D>Наконец, вспомним, как Аристотель опровергал Зенона. Вот, есть замечательное кросс-платформенное приложение InspireData. На 99,99% написано на Common Lisp, используя LispWorks.

И? Одно приложение? Как весело...
Sapienti sat!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.