Как поставить символ Лисп / Схема / Ракетка в конце? - PullRequest
1 голос
/ 07 февраля 2020

Форма в Лиспе / Схеме / Ракетке имеет символ, помещенный в первую позицию. Этот код работает в Racket:

(define (? a b) (if a (display b) 0))
(? #t "Hello")

Но я хочу смоделировать оператор a? b:0 в C / C ++, и знак вопроса (символ) должен находиться в конце после a.

Как поставить ? и a и b в этом порядке?

(define (a ? b) (if a (display b) 0))
(#t ? "Hello")

Нужно ли использовать define-syntax или что-то подобное вещи?

Ответы [ 2 ]

3 голосов
/ 07 февраля 2020

У меня есть три ответа на ваш вопрос.

1 Не делайте этого

У каждого языка есть правила, соглашения и прагматика. Ваш опыт использования Racket будет болезненным, если вы попытаетесь заставить его выглядеть как C / C ++. Вы будете тратить время на подобные проблемы вместо того, чтобы учиться думать в модели программирования Racket и использовать инструменты, разработанные Racket для этой модели.

Для конкретного примера c Racket имеет правило, что форма (выражение, определение, объявление и т. д. c) начинается с оператора (например, display или list или +) или syntacti c, ключевое слово (например, define или if). Это правило устраняет множество сложных проблем, которые мешают расширению синтаксиса. Например, что будет приоритетом инфиксного синтаксиса против других специальных форм; в (lambda ? 5), это форма lambda или (плохая) форма ??

Чтобы уточнить: Racket настоятельно рекомендует вам расширить язык с помощью новых форм syntacti c в пределах границ S-выражения, оператор-первый синтаксис.

2 Частичное решение

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

(1 . < . 2)
(< 1 2)

Таким образом, вы можете написать

(#t . ? . "Hello")

Лично я думаю, что это обычно затрудняет чтение кода.

3 Открытое исследование topi c

Люди проводят исследования по расширению структуры построения языка Racket для работы с синтаксисами, не основанными на S-выражениях. Одним из примеров является Хону; см. статью "Хону: Syntacti c Расширение для алгебры c Обозначения через Enforestation . Есть и другие, а topi c все еще открыт.

1 голос
/ 08 февраля 2020

Позвольте мне предложить альтернативное решение путем переопределения синтаксиса приложения #%app. Вот пример троичного оператора в C -подобных языках:

#lang racket

(require syntax/parse/define
         (only-in racket [#%app racket:#%app]))

(define-syntax-parser #%app
  [(_ test-expr {~datum ?} then-expr {~datum :} else-expr)
   #'(if test-expr then-expr else-expr)]
  [(_ xs ...)
   #'(racket:#%app xs ...)])
> ((= 42 42) ? "a" : "b")
"a"
> ((= 42 0) ? "a" : "b")
"b"

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

> (define-simple-macro (discard-all xs ...) 1)
> (discard-all ? 42 : 123)
1
> (if ? 1 : 2)
if: bad syntax ;; because if should have exactly three subforms, but the above line has four.

Но, как сказал Райан, это не «хороший» код Racket в том смысле, что он не поддается соглашению Racket, и никто (ну, возможно, кроме вас) не сможет понять ваш код.

...