LINUX.ORG.RU

Racket VS Common Lisp

 , , , ,


8

10

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

Ответ на: комментарий от 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 ★★★★★
()
Ответ на: комментарий от monk

Инспектор устанавливается во время запуска, а не во время компиляции, по идее. Видимо он в модуле гуйни хитро как-то переопределяется. В общем надо спрашивать на маиллитсе.

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

Гм. Сейчас посомтрел, тут, видимо, какаие-то хитрые манипуляции с инспекторами внутри Dr.Racket. В чистом репле все работает:

Welcome to Racket v5.3.3.
> (define inspector (current-inspector))
> (current-inspector (make-inspector inspector))
> (require racket/gui)
> (new frame% (label "test"))
(object:frame% ...)
> (current-inspector inspector)
> (new frame% (label "test"))
#0=(object:frame%
    #1=(object:...ed/private/wxtop.rkt:591:4
        #f
        #<cpointer:HWND>
        #t
        #t
        #2=(eventspace
            #<thread:mzscheme>
            #<procedure:...common/queue.rkt:316:34>
            '#hasheq()
            #<semaphore-peek>
            #f
            #<semaphore>
            0
            '#hash()
            0)
        #f
        #f
        #f
        #f
        #f
        #f
        "test"
        #f
        #f
        #f
        #f
        #f
        #f
        #<cpointer:HWND>
        16
        38
        #f
        #t
        #t
        #f
        #3=(object:.../private/wxpanel.rkt:730:4
            #1#
................................
            'center
            0
            #f)
        #f
        #f
        #f
        #f
        #f
        #f
        #4#
        #f
        #f
        #f
        #f
        #f
        #t
        #t
        0
        #f
        #f
        #f
        -1
        -1
        #3#
        #t
        #t
        #f
        '()
        #f
        '#hasheq()
        '#hasheq()
        #f
        #f
        #0#
        #0#
        -1
        -1
        -1
        -1
        #t
        0
        0
        #f
        '()
        #f)
    #<procedure:...rivate/mrtop.rkt:148:44>
    #f
    #1#
    #<procedure:...rivate/mrtop.rkt:148:23>
    "test"
    (object:cursor% (object:cursor-driver% #<cpointer:HCURSOR>))
    #1#
    #1#
    #3#
    #4#
    #f
    #<procedure:finish>
    #1#
    #f
    #f)
>
anonymous
()
Ответ на: комментарий от anonymous

Спасибо! Надо будет время найти и что-то наподобие SLIME-inspector сварганить: а то всё хорошо, но имён полей очень не хватает.

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

У структур поля безымянные. У классов по идее есть имена (которые указываются при инициализации), но я хз откуда их вытащить. В дескрипторе класса этих имен нет.

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

У структур поля безымянные.

???

(struct st (a b))

(define x (st 1 2))

(st-a x) -> 1
(st-b x) -> 2

a и b — поля.

Кстати, как подружить параметризацию с определениями. В CL я могу сделать

(let ((x 0))
  (defun inc () (incf x)))

А в Racket определение потом снаружи не видно.

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

А это не то?

;;#lang racket/base

(require racket/class)

(define my-class%
  (class object%
    (super-new)
    (init-field A B)
    (define/public (get-A)
      A)
    (define/private (get-B)
      B)
    ))

(define my-obj (new my-class% [A 1][B 2]))

(interface->method-names (class->interface my-class%))
(field-names my-obj)
(interface->method-names (object-interface my-obj))

;;result
'(get-A)
'(A B)
'(get-A)

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

a и b — поля.

Нет :)

Имен полей нету, есть только имена ацессоров: st-a и st-b. при чем эти имена генерируются макросом struct, и они не обязательно вообще содержат имя поля, то есть можно указать для ацессоров совершенно любые имена. Если же создавать структуру не макросом, а напрямую, то в качестве ацессоров будут просто лямбды (значения которых можно присвоить произвольно выбранным именам). А на более низком уровне нету и ацессоров для полей - внутренне в Racket структура это просто вектор. И есть лишь один ацессор - который принимает инстанс структуры и номер поля. А это уже потом генерятся лямбды вида: (lambda (x) (yoba-ref x 0)), (lambda (x) (yoba-ref x 1)) и так далее.

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

А в Racket определение потом снаружи не видно.

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

Вариантов сделать как в SBCL два - либо splicing-let, либо (define name (let ([...]) (lambda (x) ...)).

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

Я выше описал, информация о каких полях хранится. Но это далеко не все поля, большая часть в том же frame% имен не имеет.

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

Вариантов сделать как в SBCL два - либо splicing-let...

Именно это и искал. А splicing-parameterize приципиально не бывает? Просто костыли (define inspector ...) слегка напрягают, а группу параметризовать неясно как.

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

имена других полей получить нельзя - их просто не существует.

Ну почему?

grep -r "(struct st" $racket-dir | parse-struct

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

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

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

какой смысл параметризовывать лмябду, если при выходе из парметризации (и при запуске лямбды, соответственно) параметры вернутся к оригинальным значениям?

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

кстати если структура определена через struct то можно через (syntax-local-value #'struct-name) получить статическую информацию о структуре, в которой будут имена ацессоров.

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

какой смысл параметризовывать лмябду, если при выходе из парметризации (и при запуске лямбды, соответственно) параметры вернутся к оригинальным значениям

-> (parameterize ([current-inspector (make-inspector)])
    (struct st (a b))
    (struct st2 (c d))
    (define test% (class object% (super-new) (init-field a)))
    (list (st 1 2) (st2 3 4) (new test% [a 10]))) 

(list (st 1 2) (st2 3 4) (object:test% 10))

-> (st 1 2)
. . reference to an identifier before its definition: st
monk ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.