2017-01-10 4 views
1

私は副作用を持たないものをプログラミングしていますが、私のコードはあまり読みにくくありません。 次のコードを考えてみましょう:私は、コードのブロックでcsv_dataを使用しようとしている機能プログラミングにおける条件付きの "代入"

(let [csv_data (if header_row (cons header_row data_rows) data_rows)] 
) 

header_rowが存在する場合のクリーンなコンディショニング方法は何ですか?私はif-letを見てきましたが、ここでどのように役立つか分かりませんでした。

私は機能的なforループで同様の状況に遭遇しました。私はローカル変数に結果をバインドしています。コードは表現の山のように見えます。

多くの場合、別のヘルパー関数を作成する必要がありますか? 私はここで何が欠けていますか?

+0

私の答えは間違っていたので、その間に削除しました。 – Thumbnail

+0

さて、小さな間違いがあったと思いますが、そうでなければ完全に有効な答えでした。 – m33lky

答えて

2

まず、アンダースコアを使用せず、ダッシュを使用します。

第2に、小さなヘルパー機能に間違いはありません。結局のところ、これはあなたの特定のデータ形式を処理するための要件と思われます。

第3に、データを変更してこれらの決定をスキップし、すべてのコーナーケースを一様に表現できる場合は、これがさらに優れています。 (?カラム名)ヘッダー行は、データの異なる種類が含まれているので、あなたは別のそれらを維持することを好むかもしれない:

(let [csv {:header header :rows rows}] 
    ...) 

または多分あなたは、「ヘッダ」と「行」を持つことができ、いくつかの点で同じであることタイプ:行のシーケンス。次に、それらを直接連結することができます。の "コスト" について考えた後

(let [csv (concat (ensure-list header) rows)] 
    ...) 
+0

1.なぜClojureがダッシュを好むのかという歴史的な理由はありますか? 2.データのエクスポートを行っているので、すべてをマージしてlibに渡す必要があります。 – m33lky

+0

* 2。 – m33lky

+1

@ m33lky(1)ダッシュで区切られたシンボルはLispから来ます。これはあなたが他の言語で見つけることができるような大会です。 (2)ある時点では、「ヘッダ」と「行」が同じタイプになっている可能性があります。次に、それを直接連結することができます。私は問題が他のところでプッシュすることに同意します。 – coredump

-1

:たとえば

(defn ensure-list [data] 
    (and data (list data))) 

:これ

user=> (ensure-list "something") 
("something") 
user=> (ensure-list()) 
(()) 
user=> (ensure-list nil) 
nil 

とを ensure-xイディオムは、あなたのデータを正規化するための非常に一般的な方法です名前空間内の1行ヘルパー関数私は代わりにローカル関数を思いついた:

(let [merge_header_fn (fn [header_row data_rows] 
          (if header_row 
          (cons header_row data_rows) 
          data_rows)) 
     csv_data (merge_header_fn header_row data_rows) ] 
    ... 
    <use csv_data> 
    ... 
) 

誰かがこれをよりうまく処理する方法を提案できない限り、私はこれを答えとして保持します。

+0

私はここで改善が見られない、インラインバージョンはより読みやすいIMHOです。また、あなたが話している「コスト」は何ですか?古い参照ですが、関連性があります:https://groups.google.com/forum/message/raw?msg=comp.lang.lisp/9SKZ5YJUmBg/Fj05OZQomzIJ – coredump

+0

1行に多すぎることがあります。構造の欠如もあります。 – m33lky

+0

ローカルコンテキストの外で使用されない場合、私はしばしばこのようなローカルヘルパー関数を作っています(読みやすいように書式を少し変更しました)。 'let'式のローカルなのか、' def'式の最上位なのかにかかわらず、どちらか一方の "コスト"はありません。いつものように、コードをシンプルに、明白に、正しいものにすることは、他の心配よりも重要です。 –

1

私はユーティリティマクロを提案します。

(defmacro update-when [check val-to-update f & params] 
    `(if-let [x# ~check] 
    (~f x# ~val-to-update [email protected]) 
    ~val-to-update)) 

user> (let [header-row :header 
      data-rows [:data1 :data2]] 
     (let [csv-data (update-when header-row data-rows cons)] 
      csv-data)) 
;;=> (:header :data1 :data2) 

user> (let [header-row nil 
      data-rows [:data1 :data2]] 
     (let [csv-data (update-when header-row data-rows cons)] 
      csv-data)) 
;;=> [:data1 :data2] 

非常に普遍的なもので、複雑な作業を実行してから単純なコンサインメントを行うことができます。たとえば、チェックが真実であれば、いくつかのcollを元に戻し、別のリストを連結したいとします。

user> (let [header-row :header 
      data-rows [:data1 :data2]] 
     (let [csv-data (update-when header-row data-rows 
            (fn [h d & params] (apply concat (reverse d) params)) 
            [1 2 3] ['a 'b 'c])] 
      csv-data)) 

;;=> (:data2 :data1 1 2 3 a b c) 

更新 @amalloyで気づいたように、このマクロが機能する必要があります:

(defn update-when [check val-to-update f & params] 
    (if check 
    (apply f check val-to-update params) 
    val-to-update)) 
6

は、それが通常の->>マクロのように動作しますcond->>マクロ

(let [csv_data (cond->> data_rows 
       header_row (cons header-row)] 
    ) 

を使用して、しかし、各スレッド形式の前に、そのスレッド形式gフォームが使用されます。

cond->もあります。スレッドマクロの詳細はこちらOfficial threading macros guide

+0

これは慣用的な高度なClojureであることがわかりますが、私はそれを読むのが少し難しいと感じています。セマンティクスにはかなりの負荷がかかります。「その親族とは違って、some->またはcond-> testはfalseまたはnilと評価されても、評価を短絡しません」。また、ここに投稿されたcond->に関する回答があり、間違いがありました。私はそれを認知負荷に帰する。私はマクロの価値を理解していますが、ここでは私にとっては重いと感じています。 – m33lky

+1

@ m33lky短絡は問題に影響しません。つまり、複数のテスト/フォームのペアがある場合、1つの偽テストは他のペアに影響しません。これは、決して「重い」マクロや高度なClojureではありません。それはかなり単純に読んでいます:header_rowがある場合はdata_rowsをとり、header_rowを受け入れます。もちろん、マクロを読むためにはそのマクロの構文を学ばなければなりません。 case、cond、defnなどのマクロを考えてみましょう。マクロは学習する構文です。 –

+0

私はそれが高度なClojureプログラマのためだと言っていました。私は個人的にこの特定のマクロを使用したことはありません。この新しい機能を習得するのは簡単ですが、if/condのようなより伝統的な構造と同じスピードと信頼性でこのようなロジックを「読み込む」ためには、経験が必要だと思います。あなたはcond - >>がcondよりも重いことに同意しますか?ユースケースが異なるため、これはちょっと不公平な比較です。 – m33lky

関連する問題