LINUX.ORG.RU

Common Lisp и UML.


0

2

Есть ли у кого-нибудь практика моделирования при помощи UML систем на Common Lisp? Интересует опыт применения конкретных инструментов, для генерации скелетных классов например.

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

> (optimize speed (debug 0) (safety 0))

Мне вседа было интересно - если функции с (safety 0) передать на вход параметр неожиданного типа, что будет?

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

Ну вообще демонстрировать это в репле не показательно. Если я в питоновском репле напишу

2+«»

он мне тоже ошибку напишет, т.к. тутже ее _исполняет_.

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

Как счастливый обладатель SLIME могу показать:

(compile nil #'(lambda () (declare (optimize (safety "0")))))

; in: LAMBDA NIL
;     (OPTIMIZE (SAFETY "0"))
; 
; caught WARNING:
;   Ignoring bad optimization value "0" in: (OPTIMIZE (SAFETY "0"))
; 
; compilation unit finished
;   caught 1 WARNING condition

И это не функция а часть declare expression которое может содержаться в некоторых специальных формах и макросах (вроде lambda и defun).

А насчёт отличий типизации в CL от статческой есть такой пост одного из разработчиков SBCL - http://www.lispforum.com/viewtopic.php?f=2&t=60&start=10#p523. С другой стороны, в динамически-типизированных языках из двух ad-hoc полиморфных метода с типами (а -> *) и (* -> b) можно сделать композицию, а в статически-типизированных языках вроде хаскеля - нельзя (там бы пришлось диспетчеризировать в рантайме вместо подстановки спецификаций во время компиляции).

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

> Инкрементальная разработка (итеративная разработка)? Какое оно вообще имеет к языку отношение?

Совершенно прямое. Для статически типизированных языков инкрементальная разработка невозможна.

Это почему? У того же хаскела репл вполне присутствует.

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

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

Чего, чего? это на стадии компиляции происходит. sbcl сразу же в репле компилируют. Тоже самое при компиляции файла.

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

Я спрашивал не о компиляции, а о выполнении

Эти safety, speed и т.п. никак не влияют на выполнение (даже по стандарту - не должны). Это что-то вроде -O опций у gcc, они влияют на выбор компилятором стратегии оптимизации, но если им передать что-то не то, то не будет вообще никакого эффекта (о чём и написано в варнинге).

Если же вопрос был про поведение функций в динамически-типизированных языках, то ты, кажется, задаёшь этот вопрос в каждом первом треде про такие языки и тут ответ простой - будут исключения в рантайме. Отличие CL тут только в том, что некоторые его реализации, вроде SBCL, позволяют пользователю отследить ошибки несовпадения типов во время компиляции если он того захочет (читай - напишет контакты). А если использовать CL как динамический язык то тут будет всё в духе философии о том что скаладывать числа со строками, делить на ноль или обращаться по индексу за границами массива - это нормально.

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

> делить на ноль или обращаться по индексу за границами массива - это нормально.

Ой, значит в CL - нормально, а в каком-нибудь хаскеле - нет? Правда?

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

Ой, значит в CL - нормально, а в каком-нибудь хаскеле - нет? Правда?

Я буду продолжать нудить, ок?) Да, в CL, в питоне или эрланге (ну и т.п.) - всё это нормально, такая философия. В хаскеле ситуация с «числа плюс строки» невозможна outside IO и возможна inside, ситуации с делением на ноль и доступом по индексу за границами массива - в хаскеле тоже норма, в том числе в pure коде (это потому что тип не может зависеть от терма и нет функций из терма в тип). Причём в хаскеле это тоже только философия - он просто останавливается если не может сделать typecheck, хотя мог бы продолжить и сделать ill-typed код (правда, код с хорошим typecheck-ом легче транслировать, можно меньше боксировать, но вообще - поиск нормального терма независим от typecheck-а).

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

Да, в рантайме идет проверка. тут несколько погорячился. Хотя и помогает. Например, clisp и этого не умеет делать. Понятно,что это плата за динамичность и другие фишки.

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

> Эти safety, speed и т.п. никак не влияют на выполнение (даже по стандарту - не должны)

Насколько я могу судить, дизассемблированный код http://www.linux.org.ru/jump-message.jsp?msgid=6554352&cid=6573530 сфейлит, если на входе будет не число.

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

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

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

Насколько я могу судить, дизассемблированный код Common Lisp и UML. (комментарий) сфейлит, если на входе будет не число.

На самом деле там будет такой код:

ADD EDX, EDI
MOV ESP, EBP
CLC
POP EBP
RET

т.е. если выбросить эпилог, получится, что функция add == мнемонике add. Так что проверяющий код находится в другом месте, причём если поставить safety = 3, он будет нормальным рестартом, а если safety = 0, то его вообще не будет (т.е. на выбор), но в самой add при speed = 3 и debug = 0, так и будет только одна мнемоника.

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

Наврал. Проверяющий код будет в самой add при safety = 3, и его не будет при safety = 0. Но не суть - за его вычетом реальную работу выполняет тольк _инструкция_ add.

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

> Проверяющий код будет в самой add при safety = 3, и его не будет при safety = 0

То есть при safety 0 программа молча сглючит?

Но не суть

Суть в том, что везде, где CL-фанбои хвастаются быстродействием, я вижу safety 0. Правильно ли я понимаю, что в таком случае ошибки, связанные с типами, не обнаруживаются?

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

Т.е. проверка будет, но по месту вызова?

Будет при safety = 3 в тот момент когда, двигаясь по control flow, кто-то поробует сделать (add 1 «2») - соответсвующий поток «остановится». При safety = 0 (add 1 «2») вернёт что-то вроде Nothing (но не упадёт).

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

То есть при safety 0 программа молча сглючит?

А что она должна сделать, учитывая что у нас там одна инструкция add? В SBCL мы получим (type-of (add 1 «2»)) == CONS - первая ячейка будет указателем на объект который описывает «примитив со странным тэгом» (там будет его lowtag и widetag; (type-of (car (add 1 «2»))) == SB-KERNEL::RANDOM-CLASS), вторая будет содержать дефолтный фикснум (ноль). Ну т.е. как в хаскеле передают Nothing вверх по цепочке вычислений, только тут ещё ассоциированное значение.

Суть в том, что везде, где CL-фанбои хвастаются быстродействием, я вижу safety 0.

Так меньше букв в ассемблере получается же.

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

В смысле в compile-time? В runtime с safety == 0 это экстрим и так обычно не пишут, уже при safety == 1 будет честный рестарт. А чтобы было в compile-time нужно добавить отдельный контракт:

(sb-c:defknown foo (fixnum fixnum) fixnum)

тогда будет так:

(compile nil #'(lambda () (add 1 "2")))
; in: LAMBDA NIL
;     (ADD 1 "2")
; 
; caught WARNING:
;   Asserted type FIXNUM conflicts with derived type
;   (VALUES (SIMPLE-ARRAY CHARACTER (1)) &OPTIONAL).
;   See also:
;     The SBCL Manual, Node "Handling of Types"
; 
; compilation unit finished
;   caught 1 WARNING condition

Честно говоря, я не знаю почему он не генерируется из декларации (или может не знаю о возможности такой деклариции).

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

>> То есть при safety 0 программа молча сглючит?

А что она должна сделать, учитывая что у нас там одна инструкция add?

Блин. Это ответ «да, она сглючит»?

Суть в том, что везде, где CL-фанбои хвастаются быстродействием, я вижу safety 0.

Так меньше букв в ассемблере получается же.

Ахренеть.

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

В смысле в compile-time?

В рантайме, блин, в рантайме.

В runtime с safety == 0 это экстрим и так обычно не пишут

Еще раз, медленно и печально: отследит ли функция, откомпилированная с safety 0, ошибку в типе переданного ей аргумента?

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

>Да, в рантайме идет проверка.

Ну так это тогда не статика, а хинты компилятору + ассерты. Полезная штука в динамических языках, но к статике отношения не имеет.

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

>Для статически типизированных языков инкрементальная разработка невозможна.

Ну если вы про ту инкрементальную разработку которая описана во всех аджайлах - так кент бекк ее пркрасно к статически типизированной джаве применяет. Так что 4.2

Главная фишка нормального репла - это возможность написать ф-ю, тут же ее оттестировать

И? В статически типизированых тоже реализуема, только не понятно зачем - потому что сначала пишутся тесты (которые нужны _все время и на будеющее_) а потом функция. Обычный TDD + удобные иснтрументы (таже ИДЕЯ + JUnit) - и репл тут сольет по удобству.

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

Еще раз, медленно и печально: отследит ли функция, откомпилированная с safety 0, ошибку в типе переданного ей аргумента?

мы получим ... объект который описывает «примитив со странным тэгом»

Чем этот ответ не устраивает? Можно прочесть так - она вернёт не число, но значение имеющее смысл.

В любом случае, процент кода в котором делают декларации (вроде iolib.stream - там gray streams на буферах в foreign memory) или defknown (как в sb-cga - там векторные операции с использованием SSE2) достаточно мал, так что весь разговор чисто гипотетический, навроде «можно ли при желании следить за типами в compie/run-time используя SBCL».

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

>Еще раз, медленно и печально: отследит ли функция, откомпилированная с safety 0, ошибку в типе переданного ей аргумента?
Еще раз, медленно и печально: выстрелит ли ружье в ногу, если снять предохранитель?

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

> Да, в CL, в питоне или эрланге (ну и т.п.) - всё это нормально

Как же это «нормально», если бросается исключение?

ситуации с делением на ноль и доступом по индексу за границами массива - в хаскеле тоже норма

А только что говорили, что не норма :)

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

> Ну если вы про ту инкрементальную разработку которая описана во всех аджайлах

Нет. Я про работу с реплом.

И? В статически типизированых тоже реализуема

Нереализуема. Чекер _не даст_ запустить эту функцию, пока вы не сделаете для нее корректный тип. А корректного типа у нее нет - потому что это черновой вариант. Так что способа запустить эту функцию у вас НЕТ.

потому что сначала пишутся тесты (которые нужны _все время и на будеющее_) а потом функция.

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

Обычный TDD + удобные иснтрументы (таже ИДЕЯ + JUnit) - и репл тут сольет по удобству.

Нет.

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

>после того, как черновой вариант примет более-менее адекватную форму

Это - ключевая ошибка в подходе. _Любые_ тесты нужно добавлять, если они проверяют что то чего раньше не проверялось.

Я про работу с реплом.

Ну тогда определение в студию. А то термин уже занят.

А корректного типа у нее нет - потому что это черновой вариант.

И это тоже не верно. Я когда в голове придумываю функцию я придумываю ее для конкретного рода данных. Так что тип есть сразу.

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

>пока вы не сделаете для нее корректный тип.

Это тоже не правда. Duck typing не противоречит статике, и вполне в ней сочетается в том же OCaml-е.

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