具有返回一个字符序列的功能,我需要对其进行修改以允许将元数据附加到某些字符(但不是全部)上。 Clojure不支持原始类型的'with-meta'。因此,可能的选项是:

  • 返回[字符,元数据]的 vector 序列;

    优点:简单性,数据和元数据 bundle 在一起
    缺点:需要从 vector 中提取数据
  • 返回两个单独的seq,一个用于字符,一个用于元数据,如果调用者关心元数据,则大多数调用者会同时进行迭代。

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

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

  • 哪种方法更好?

    最佳答案

    使用 vector /图序列,例如

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

    看起来对我来说是最好的选择,如果有这样的任务,那就是我自己要做的。然后,例如,编写一个将此类序列转换回char序列的函数非常简单:
    (defn characters [s] (map :char s))
    ; or
    (defn characters [s] (map first s))
    

    使用解构绑定(bind),同时遍历字符和元数据也非常容易:
    (doseq [{:keys [char meta]} s] ...)
    ; or
    (doseq [[char meta] s] ...)
    

    使用什么( map 或 vector )主要取决于个人喜好。

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

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

    10-04 21:21
    查看更多