Как вы узнаете поля и свойства структуры? - PullRequest
0 голосов
/ 04 сентября 2018

вопрос

Предположим, у вас есть такая структура:

(struct soldier (name rank serial-number) #:transparent)
(define s (soldier 'Smith 'private 100134))

Как узнать, какие поля содержит soldier или s? Или какие общие интерфейсы он поддерживает, или какие свойства типа структуры он имеет?


Научно-исследовательские работы до сих пор

(Пропустите этот раздел, если вы уже знаете ответ.)

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

Глава Отражение и безопасность содержит раздел " Инспекторы конструкций ", в котором говорится:

Инспектор обеспечивает доступ к полям структуры и информации о типе структуры без обычных полевых методов доступа и мутаторов.

но я не понял, как заставить инспектора это предоставить.

struct-info и struct-type-info предоставляют некоторую информацию, но не имена полей, интерфейсы, свойства и т. Д.:

> (struct-type-info struct:soldier)
'soldier
3
0
#<procedure:soldier-ref>
#<procedure:soldier-set!>
'(0 1 2)
#f
#f

struct->vector и struct->list обеспечивают доступ к содержимому экземпляра и вышеприведенным данным, но это все:

> (struct->vector s)
'#(struct:soldier Smith private 100134)

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

1 Ответ

0 голосов
/ 04 сентября 2018

Имена полей недоступны во время выполнения. Однако во время расширения вы можете использовать syntax-local-value в имени структуры, чтобы получить некоторую информацию.

Быстрый пример:

#lang racket
(require (for-syntax racket/struct-info))

(struct foo (a b))
(begin-for-syntax
  (display (extract-struct-info (syntax-local-value #'foo))))

Обновление

В этом примере:

#lang racket
(require (for-syntax racket/struct-info))

(struct foo (a [b #:mutable] c))
(begin-for-syntax
  (display (extract-struct-info (syntax-local-value #'foo))))

Список идентификаторов для мутаторов: (#f #<syntax:4:8 set-foo-b!> #f). То есть только второе поле является изменяемым.

Информация доступна во время расширения, поэтому вы можете перенести ее во время выполнения, вызвав макрос, который раскрывается в определение, например (define info '(#f set-foo-b! #f) или подобное.

...