是否可以将结构嵌套在Clojure中的结构中?请考虑以下代码:
(defstruct rect :height :width) (defstruct color-rect :color (struct rect)) (defn #^{:doc "Echoes the details of the rect passed to it"} echo-rect [r] (println (:color r)) (println (:height r)) (println (:width r))) (def first-rect (struct rect 1 2)) ;(def c-rect1 (struct color-rect 249 first-rect)) ;form 1 ;output "249 nil nil" (def c-rect1 (struct color-rect 249 1 2)) ;form 2 ;output "Too many arguments to struct constructor (echo-rect c-rect1)
当然这是一个人为的例子,但有些情况下我想将大型数据结构分解为更小的子结构,以使代码更易于维护.由于注释表明如果我形成1,我得到"249 nil nil",但如果我做表格2,我得到"结构构造函数的参数太多".
如果我以错误的方式处理这个问题,请告诉我应该做什么.搜索Clojure google小组并没有为我提供任何帮助.
编辑:
我想我在问题陈述中并不像我想象的那样清楚:
1.)是否可以在Clojure中将一个结构嵌套在另一个结构中?(从下面判断,这是肯定的.)
2.)如果是这样,那么正确的语法是什么?(同样,从下面看,看起来有几种方法可以做到这一点.)
3.)当你有一个嵌套在另一个结构中的结构时,如何通过指定的键获取值?
我想我的示例代码并没有真正展示我想要做的很好.我在这里添加这个,以便其他人搜索这个可能更容易找到这个问题及其答案.
我同意其他海报的结构图并不真正支持继承.但是,如果您只想创建一个使用另一个键的新结构,这将起作用:
; Create the rect struct (defstruct rect :height :width) ; Create the color-rect using all the keys from rect, with color added on (def color-rect (apply create-struct (cons :color (keys (struct rect))))) (defn create-color-rect "A constructor function that takes a color and a rect, or a color height and width" ([c r] (apply struct (concat [color-rect c] (vals r)))) ([c h w] (struct color-rect c h w)))
您不需要该echo-rect
函数,您可以简单地评估struct map实例以查看其中的内容:
user=> (def first-rect (struct rect 1 2)) #'user/first-rect user=> first-rect {:height 1, :width 2} user=> (create-color-rect 249 first-rect) {:color 249, :height 1, :width 2} user=> (create-color-rect 249 1 2) {:color 249, :height 1, :width 2}
嵌套结构是可能的并且有时是期望的.但是,看起来你正在尝试做一些不同的事情:看起来你正试图使用结构类型的继承而不是组合.也就是说,在表单2中,您正在创建一个包含 rect 的color-rect,但是您正在尝试构造一个实例,就好像它是一个rect.表单1的工作原理是因为你从一个预先存在的rect构造c-rect1,这是使用组合的正确方法.
快速搜索Clojure组或仅在Web上进行快速搜索可以使您对组合和继承之间的区别进行良好描述.在Clojure中,组合或鸭子打字(再次参见Google)几乎总是优先于继承.
编辑:
回答你的问题#3:使用 - >提取嵌套结构中的数据的替代方法,正如Brian Carper在他的回答中所描述的那样,与其兄弟姐妹关联和更新一起进入:
例如:
(def cr {:rect {:height 1, :width 2}, :color :blue}) (get-in cr [:rect :width]) ;; => 2 (assoc-in cr [:rect :height] 7) ;; => {:rect {:height 7, :width 2}, :color :blue} (update-in cr [:rect :width] * 2) ;; => {:rect {:height 1, :width 4}, :color :blue} (assoc-in cr [:a :new :deeply :nested :field] 123) ;; => {:a {:new {:deeply {:nested {:field 123}}}}, ;; :rect {:height 1, :width 2}, :color :blue}
如果给它一个与之关联的键,则可以使struct成为另一个struct的值.你可以这样做.
(您可以通过->
一些语法糖轻松访问任意嵌套的哈希/结构的内容.)
(defstruct rect :height :width) (defstruct color-rect :rect :color) (def cr (struct color-rect (struct rect 1 2) :blue)) ;; => {:rect {:height 1, :width 2}, :color :blue} (:color cr) ;; => :blue (:width (:rect cr)) ;; => 2 (-> cr :color) ;; => :blue (-> cr :rect :width) ;; => 2