Как вы получаете struct-copy для создания структуры того же типа, что и оригинал? - PullRequest
0 голосов
/ 03 сентября 2018

Для иллюстрации приведем небольшую неизменную структуру и функцию для ее обновления:

(struct timeseries (variable observations) #:transparent)

(define (add-observation ts t v)
  (struct-copy timeseries ts
               [observations (conj (timeseries-observations ts) `(,t ,v))]))

Мой вопрос: если я создаю структуру, которая наследуется от timeseries, то add-observation вернет структуру timeseries, а не структуру того типа, который был передан. Как вы обновляете структуру и сохраняете ее тип?

Кстати, если приведенный выше код не совсем так, как это делается в Racket, пожалуйста, дайте мне знать обычным способом. Тот факт, что я не нашел функцию в библиотеках Racket, такую ​​как struct-copy, но которая сохраняет тип исходной структуры, заставляет меня подозревать, что я поступаю неправильно. Есть ли какой-нибудь обычный способ достичь той же цели, не сталкиваясь с проблемой возврата структуры другого типа, чем вы начали?

1 Ответ

0 голосов
/ 28 октября 2018

К сожалению, это одно из общеизвестных ограничений struct-copy, большинство из которых вытекают из того, что Сэм Тобин-Хохштадт метко описал как "негигенически склеивающие части структур вместе". (а не низкоуровневое представление о копирующих структурах), и является частью причины , что «struct-copy безнадежен и не может быть исправлен без существенных изменений в том, как работают структуры». Матиас Фелляйзен описал это как "ахиллесова пята в нашем мире". В сообществе Racket определенно есть желание улучшить эту ситуацию, но по ряду причин это кажется пугающим. Я не знаю никого, кто бы активно работал над этим, и на что похоже принципиальное решение, остается открытым вопросом.

Структуры во многом очень важны для Racket. Концептуально, каждое значение в Racket может быть экземпляром некоторого структурного типа, хотя в действительности система времени выполнения имеет специализированные представления для определенных встроенных модулей. Фактически, я думаю, что текущая работа по замене C на Chez Scheme в реализации Racket может использовать структуры для некоторых вещей, встроенных в устаревшую Racket VM. Это возможно, потому что структуры предлагают сильные возможности инкапсуляции, особенно через инспекторов . Улучшение структуры работы затронуло бы практически весь Racket и повлекло бы за собой множество разрозненных соображений, особенно в отношении обратной совместимости.

Вот несколько советов для дальнейшего чтения о проблемах:

  • Это сообщение от Сэма обрисовывает, как struct может начать предоставлять больше статической информации при сохранении обратной совместимости.
  • Эта проблема GitHub , в частности последний комментарий от Alexis, указывает (а), что не очевидно, какой будет правильная статическая информация для добавления, и (б) что добавление статической информации о Имена полей будут недостаточны для решения проблем с подтипами.
  • Эта ветка указывает на другое ограничение struct-copy и включает в себя хорошее резюме от Alexis:

    struct-copy непоправимо сломан и не может быть исправлен без фундаментальные изменения в структурной системе Racket. А именно, он имеет Проблема «нарезки», знакомая программистам C ++ при использовании struct наследование, и как он синтезирует полевые методы доступа из предоставленные имена полей негигиеничны и могут быть легко сорваны.

Хорошая новость заключается в том, что, хотя выяснить, как правильно делать общее дело, сложно, подход Racket «языки как библиотеки» позволяет всем программистам и авторам библиотек пробовать разные подходы в своем собственном коде. Существуют различные пакеты Racket, чтобы помочь с функциональным обновлением и другими функциями. Alexis 'struct-update предоставляет макрос для синтеза таких функций, как timeseries-observations-update. Джей МакКарти также экспериментировал с улучшениями для структурирования в библиотечном коде. Вы также можете реализовать решение, адаптированное к вашему конкретному варианту использования, от реализации согласованного метода copyracket/generic или racket/class) до создания языка, специфичного для домена, который может более естественно выразить вашу проблемную область. Эта ветка списка рассылки , несмотря на тему, охватывает множество подходов к функциональному обновлению в Racket (включая некоторые мои мысли о DSL).

...