Clojure:如何模拟向流中的字符添加元数据?

标签 clojure metadata

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

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

    优点:简单、数据和元数据捆绑在一起
    缺点:需要从向量中提取数据
  • 返回两个单独的序列,一个用于字符,一个用于元数据,调用者如果关心元数据,则大多数情况下会同时迭代这些序列;

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

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

哪种方法更好?

最佳答案

使用矢量/ map 序列,例如

({: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))

同时遍历字符和元数据也很容易使用解构绑定(bind):

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

使用什么( map 或矢量)主要是个人喜好问题。

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

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

关于Clojure:如何模拟向流中的字符添加元数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13860810/

相关文章:

Clojure:在 Erathosthene 筛中避免堆栈溢出?

java - 尝试加载资源时 clojure.lang.Compiler 中的 NPE

ffmpeg 元数据副本(全部)

ios - iTunes Connect 应用内购买定价未显示

swift - 无法将图片网址从 FirebaseStorage 下载到 FirebaseDatabase - Swift - 不再识别metadata.downloadURL()

clojure.core/or 部分函数适用于第一个参数,但不适用于第二个参数

clojure 排序总是返回一个列表

java - 如何从 Clojure 引用同一包中的 Java 类?

objective-c - 使用 AVFoundation 修改音频元数据

annotations - 如何访问 Dart 注释元数据