![](/img/trans.png)
[英]Is assignment with "let" not against the idea of functional programming in Clojure
[英]Conditional “assignment” in functional programming
我正在編寫沒有副作用的程序,但是我的代碼不太可讀。 考慮以下代碼:
(let [csv_data (if header_row (cons header_row data_rows) data_rows)]
)
我正在嘗試在代碼塊中使用csv_data
。 有沒有一種以header_row
為條件的干凈方法? 我看過if-let
,但看不到這有什么幫助。
我也遇到了類似的情況,即使用功能性for循環將結果綁定到局部變量,並且代碼看起來像一堆表達式。
在很多情況下,我真的必須創建一個單獨的輔助函數嗎? 我在這里想念什么?
使用cond->>
宏
(let [csv_data (cond->> data_rows
header_row (cons header-row)]
)
它的工作方式類似於常規的->>
宏,但是在每個線程形式之前必須放置一個測試表達式,以確定是否將使用線程形式。
還有cond->
。 在此處閱讀有關線程宏的更多信息: 官方線程宏指南
首先,請勿使用下划線,而應使用破折號。
第二,輔助功能很少沒有錯。 畢竟,這似乎是處理您的特定數據格式的要求。
第三,如果您可以更改數據,以便跳過那些決定,並對所有極端情況進行統一表示,那就更好了。 標題行包含另一種數據(列名?),因此您可能希望將它們分開:
(let [csv {:header header :rows rows}]
...)
或者,也許在某些時候,“頁眉”和“行”可以是同一類型:行序列。 然后,您可以直接連接它們。 ensure-x
習慣用法是標准化數據的一種非常常用的方法:
(defn ensure-list [data]
(and data (list data)))
例如:
user=> (ensure-list "something")
("something")
user=> (ensure-list ())
(())
user=> (ensure-list nil)
nil
因此:
(let [csv (concat (ensure-list header) rows)]
...)
我會提出一個實用程序宏。 像這樣:
(defmacro update-when [check val-to-update f & params]
`(if-let [x# ~check]
(~f x# ~val-to-update ~@params)
~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]
它非常通用,可以讓您完成更復雜的任務,而不僅僅是簡單的調整。 例如,如果要檢查是否為真,您想反轉一些列,並連接另一個列表...
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))
在考慮了命名空間中單行幫助函數的“成本”之后,我想出了一個局部函數:
(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>
...
)
除非有人能提出一種更優雅的處理方式,否則我將以此為答案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.