3

一連の文字を返す関数があるので、一部の文字(すべてではない)にメタデータを添付できるように変更する必要があります。Clojureは、プリミティブ型の「with-meta」をサポートしていません。したがって、可能なオプションは次のとおりです。

  • [文字、メタデータ]のベクトルのシーケンスを返します。

    長所:シンプルさ、データとメタデータが結びついている
    短所:ベクターからデータを抽出する必要がある
     
  • 1つは文字用でもう1つはメタデータ用の、2つの別々のシーケンスを返します。呼び出し元は、メタデータに関心がある場合、それらを同時に繰り返すことがほとんどです。

    長所:呼び出し元は各ストリーム要素からデータを抽出する必要がなく、必要に応じてメタシーケンスを
    破棄できます短所:両方のシーケンスを一度に繰り返す必要があり、メタデータが必要な場合は呼び出し側でより複雑になります
     
  • 1つの文字を含み、それ自体にメタをアタッチできるレコードラッパーを導入します(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インターフェイスの使用はそれほど良くありません。この種のメタデータは、ドメインコードではなく、主に言語関連のコード(マクロ、コード前処理、構文拡張など)を対象としていると思います。もちろん、私はこの仮定で間違っているかもしれません。

また、2つの並列シーケンスを使用することは、インターフェイスのユーザーにとって単一のシーケンスほど便利ではないため、最悪のオプションです。また、メタデータを破棄することは、上記で作成した関数を使用すると非常に簡単であり、すべてのシーケンスが遅延している場合でも、パフォーマンスに影響を与えることはありません。

于 2012-12-13T14:10:22.950 に答える