Как передать идентификатор поля объекта ракетки в качестве аргумента функции - PullRequest
0 голосов
/ 26 сентября 2018

У меня есть пример объекта

(define test-class%
  (class object%
         (super-new)
         (field [test-field 3])
         (field [test-field2 2])))
(define test-object (make-object test-class%))

Позже у меня есть код:

(set-data-field! env data-key test-field (+ val 1))

, что приводит к ошибке: 3.rkt: 1548: 42: test-field: несвязанный идентификатор в модуле: test-field

Я хочу передать идентификатор поля в set-data-field!потому что к хешированному объекту может обратиться любой поток, и он защищен с помощью этого кода:

(define (set-data-field! env key field val)
 (let ([data (get-data env key)])
   (if data
     (let ()
       (semaphore-wait (get-data-sem env))
       (set-field! field (get-data env key) val)
       (semaphore-post (get-data-sem env))
       #t)
     #f)))

Как я могу передать идентификатор поля, чтобы выполнить это?

1 Ответ

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

Вы не можете динамически обращаться к полю, используя get-field или set-field!, потому что они являются макросами, а имя поля предоставляется статически (в качестве литерального идентификатора, а не в качестве выражения, которое оценивается).К счастью, racket/class также предоставляет dynamic-get-field и dynamic-set-field!, которые являются обычными функциями, которые принимают символы вместо имен полей.Используя эти функции, вы можете настроить set-data-field! для принятия имени поля:

(define (set-data-field! env key field val)
 (let ([data (get-data env key)])
   (if data
     (let ()
       (semaphore-wait (get-data-sem env))
       (dynamic-set-field! field (get-data env key) val)
       (semaphore-post (get-data-sem env))
       #t)
     #f)))

Затем вы можете настроить свой вызов на set-data-field!, чтобы передать имя поля в виде символа:

(set-data-field! env data-key 'test-field (+ val 1))
...