LINUX.ORG.RU

Racket VS Common Lisp

 , , , ,


8

10

Добрый день дорогие аналитики L0R'a. Ковыряю ракет, пишу на нем клиентскую программу - а пока хочется вот что спросить. Все же что лучше - Racket или Common Lisp? Что более перспективно? Ну и естественно, какие у одного недостатки/преимущества по сравнению с другим?

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

А что ещё у функции кроме имени есть?

Не знаю, что там у нее есть еще, но вот имени у большинства ф-й нет.

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

ты код целиком дай.

(define-serializable-class test-s% object% 
    (init size)
    (super-new))

(define ss (serialize (new test-s% (size 10))))

ss сохраняю в файл

Затем меняю опеределение test-s% на

(define-serializable-class test-s% object% 
    (init size amount)
    (define size0 size)
    (define amount0 amount)
    (super-new))

и вызываю deserialize из сохранённой строки. Ошибку ты видел.

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

но вот имени у большинства ф-й нет.

Опять разница традиций. В CL принято хранить данные в объектах и структурах, а безымянные функции встречаются только в параметрах map, reduce и т.д.

Функцию в SBCL можно сериализовать

* (defvar *a* (lambda (a b) (+ a b)))

*A*
* (describe *a*)

#<FUNCTION (LAMBDA (A B)) {BC1B04D}>
  [compiled function]

Lambda-list: (A B)
Derived type: (FUNCTION (T T) (VALUES NUMBER &OPTIONAL))
Source form:
  (LAMBDA (A B) (+ A B))
*

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

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

Что характеризует нужность трейсеров и неадекватного общелиспового дебагера.

Вот человек просит нормальный дебаггер. http://lists.racket-lang.org/users/archive/2012-April/051727.html и http://lists.racket-lang.org/users/archive/2012-April/051726.html .

Что характерно: просит в апреле 2012 и уже год не может дождаться ответа. Может на самом деле «сделать не можем, а значит скажем, что не нужно»?.

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

и вызываю deserialize из сохранённой строки. Ошибку ты видел.

А, ясно. И какую ошибку по-твоему должно было вывести?

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

Опять разница традиций. В CL принято хранить данные в объектах и структурах, а безымянные функции встречаются только в параметрах map, reduce и т.д.

Ну все методы классов - это замыкания. У них нету имен.

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

Именно так. Для их сериализации нужно делать преобразования над кодом, например, как это делается в #lang web-server, там уже лямбды сериализуются.

Функцию в SBCL можно сериализовать

Не функцию, а имя функции. Не надо путать. Я потом возьму и *a* переопределю - и пиздец твой десериализации. То есть ф-я якобы десериализуется, вот только не в ту что нужно.

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

Что характерно: просит в апреле 2012 и уже год не может дождаться ответа. Может на самом деле «сделать не можем, а значит скажем, что не нужно»?.

Какие-то слишком сильные выводы, из-за того весь PLT team не кинулся выполнять реквест одного единственного человека. Если кому-то нужен такой дебаггер - ну так никто не мешает сделать самому, тогда тебе и на маиллисте помогут, пояснят как решить эту задачу.

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

И какую ошибку по-твоему должно было вывести?

«не совпадает количество полей», например. «Ошибка в описании объекта test-s%» (это что cl-store по-идее выдает, не проверял). Но не непонятный car внутри deserialize'а. Причём никакой подсветки места ошибки или стектрейса нет.

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

в случае рестартов - продолжение это частный случай рестарта

а не наоборот?

Они разные. В общелиспе не раскручивается стек при обработке специального условия в handler-bind до вызова рестарта. Технически, видимо, просто создается временный вложенный стек. Как понимаю, это влияет на обработку unwind-protect.

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

Я потом возьму и *a* переопределю - и пиздец твой десериализации.

Там исходный код виден. Его и сериализуем. Имя у данной функции "(LAMBDA (A B))" его сериализовать бесполезно.

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

Какие-то слишком сильные выводы, из-за того весь PLT team не кинулся выполнять реквест одного единственного человека.

Из-за того, что реквест пригнорирован. Если бы ответили типа «это не надо» или «будет в таком-то релизе», то вопросов бы не было.

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

Как понимаю, это влияет на обработку unwind-protect.

Кстати да. Handler-bind на продолжениях не получается. В CL насколько я понимаю, обработка handler-bind происходит внутри вызова исключения. Соответственно, в Racket надо или переписывать raise (а он вроде как примитив) или не иметь рестарта continue...

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

Ну все методы классов - это замыкания. У них нету имен.

Вообще-то, то что ты отправляешь через send — именно имя метода. Или как ты безымянные методы различаешь? defgeneric в CL/SWINDLE тоже функцию к имени привязывает.

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

Кстати да. Handler-bind на продолжениях не получается. В CL насколько я понимаю, обработка handler-bind происходит внутри вызова исключения. Соответственно, в Racket надо или переписывать raise (а он вроде как примитив) или не иметь рестарта continue...

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

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

Вообще-то, то что ты отправляешь через send — именно имя метода.

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

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

Там исходный код виден. Его и сериализуем.

Ну так а если это замыкание, что ты потом с этим исходным кодом будешь делать?

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

барьеры — немножко не про то.

Есть ли возможность сделать

-> (define (test l)
    (if (null? l) null
      (cons (/ 1 (car l)) (test (cdr l)))))

-> (define (safe-test l)
    (with-handlers .... ; вот тут не знаю что
      (test l)))
      
-> (safe-test '(1 2 3 0 5))

(1 1/2 1/3 0 1/5)

?

В общем, можно ли написать на Racket такую функцию, чтобы внутри неё (в её динамическом окружении) делений на 0 возвращало 0, а не прерывало вычисления?

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

если это замыкание

Я выше написал, что для простых функций подходит, а для замыканий и продолжений — нет.

Имя метода - это просто некий ключ, по которому ищется безымянная лямбда.

Так и имя функции тоже «просто некий ключ», особенно в схеме, где функция определяется как присваивание лямбды переменной. Для метода этот ключ будет состоять из имени класса и имени метода. Другое дело, что изнутри функции схема скорее всего не даст её имя. В SBCL внутри функции хранится её имя.

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

В общем, можно ли написать на Racket такую функцию, чтобы внутри неё (в её динамическом окружении) делений на 0 возвращало 0, а не прерывало вычисления?

Перехватываем исключение и возвращаем 0. Для этого with-handlersи есть. А в чем проблема-то?

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

Я выше написал, что для простых функций подходит, а для замыканий и продолжений — нет.

То есть функции не сериализуются, о чем я и сказал.

Другое дело, что изнутри функции схема скорее всего не даст её имя. В SBCL внутри функции хранится её имя.

почему же не даст? Даст. Более того - даже у лямбд бывает inferred name.

Так и имя функции тоже «просто некий ключ»

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

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

А в чем проблема-то?

Напиши такую функцию

Если я пишу

(define (safe-test l)
  (with-handlers (((lambda (v) #t) (lambda (v) 0)))
    (test l)))

то (safe-test '(1 2 3 0 5)) возвращает просто 0.

Как сделать правильно? В документации такого примера нет, а на форумах вообще пишут, что Racket так не умеет

monk ★★★★★
()
Ответ на: комментарий от anonymous
(defun test (l)
           (when l
             (cons (restart-case 
                      (/ 1 (car l)) 
                   (use-value (value) "" value)) 
             (test (cdr l)))))

(defun safe-test (l)
   (handler-bind ((arithmetic-error (lambda (c) 
                    (declare (ignore c)) (use-value 0))))
       (test l)))

(safe-test '(1 2 3 0 5)) => (1 1/2 1/3 0 1/5)
monk ★★★★★
()

Добрый день дорогие аналитики L0R'a. Хочется вот что спросить. Все же что лучше - сайентология или Церковь Св. Муна? Что более перспективно? Ну и естественно, какие у одного недостатки/преимущества по сравнению с другим?

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

Видимо, как-то так:

#lang racket

(define-syntax-rule (with-throw-continuation body ...)
  (let/cc k (with-handlers ([exn? (λ _ (raise k))]) body ...)))

(define (test l) 
  (if (null? l)
      '()
      (cons (with-handlers ([(λ _ #t) (λ (k) (k 0))])
              (with-throw-continuation (/ 1 (car l))))
            (test (cdr l)))))

идея следующая - with-throw-continuation перехватывает исключение из тела и выбрасывает в качестве исключения соответствующее продолжение, нам остается лишь взять это продолжение в with-handler и применить к нужному аргументу.

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

точнее так, если совсем как в примере:

#lang racket

(define-syntax-rule (with-throw-continuation body ...)
  (let/cc k (with-handlers ([exn? (λ _ (raise k))]) body ...)))

(define (test l) 
  (if (null? l)
      '()
      (cons (with-throw-continuation (/ 1 (car l)))
            (test (cdr l)))))

(define (safe-test l)
  (with-handlers ([(λ _ #t) (λ (k) (k 0))])
              (test l)))
ну да разница несущественна.

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

Если совсем как в пример, то так (там проверка на тип ошибки):

(define (test l) 
  (if (null? l)
      '()
      (cons (let/cc k (with-handlers 
                          ([exn? (λ (v) (raise (cons v k)))]) 
                        (/ 1 (car l))))
            (test (cdr l)))))



(define (safe-test l)
  (with-handlers ([(λ (v) (exn:fail:contract:divide-by-zero? (car v))) 
                   (λ (v) ((cdr v) 0))])
              (test l)))

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

Из нерешаемого (возможно): есть ли возможность установить инспектора для модуля не влезая в его исходники?

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

Если совсем как в пример, то так (там проверка на тип ошибки):

Ну да. По-хорошему надо сделать структуру-враппер, которая будет содержать проброщенное исключение вместе с продолжением и уже с ним работать.

Почему работает, пока не понял.

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

(with-handlers ([...])
               (cons (with-throe-continuation (/ 1 0)) - захватываем продолжение в этой форме
                     ...)

контекст у продолжения получается такой:
(with-handlers ([...])
               (cons <> - на это место встанет аргумент (0)
                     ...)

вызываем продолжение в хендлере, подставляя 0, в результате получается:
(with-handlers ([...])
               (cons 0
                     ...)

Из нерешаемого (возможно): есть ли возможность установить инспектора для модуля не влезая в его исходники?

Как я понимаю, смысл инспекторов именно в том, чтобы этого было делать нельзя :)

Надо спрашивать на маиллисте, может, там посоветуют какой-нибудь work around.

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

Тогда уж корректнее:

;;#lang racket

(define-syntax-rule (with-throw-continuation body ...)
  (let/cc k
    (with-handlers ([exn? (λ (e) (raise (cons k e)))])
      body ...)))

(define (test l) 
  (if (null? l)
      null
      (cons (with-throw-continuation (/ 1 (car l)))
            (test (cdr l)))))

(define (safe-test l)
  (with-handlers ([(lambda (v)
                     (match v
                       [(cons (? continuation?) (? exn?)) #t]
                       [_ #f]))
                   (lambda (v)
                     (match-define (cons k e) v)
                     (cond
                       [(exn:fail:contract:divide-by-zero? e) (k 0)]
                       [else (raise e)]))])
    (test l)))

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

Как я понимаю, смысл инспекторов именно в том, чтобы этого было делать нельзя :)

Да нет. В документации напрямую написано: «Inspectors are primarily intended for use by debuggers.». По логике доолжно быть что-то типа:

(define (load-inspected file)
   (parameterize ([current-inspector (make-inspector)])
     (load/use-compiled file)))

но хотелось бы найти какую-нибудь документацию с примерами, а то referense очень лаконичен.

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

Экспериментальный метод привел к следующему:

Добро пожаловать в DrRacket, версия 5.3.3 [3m].
Язык: racket [выбранный].
> (define inspector (current-inspector))
> (current-inspector (make-inspector inspector))
> (module m racket
    (provide struct:yoba)
    (struct yoba (x y)))
> (require 'm)
> (struct-type-info struct:yoba)
struct-type-info: current inspector cannot extract info for structure type
  structure type: #<struct-type:yoba>
> (current-inspector inspector)
> (struct-type-info struct:yoba)
'yoba
2
0
#<procedure:yoba-ref>
#<procedure:yoba-set!>
'(0 1)
#f
#f
> 

> (define inspector (current-inspector))
> (current-inspector (make-inspector inspector))
> (module m racket
    (provide struct:yoba)
    (provide yoba)
    (struct yoba (x y)))
> (require 'm)
> (yoba 1 2)
#<yoba>
> (struct-info (yoba 1 2))
#f
#t
> (current-inspector inspector)
> (struct-info (yoba 1 2))
#<struct-type:yoba>
#f
> (yoba 1 2)
(yoba 1 2)
> 

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

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

дебагер устанавливает в качестве текущего инспектора инспектор-потомок (сохраняя предка)

А можно ли таким образом загрузить существующий модуль? Например racket/gui?

require, нсколько я понимаю инспектора внутрь не пробрасывает... load — вроде некошерно. Как правильно?

monk ★★★★★
()
Ответ на: комментарий от monk
#lang racket

(define inspector (current-inspector))
(current-inspector (make-inspector inspector))

(require racket/gui ...)

(current-inspector inspector)

*наш код*

не работает так?

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

Не работает.

(define inspector (current-inspector))
(current-inspector (make-inspector inspector))

(require racket/gui)

(define test% (class object% (init size) (define s size) (super-new)))

(current-inspector inspector)

> (new frame% (label "test"))
(object:frame% ...)
> (new test% (size "test"))
(object:test% "test")

Должна быть какая-то команда «скомпилировать модуль». Как в CL compile-file. Здесь вроде есть: http://docs.racket-lang.org/reference/eval.html , но не одна команда а полдюжины

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

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

Кстати, а что тебе не понравилось-то, болезный? Сайентологи, мунниты, ракетчики, лисперы - это ведь всё эзотерические секты. Аналогия самая прямая. Что не так-то?

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

Ты мало того, что не адекватен, так ещё и агрессивен... Плохо переставать принимать лекарства - совсем дурачком станешь. Хотя, куда уж больше....

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

спасибо, друг! а у тебя еще ссылки есть?

Нет больше. Кликни Серёгу Брина с Маунтин-Вьюского переулка , говорят у него много.

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

так ещё и агрессивен

Сектанты всегда воспринимают объективную информацию как агрессию.

Особенно если это информация относительно их секты. Поэтому у лиспачей всегда так рвёт пердаки, когда кто-то решается расставить точки над «ё». Ведь объективно лисп — это причудливый невыстреливший язычок, а вовсе не «превосходящий все остальные языки метаязык, предвосхитивший будущее».

А сами лисперы — не элитарии IT-мира, а кучка задротов, антисоциалов и фанатиков с узким кругозором.

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

ну а ты впустую тратишь время на такие высиры и чо? лучше бы убирался отсюда и не мешал читать интересные сообщения

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

ну а ты впустую тратишь время на такие высиры и чо?

Почему впустую? Меня забавляет, как разлетаются в клочья пердаки скобканутых. Баттхёрт лисперов — стабильный источник лулза.

лучше бы убирался отсюда

Нет ты.

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

Люди в перерывах между тренажеркой, виски и секасом обсуждают racket и lisp - на их месте могла быть критика чистого разума vs чему нас учат полевые лилии и небесные птицы кьеркегора... но тут врывается эксцентричный анонимус и начинает неистово престрастно уличать в задростве напрополую всех подряд, хотя в это время мог бы отдыхать в компании приятных девушек или кодить на джаве, играть на форексе, спекулировать на чьорном рынке органов (рубить бабло, в общем, в его представлении). Стало быть, одинокий аутист - кто-то другой, кое-кто из забывших рефлексануть :)

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

можно сделать вот так:

(define-syntax-rule (try-or-zero body ...)
  (let/cc k (with-handlers ([exn? (λ _ (k 0))]) body ...)))

(define (testl l) 
  (if (null? l)
      '()
      (cons (try-or-zero (/ 1 (car l)))
            (testl (cdr l)))))

(testl '(1 2 3 0 5))
x4DA ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.