Struct 添加结构字段
所以,我有一个球拍结构,统计:Struct 添加结构字段,struct,scheme,racket,Struct,Scheme,Racket,所以,我有一个球拍结构,统计: (struct stats (str con dex int wis cha)) 我有一个函数添加统计数据: (define (modify-stats mods base) (stats (+ (stats-str mods) (stats-str base)) (+ (stats-con mods) (stats-con base)) (+ (stats-dex
(struct stats (str con dex int wis cha))
我有一个函数添加统计数据:
(define (modify-stats mods base)
(stats (+ (stats-str mods)
(stats-str base))
(+ (stats-con mods)
(stats-con base))
(+ (stats-dex mods)
(stats-dex base))
(+ (stats-int mods)
(stats-int base))
(+ (stats-wis mods)
(stats-wis base))
(+ (stats-cha mods)
(stats-cha base))))
显然,这真的很混乱,而且有很多不必要的重复。我设法把它删减到一个更可读的版本:
(define (modify-stats mods base)
(define (add-stat statid)
(+ (statid mods)
(statid base)))
(stats (add-stat stats-str)
(add-stat stats-con)
(add-stat stats-dex)
(add-stat stats-int)
(add-stat stats-wis)
(add-stat stats-cha)))
但仍然有很多重复的“统计(s)”在那里。有没有更干净的方法可以在同一类型的两个结构的字段上执行操作
更新:
我已经设法让它变得更好了,就像这样:
(define (stat a-stat stats)
(match a-stat
["str" (stats-str stats)]
["con" (stats-con stats)]
["dex" (stats-dex stats)]
["int" (stats-int stats)]
["wis" (stats-wis stats)]
["cha" (stats-cha stats)]
[_ (error "Not a stat!")]))
(define (modify-stats mods base)
(define (add-stat string)
(+ (stat string mods)
(stat string base)))
(stats (add-stat "str")
(add-stat "con")
(add-stat "dex")
(add-stat "int")
(add-stat "wis")
(add-stat "cha")))
在不诉诸反思的情况下,有一种方法可以做到:
(define (modify-stats mods base)
(define (get-fields obj)
(map (lambda (getter) (getter obj))
(list stats-str stats-con stats-dex stats-int stats-wis stats-cha)))
(apply stats (map + (get-fields mods) (get-fields base))))
尽管我不愿意建议使用宏来提高性能,但此宏生成的代码与OP的第一个版本完全相同:
(require (for-syntax racket/syntax))
(define modify-stats
(let-syntax
((bump (lambda (stx)
(define (bump-attr attr)
(with-syntax ((getter (format-id attr "stats-~a" attr #:source attr)))
#'(+ (getter mods) (getter base))))
(syntax-case stx ()
((_ attr ...)
(with-syntax (((bumped ...) (map bump-attr (syntax->list #'(attr ...)))))
#'(lambda (mods base)
(stats bumped ...))))))))
(bump str con dex int wis cha)))
这个版本大约比OP的第一个版本慢17倍,比OP的第二个版本慢3倍。因此,如果性能重要,我会坚持最初的版本。完全可以理解。第一个版本对于内联来说很简单。第二种方法增加了更多的间接成本,而我的方法又提高了一个档次。:-)同意。因此,“理想”的解决方案是使用反射生成第一个版本的语法扩展。你认为这是可行的吗?我实际上是在为这样的事情写一个概念证明宏,但没有使用反射(因为这也有成本)。+1用于接受挑战;-)也许是因为我没有那么聪明,但是第二种执行操作的方式读起来就像我能想象的读代码一样清晰。除非有令人信服的理由,例如许多不同的结构具有类似的操作,否则这看起来就像是我想要维持的。如果通用方法是合适的,那么我希望传入像addstat
这样的操作,而不是硬连接它<代码>此问题似乎更适合StackExchange代码审查,因为代码正在运行。