LINUX.ORG.RU

Вышел Racket 6.4

 ,


4

3

Вышла версия 6.4 языка Racket — языка программирования общего назначения из семейства Lisp/Scheme.

  • Исправлена уязвимость в Web-сервере. Данная уязвимость позволяла получить доступ к любому файлу, доступному Web-серверу для чтения (подробности).
  • Новый инкрементальный сборщик мусора уменьшил паузы, что особенно важно в играх и анимациях.
  • Скроллинг в DrRacket стал быстрее.
  • Добавлен болгарский перевод в DrRacket.
  • Каталог пакетов теперь имеет адрес HTTPS по умолчанию, а не HTTP.
  • Документация теперь может определять свои собственные категории для главной страницы руководства с использованием строк.
  • Шпаргалка по Racket включена в основной дистрибутив.
  • Контракт, который Typed Racket генерирует для типа Any, стал более либеральным, что позволяет большему числу программ как с использованием системы типов, так и без неё работать без ошибок контракта.
  • Redex поддерживает спецификацию связей (binding specifications).
  • Все функции pict принимают pict-convertible, что обеспечивает прозрачное взаимодействие между pict и библиотеками типа 2htdp/image.
  • Команды raco profile и raco contract-profile предоставляют лёгкий доступ к инструментарию профилирования без необходимости изменять сами программы.

>>> Подробности

anonymous

Проверено: maxcom ()
Последнее исправление: Wizard_ (всего исправлений: 6)
Ответ на: комментарий от q0tw4

сразу резко полностью подставляет #,(synth-def-sr-form sd) несмотря на то, что в sd есть тоже вызовы макросов

В CL, если макрос вида `(... ,(synth-def-sr-form sd) ...), то даже при macroexpand-1 (synth-def-sr-form sd) целиком выполнится.

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

В CL

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

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

Я заменяю (begin-for-syntax ...) на (module m racket ...)

Интересно как такое провернуть с моей saw-err в примере. И вообще непонятно, откуда берутся символы hold и прочие. Вроде как они порождаютса из репла когда я пишу play, но вроде как находятся всетаки на стадии 1 и успешно матчатся со списком literal-id в syntax-case. Но когда я сочиняю простой define-syntax-rule, они почему-то интернятся куда-то в другое место. Вопщем интересно узнать, почему в http://pasterack.org/pastes/15193 (play (saw-err 440 0.0) 3) не компилится, и как объяснить этому монстру, что я имел ввиду именно тот hold, что в syntax-case. Или может быть я ошибся на шаг раньше когда решил, что макрос может вернуть невалидный для ракета синтакс, который пойдет параметром активного макроса и уже там преобразуется в валидный. Вот скажи есть ли такое условие, что макрос обязан возвращать синтакс в терминах текущего языка? И можно ли это обойти организовав себе модуль-язык...

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

Интересно как такое провернуть с моей saw-err в примере.

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

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

(play (saw-err 440 0.0) 3) не компилится

У тебя в sl->synth-def попадает (saw-err 440 0.0). Он не начинается на hold. Раскрытие макросов всегда начинается снаружи. То есть если есть (play (saw-err 440 0.0) 3), и play и saw-err — макросы, то сначала раскроется play, а уже в результате раскрытия — (saw-err 440 0.0).

Если очень хочется (но этого делать крайне не рекомендуется) использовать макрос как функцию, то в sl->synth-def вместо (syntax-case sl-stx (lt hold push saw) надо писать что-то вроде (syntax-case (syntax-disarm (local-expand sl-stx (syntax-local-context) #f) #f) (lt hold push saw)

Здесь local-expand принудительно раскрывает макрос, а syntax-disarm позволяет использовать биндинги из него.

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

я переписал транслятор в виде класса с диспатчем в методы по имени первого слова в синтаксе

Это правильно.

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

Ага перенес. И тут выполз баг из серии «я хз что с этим делать». Впрочем может он родился ранее, но странно, вроде до рефакторинга это место там было, но работало. https://github.com/Hikawa/synmak/tree/ea5029bee7ad30698d48ba582e2b3fe94b35761d (короче переехал на гытхаб, ибо файл уже не один). Вобщем проблема в том, что при кодогенерации формы #`(begin #,@<tratat>) оно не видит символа begin. Ну ок сказал я и написал функциональный аналог бегина. Дак нет же, не видит и его. Ну ок приказал подставлять не символ а сразу ссылку на функцию, но и так не нравится

synthdef.rkt:49:29: ?: function application is not allowed;
 no #%app syntax transformer is bound in: (#<procedure:begin-fun> (let ((result (+ g1 0))) (set! g1 (+ g1 (* 1/44100 (* (+ 0 1) 400)))) (- result (floor result))))

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

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

Вот упрощенный пример этой баги:

Файл «test.rkt»

#lang racket

(require syntax/stx)

(provide test)

(define (test stx)
  #`(begin #,@(stx-cdr stx) 1))

Следующий код не работает:

#lang racket

(require (for-syntax "test.rkt"))

(define-syntax (app-test stx)
  (test stx))

> (app-test (print 3))
. test.rkt:8:5: begin: unbound identifier;
 also, no #%app syntax transformer is bound
  context...:
  other binding...: in: begin

Вот что это за... Вот точно надо писать свой ракет, потому что нельзя делать ЯП вот так. На таком невозможно работать.

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

Ага, в ирке ответили что надо прогрузить ракет на -1 стадию, что в принципе логично. Тогда понятно почему с begin-for-syntax работает. Там то прогрузка происходит в начале файла на стадию ниже текущей. А в отдельном модуле надо грузиться самому, ибо когда меня загружают, мои символы уже смотрят вникуда. Не думал, что мне так быстро понадобятся такие заумные штуки как -1 стадия.

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

racket-way макросы не следуюет использовать для оптимизаций

Ну ок, написал полностью динамическую версию repl https://github.com/Hikawa/synmak/tree/99841d48aff07bde7e6dded2609433cd73cf8741 . Как я и думал когда писал статику, вышло сложнее (чего стоит один только ремап переменных состояния на вектор хешей), хоть и без единого евала. Причем подобный общий подход будет гарантированно безбожно тупить там, где можно было обойтись статикой или почти статикой.

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

Вобщем, понятно почему я предпочитаю коммон?

Если решение в стиле CL, то просто замени в определении play #`(let ...) на (datum->syntax stx (syntax->datum #`(let ...)))

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

«Лошадь завсегда лучше, куда вожжу потянешь, туда и едет, и даже если пьян, то до дому довезёт, а вот машина в самый неподходящий момент всегда глохнет»

А в целом — нельзя смешивать идентификаторы разных фаз. У тебя synthdef импортируется for-syntax. А begin появляется в нём. Соответственно, begin получает привязку только в фазе for-syntax и не работает. Правильное решение: в synthdef добавить (require (for-template racket)). Тогда в synthdef идентификаторы получат привязку на -1 (for-template) уровне в модуле racket и при импорте в for-syntax уровни сдвинутся на один и begin будет рабочий.

P.S. Если объяснил непонятно, скажи, попробую понятней объяснить.

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

просто замени в определении play #`(let ...) на (datum->syntax stx (syntax->datum #`(let ...)))

Ага знаю

Если объяснил непонятно

Это уже в ирке рассказали

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

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

чем генератор повторителя в рантайме.

Именно то, что ты хотел в первый раз, работало простой заменой (repl ...) на (for/vector ...). Текущая версия делает что-то для меня не очень понятное.

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

простой заменой

Забываешь, что выражения statefull. При повторении, на каждой итерации обязан быть независимый набор переменных состояния, иначе вместо того, чтоб играть 2 волны впаралель оно начнет играть одну волну с частотой равной сумме заданных частот. Так уже было однажды, до того как я это поправил с помошью generate-temporary.

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

Кстати, посмотрел я на этот play повнимательней...

Можешь мне объяснить зачем вообще он является макросом? Он ведь по сути получает некую последовательность команд и их проигрывает. Или нет?

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

Забываешь, что выражения statefull.

(play (vector (saw (* (+ 0 1) 400) 0) (saw (* (+ 1 1) 400) 0)) 3) == (play (repl i 2 (saw (* (+ i 1) 400) 0)) 3)

Или нет? Если равно, то можно заменить на (play (for/vector ([i 2]) (saw (* (+ i 1) 400) 0)) 3). Точнее можно было бы, если бы play было функцией, а не макросом, который особым образом обрабатывает всё, что начинается на vector.

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

который особым образом обрабатывает всё, что начинается на vector.

Особым образом обрабатывается saw. vector просто лифтится как в хаскель стрелках. Вобщем идея (play `(vector ,@(for/list ([i 2]) `(saw (* (+ ,i 1) 400) 0))) 3) вполне рабочая, но это как раз пример статического лупа, где количество повторений известно при компиляции. В моем же варианте все так сложно потому, что вместо [i 2] можно написать [i (floor (* 1.9 (saw 20 0)))] и получить 20 раз в секунду отваливающийся второй канал.

если бы play было функцией

Он макрос потому, что это хитрый ход с неявным eval. Был бы он функцией, транслятор выдал бы ему синтакс, который следовало бы запустить евалом. Только не надо предлагать вместа синтакса делать просто лямбду. Так я до компиляции в C никогда не дойду.

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

Добавил евенты https://github.com/Hikawa/synmak/tree/363c17c8ed96027b59a8c82791ec3112a1d54def . Код начал загавняться. Если не лень, может предложишь чего глядя на код по диагонали. Свежий взгляд всегда полезен.

Да кстати мне еще небось разгребать вложенные holdы с одинаковыми именами переменных + вложенные let-syntax с make-set!-transformerами, которые должны чейниться...

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

Он макрос потому, что это хитрый ход с неявным eval.

Да кстати мне еще небось разгребать вложенные holdы с одинаковыми именами переменных + вложенные let-syntax с make-set!-transformerами, которые должны чейниться...

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

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

Если настаиваешь на макросе play

У него есть функциональная ипостась translate-synth.

Я тут это задумался о том, можно ли ввести таки макросы для моего ДСЛ и совершенно непонимаю что я делаю и как это делать. Поидее оно должно выглядеть както так (begin (def (sound x) (saw (* x 200) 0)) (repl i 2 (sound (+ i 1))) тоесть символьная подстановка. Но как это впихнуть в текущую систему непонятно.

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

Но как это впихнуть в текущую систему непонятно

Так это выглядит как программа. А не «vector». А промежуточное представление точно нельзя в замыкания завернуть? Тогда play было бы просто функцией, а вся механика была бы в его параметре (параметр типа «функция»).

Или у тебя разные функции могут влиять на состояние друг друга?

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

параметр типа «функция»

А не АСТ ДЛСя? Непонял.

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

Тогда play было бы просто функцией

Первая версия play как раз была функцией. Тогда я не дождался окончания выполнения кода типа (for ([i (* secs 44100)]) (define sample (eval (synth-def-sr-form sd)))) и догадался переписать его как (let ([fun (eval #`(lambda () #,(synth-def-sr-form sd)))]) (for ... и в принципе я могу вернуть этот вариант. Но потом я просто подумал, что забавнее будет зашифровать этот eval макросом.

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

(define-syntax (def stx)
  (syntax-case stx ()
    [(_ (macro arg ...) body) (begin (define-syntax-rule (macro arg ...) body) #'(void))]))

но совершенно непонятно, как его интегрировать в окружение без eval. В принципе такие штуки работают. Если написать (play (some-macro ...) ...), оно зацепит макрос из текущего окружения и спокойно его применит (проверял). В любом случае я могу реализовать def средствами класса транслятора, если заведу таблицу макросов и попляшу хорошенько с бубном.

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

Я пытаюсь генерировать на ракете так, как я буду генерировать на С

Семантика разная. Может лучше за основу взять подход L++?

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

(begin (def (sound x) (saw (* x 200) 0)) (repl i 2 (sound (+ i 1)))

Its ALIVE!!!! https://github.com/Hikawa/synmak/tree/f525d908e91e8ad4e2bc19804bb95a66a7391d15 . Сам не верю что получилось. Только вопрос на засыпку с закоментированным

(define-namespace-anchor my-namespace)
(define-syntax-rule (make-rules name ...)
  (make-hash (list (cons 'name (eval (string->symbol (string-append "translate-" (symbol->string 'name)))
                                     (namespace-anchor->namespace my-namespace))) ...)))

В своем файле оно норм компилитсо, а когда импортишь из другого в for-syntax, eval перестает интернить символы. Опять подстава. Ну тут к счастью можно подставить макрос руками. Классный язык ракет, если в нем макросы можно разворачивать на мозге, если не компилятся по неясной причине))

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

а когда импортишь из другого в for-syntax, eval перестает интернить символы

Опять не та фаза.

Правильно

(define-syntax (make-rules stx)
  (syntax-case stx ()
    [(_ name ...)
     (with-syntax ([(translate-name ...) (stx-map (λ (x) (format-id x "translate-~a" x)) #'(name ...))])
       #'(make-hash (list (cons 'name translate-name) ...)))]))

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

А что тогда делает (define-namespace-anchor my-namespace)? Вроде как это ответ на то, что я просил инфраструктуру ручного управления биндингами. Почему не работает через фазы?

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

Вроде как это ответ на то, что я просил инфраструктуру ручного управления биндингами. Почему не работает через фазы?

eval выполняется при выполнении модуля. И выполняется в нулевой фазе (определяется пространством имён). А импортируешь всё остальные ты в for-syntax — первую фазу.

(define-namespace-anchor my-namespace) позволяет тебе внутри eval'а использовать биндинги соответствующего пространства имён в нулевой фазе.

Если очень хочется eval, пиши:

(define-namespace-anchor my-namespace)
(define-syntax-rule (make-rules name ...)
  (make-hash (list (cons 'name 
                         (eval #'(string->symbol (string-append "translate-" (symbol->string 'name)))
                               (namespace-anchor->namespace my-namespace))) ...)))

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

Вот чем и плох ракет. Очень сложно держать в голове все эти фазы. Научить бы дракета подсвечивать их разными цветами. В коммоне в принципе тоже возникают проблемы, когда макросом генеришь макрос, но там наверно проще это все разложить по этапам. А тут смотришь на этот код, пытаешься представить себе, что ктото инклюдит его на 1 фазу и получаешь надпись brain system error: segfault между монитором и глазами.

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

Научить бы дракета подсвечивать их разными цветами.

В macro-stepper'е подсвечиваются. В смысле тыкаешь в символ, все его биндинги выделяются, а справа видно в каких фазах данный символ имеет биндинги

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

Ыы нашел эпик баг в компилере

#lang typed/racket

(require (for-template typed/racket))

(struct pt ([x : Real] [y : Real]))

=> . struct: expected a field-specification keyword in: :

Тоесть если сделать require for-template, язык резко теряет свою типизированность. трололо.

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

и в догонку непонятно как узать syntax-case в typedе: (syntax-case #'(1 2) () [(x ...) #'(x ...)]) падает с Type Checker: missing type for identifier.

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

если сделать require for-template, язык резко теряет свою типизированность. трололо.

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

Хотя здесь это правильно. typed/racket в своём for-syntax инстанцирует нетипизированный racket. Значит, если ты сделал (for-template typed/racket), то этот модуль является синтаксическим для него, а значит нетипизированным.

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

Тоесть вывод получается такой: typed не готов к продакшену, узай контракты. Не ну что, я буду писать (match (syntax->list stx) ...) вместо syntax-case чтоли. Да и еще там куча багов есть, например из того, что еще находил

> (define [x : (Listof (HashTable Any Any))] (list (make-hash)))
. type-check: type name HashTable used out of context in (HashTable Any Any) in: HashTable

Это же выходит не ЯП, а сплошной глюкодром, я такое только в идрисе когдато видел и в перле 6, когда тот на пароте еще был.

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

(define [x : (Listof (HashTable Any Any))] (list (make-hash)))

Так ошибка у тебя. Должно быть

#lang typed/racket
(define x : (Listof (HashTable Any Any)) (list (make-hash)))

typed не готов к продакшену, узай контракты

Для написания тел макросов — да. А зачем тебе типы на стадии компиляции?

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

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

PS. А разве есть смысл юзать ракет там, где нет своего ЯП. В этом же его сила, не?

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

Потому что у меня компилятор ёпт.

У тебя странный компилятор. Обычно люди делают это по-другому. L++ я тебе уже ссылку давал. Вот компилятор в Racket на макросах: http://planet.racket-lang.org/package-source/dyoo/bf.plt/1/2/manual.html

Для него компиляция есть свой такой временный, но вполне так рантайм с функциями над синтаксами и прочим.

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

А разве есть смысл юзать ракет там, где нет своего ЯП. В этом же его сила, не?

В смысле «Зачем ракет без DSL?». Затем же, зачем C++ без boost, например, Я свои программы пишу на чистом Racket, так как это просто удобно.

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

В контрактах есть заморочка, что они лучше работают через модули. А нужны типы только для одной задачи - помочь с дебугом, так как типизация позволяет выловить ошибку ближе всего к месту ее возникновения. Так что контракты то да, но все эти #:freevar напрягают, а без них толку уже меньше.

У тебя странный компилятор.

Ну во-первых он компилит пока что s-expr в s-expr, так что сохранять syntax с оригинальным сорцом - фишка от которой сложно отказаться. Во-вторых любой мало мальски сложный макрос требует выделения частей функционала отдельно, и частенько это выделение приходится именно на ту часть, которая выполняется в фазе 1, что и приводит к необходимости использовать syntax-case в отдельной функции, которой тоже необходимо выдать тип.

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

В контрактах есть заморочка, что они лучше работают через модули.

define/contract. Что в нём не хватает?

И для синтаксисов ещё раз напоминаю про syntax-parse. Там замечательные встроенные контракты на структуру синтаксиса.

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

define/contract. Что в нём не хватает?

https://docs.racket-lang.org/guide/contracts-gotchas.html пункт 7.9.2. Контракты предназначены для командной разработки в разных модулях. Для рефакторинга своего кода они хоть и годятся, но работают хуже, чем статическая система проверки типов.

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

https://docs.racket-lang.org/guide/contracts-gotchas.html пункт 7.9.2.

Там только blame неправильный. Цепочка вызовов и в трассировке видна. Зачем вообще blame внутри одного модуля? Разве что если один модуль командой разрабатывать, но это уже групповуха какая-то.

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

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

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

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

Ну если так, то typed/racket подойдёт. Просто имей в виду, что достаточно большая часть библиотек не имеет описаний типов (как в твоём примере с syntax-case, там не указан тип у функции datum->syntax/shape). Если типизация есть, то всё работает хорошо.

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

Ну я и говорю: неготов. А еще есть некие сомнения по поводу движка вывода типов. Его как смотрю не особо любят узать, так что врядли вылизали как хаскель, хоть и обещали подобную мощность. В общем непонятно, есть ли смысл в своих проектах заморачиваться типо-параметрами и прочим. Вот например в моем компиляторе я решил узать типы крайне четко для описания работы скомпиленного. Тоесть всяким макросам на def я вообще не дам типа, сначала подставлю, потом уже потипизирую. Короче макроязык будет безтиповый - всеравно его в компилтайме вычислять, а там спешить некуда. А функций в моем ДСЛ в принципе нету, вместо них ограниченный набор стрелок.

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

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

Система типов в Racket мощнее. Есть интервальные типы, типы-объединения и подтипы.

Вывод типов в Racket не выводит типы, а проверяет их (этим он строго отличается от хаскеля). Но проверяет типы хорошо (учитывает конструкции cond и if).

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

Вот пример, где проверки типов не хватает:

(: f (-> Integer Positive-Integer))
(define (f x)
  (if (> x 1) x (- 2 x)))

при том, что

(: f (-> Integer Positive-Integer))
(define (f x)
  (if (> x 0) x (- 1 x)))
успешно проходит проверку.

Проверяльщик типов не может доказать, что (- 2 x) больше нуля, если x меньше единицы.

Приходится писать так:

(: f (-> Integer Positive-Integer))
(define (f x)
  (if (> x 1) x (cast (- 2 x) Positive-Integer)))

Но в этом случае cast добавляет проверку при выполнении.

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

интервальные типы, типы-объединения

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

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

Ну вот, опять нужна помощь. Я зачитал файл с помощью read-syntax и при попытке заузать полученный синтакс наткнулся на no #%datum syntax transformer is bound in the transformer environment. Вопрос: как заставить read-syntax работать в нашем неймспейсе или перебиндить то, что он выдает. Там что всякие disarm надо да?

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