В Racket я хочу использовать имена полей структуры для метапрограммирования.Получить имена полей структуры
Например:
(struct pt [x y])
(struct-fields pt) ;; -> '(x y)
В Racket я хочу использовать имена полей структуры для метапрограммирования.Получить имена полей структуры
Например:
(struct pt [x y])
(struct-fields pt) ;; -> '(x y)
Вы не можете. Вы можете получить аксессоров, которые будут здесь pt-x
и pt-y
, но вы не можете получить только x
и y
. Почему это? Одна из причин заключается в том, что на самом деле могут быть дубликаты. Рассмотрим сценарий с участием какой-то пагубной STRUCT подтипов:
#lang racket/base
(struct A [x] #:transparent)
(struct B A [x] #:transparent)
Теперь структура типа B
имеет два x
поля, A-x
и B-x
. По этой причине любой макрос, который пытается использовать имена полей только с structs, нарушается, когда может быть задействовано подтипирование.
Что вы можете сделать, это использовать аксессоров, вместо этого, который можно достичь с помощью syntax-local-value
плюс extract-struct-info
, затем смотрит на четвертый элемент результирующего списка. Однако, честно говоря, я думаю, что это слишком много работы, поэтому я написал класс синтаксиса, чтобы сделать для вас всю тяжелую работу. Установите syntax-classes
пакет и использовать класс struct-id
синтаксиса:
#lang racket/base
(require (for-syntax racket/base
syntax/parse/class/struct-id)
syntax/parse/define)
(define-simple-macro (struct-accessors id:struct-id)
(list id.accessor-id ...))
> (struct pt [x y] #:transparent)
> (struct-accessors pt)
'(#<procedure:pt-x> #<procedure:pt-y>)
Я полагаю, я мог бы назвать '~ a' по процедуре аксессора затем извлечь имя поля из строкового представления, но это, кажется, очень безвкусные. Я надеялся использовать имена полей структуры для извлечения значений для создания экземпляров структур из документа sxml, но я начинаю думать, что это не лучший способ или даже приемлемый способ сделать это. – Winny
@Winny Атрибут 'accessor-id' дает вам идентификаторы, поэтому вы можете просто использовать' (синтаксис карты-e (атрибут access-id)) ', чтобы получить кучу символов; не используйте '~ a' для этого таким хакерским способом. Снятие общего префикса off * будет * работать для структур без подтипирования, так что было бы хорошо, если бы вы гарантировали 'supertype-id'' 't'. –