Skip to main content

[clojure] update map với cond->

Kiểu dữ liệu map trong clojure tương tự dict trong Python. Do Clojure mọi kiểu dữ liệu đều là immutable, nên mọi thao tác với map đều trả về 1 map mới. Để update 1 map dựa theo điều kiện sẽ khá phức tạp cho đến khi dùng cond-> macro. Ví dụ code Python tương ứng

options = {"max-keys": 100}

if 1 == 1:
    options["next-token"] = "abcd"
if 1 != 1:
    print("won't run")
if 5 > 3:
    options["other-op"] = "hehe"

def call_api(url, options):
    print(url, options)

call_api("https://url", options)
# https://url {'max-keys': 100, 'next-token': 'abcd', 'other-op': 'hehe'}

Macro cond-> nhận vào các cặp điều kiện - function để chạy khi điều kiện đúng, sử dụng để update dict:

(def init-options {:max-keys 100})
(def options (cond->
                 options
               (= 1 1) (assoc :next-token "abcd")
               (not= 1 1) (prn "won't run")
               (> 5 3) (assoc :other-op "hehe")))

(defn call-api [url options]
  (println "calling " url "with options: " options))

(call-api "https://url" options)
;; calling  https://url with options:  {:max-keys 100, :next-token abcd, :other-op hehe}

Đầu vào đầu tiên của cond-> là giá trị ban đầu options, theo sau là các cặp điều kiện:

nếu (= 1 1) thì gọi (assoc optíons :next-token "abcd") để thêm cặp key-value vào map options, kết quả này lại được gán tiếp làm đầu vào cho function (prn KETQUA "wont'run"), nhưng điều kiện (not= 1 1) là false nên function không được chạy, và tiếp tục...

Toàn bộ phần (cond-> ...) có thể đưa trực tiếp vào trong (call-api ):


(defn call-api [url options]
  (println "calling " url "with options: " options))

(call-api "https://url"
          (cond->
            {:max-keys 100}
            (= 1 1) (assoc :next-token "abcd")
            (not= 1 1) (prn "won't run")
            (> 5 3) (assoc :other-op "hehe")))

Code Python liệu có thể viết trong 1 dòng như vậy?

Ứng dụng

Khi option được gọi sẽ thay đổi theo điều kiện, ví dụ gọi API khi cần paginate sang trang, dùng cond-> để update options gọi trang tiếp theo.

(def next-page-token "XYZ")
(call-api "https://url"
          (cond-> 
            init-options 
            (some? next-page-token) (assoc :next-page-token next-page-token)))

Source

Trong REPL

user=>
(source cond->)
(defmacro cond->
  "Takes an expression and a set of test/form pairs. Threads expr (via ->)
  through each form for which the corresponding test
  expression is true. Note that, unlike cond branching, cond-> threading does
  not short circuit after the first true test expression."
  {:added "1.5"}
  [expr & clauses]
  (assert (even? (count clauses)))
  (let [g (gensym)
        steps (map (fn [[test step]] `(if ~test (-> ~g ~step) ~g))
                   (partition 2 clauses))]
    `(let [~g ~expr
           ~@(interleave (repeat g) (butlast steps))]
       ~(if (empty? steps)
          g
          (last steps)))))
nil

Kết luận

cond-> macro giúp viết code update kiểu dữ liệu theo các điều kiện một cách sạch đẹp hơn.

Hết.

HVN at https://pymi.vn and https://www.familug.org.

Ủng hộ tác giả 🍺

Comments

Popular posts from this blog

Tài liệu và hướng dẫn học Python

Để tiết kiệm thời gian, tốt nhất là đi học PyMI Updated: 130617 Sau đây là các tài liệu khuyên dùng: Vì nhiều lý do, nên học python2.7 tại thời điểm hiện tại (giờ là tháng 6/2013 - muốn biết tại sao thì tự tìm hiểu) python 3.5+ (giờ là tháng 2/2017) Chuẩn bị: 1. biết bật tắt máy 2. biết cài python 3. tập gõ 10 ngón - gõ 2 ngón hay 1 ngón cũng không sao, nhưng 10 ngón là cách dễ nhất để gõ nhanh nhất. Tài liệu - Nên dùng tài liệu tại trang chủ của Python làm chính, tham khảo thêm các tài liệu khác tại http://www.familug.org/2016/12/free-ebook.html Căn bản, mới học 1.1 Python PyMI.vn https://pymi.vn/tutorial/ 1.2. Python offical tutorial kết hợp làm bài tập trên HackerRank  (đề bài bằng tiếng Anh, nhưng Google translate 1 lúc cũng ra vì có nhiều ví dụ mẫu đi kèm). Học viên của Pymi.vn có rất nhiều học viên đã tự học với Learn Python the hard way nhưng chưa thấy ai thành công cả. Hai link dưới nên đọc sau khi đã nắm được những phần cơ bản của ngôn ngữ pytho...

The PyMiers

New FAMILUG