3

有一个返回字符序列的函数,我需要修改它以允许将元数据附加到某些字符(但不是全部)。Clojure 不支持原始类型的“with-meta”。因此,可能的选择是:

  • 返回 [character, metadata] 的向量序列;

    优点:简单,数据和元数据绑定在一起
    缺点:需要从向量中提取数据
     
  • 返回两个单独的序列,一个用于字符,一个用于元数据,如果调用者关心元数据,他会同时迭代它们;

    优点:调用者不必从每个流元素中提取数据,如果他愿意,可能会丢弃元序列
    缺点:需要一次迭代两个 seq,如果需要元数据,调用方会更复杂
     
  • 引入一些包含一个字符并允许将元附加到自身的记录包装器(Clojure 记录实现 IMeta);

    优点:数据和元数据绑定在一起
    缺点:需要从记录中提取数据
     
  • 你更好的选择。

哪种方法更好?

4

1 回答 1

1

使用矢量/地图序列,例如

({:char 'x' :meta <...>} {:char 'y' :meta <...>} {:char 'z' :meta <...>} ...)
; or
(['x' <...>] ['y' <...>] ['z' <...>] ...)

看起来对我来说是最好的选择,如果我有这样的任务,我会自己做。然后,例如,编写一个将此类序列转换回字符序列的函数非常简单:

(defn characters [s] (map :char s))
; or
(defn characters [s] (map first s))

使用解构绑定同时迭代字符和元数据也很容易:

(doseq [{:keys [char meta]} s] ...)
; or
(doseq [[char meta] s] ...)

使用什么(地图或矢量)主要取决于个人喜好。

IMO,使用记录及其IMeta界面不太好:我认为这种元数据主要用于与语言相关的代码(宏、代码预处理、语法扩展等),而不是用于域代码。当然,我在这个假设中可能是错误的。

并且使用两个并行序列是最糟糕的选择,因为它不像单个序列那样方便您的界面用户。使用我上面写的函数丢弃元数据非常简单,如果所有序列都是惰性的,它甚至不会影响性能。

于 2012-12-13T14:10:22.950 回答