From 7a13d24e6f802f0d87fc112ea5126da1e972af7c Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Thu, 5 Sep 2019 13:11:53 -0500 Subject: [PATCH] Add get-in, update-in, and freeze to core. --- CHANGELOG.md | 2 +- src/boot/boot.janet | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ffe550cb..7568dd89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog All notable changes to this project will be documented in this file. -## 1.3.0 - 2019-09-04 +## 1.3.0 - 2019-09-05 - Add `jpm run rule` and `jpm rules` to jpm to improve utility and discoverability of jpm. - Remove `cook` module and move `path` module to https://github.com/janet-lang/path.git. The functionality in `cook` is now bundled directly in the `jpm` script. diff --git a/src/boot/boot.janet b/src/boot/boot.janet index 21ad384e..07c63071 100644 --- a/src/boot/boot.janet +++ b/src/boot/boot.janet @@ -952,6 +952,35 @@ (put res (get keys i) (get vals i))) res) +(defn get-in + "Access a value in a nested data structure. Looks into the data structure via + a sequence of keys." + [ds ks &opt dflt] + (var d ds) + (loop [k :in ks :while d] (set d (get d k))) + (or d dflt)) + +(defn update-in + "Access a value in a nested data structure. Looks into the data structure via + a sequence of keys. Missing data structures will be replaced with tables. Returns + the modified, original data structure." + [ds ks f & args] + (var d ds) + (def len (length ks)) + (if (< len 1) (error "expected at least 1 key in ks")) + (for i 0 (- len 1) + (def k (get ks i)) + (def v (get d k)) + (if (= nil v) + (let [newv (table)] + (put d k newv) + (set d newv)) + (set d v))) + (def last-key (last ks)) + (def last-val (get d last-key)) + (put d last-key (f last-val ;args)) + ds) + (defn update "Accepts a key argument and passes its associated value to a function. The key is the re-associated to the function's return value. Returns the updated @@ -1444,6 +1473,21 @@ [x y] (not (deep-not= x y))) +(defn freeze + "Freeze an object (make it immutable) and do a deep copy, making + child values also immutable. Closures, fibers, and abstract types + will not be recursively frozen, but all other types will." + [x] + (case (type x) + :array (tuple/slice (map freeze x)) + :tuple (tuple/slice (map freeze x)) + :table (if-let [p (table/getproto x)] + (freeze (merge (table/clone p) x)) + (struct ;(map freeze (kvs x)))) + :struct (struct ;(map freeze (kvs x))) + :buffer (string x) + x)) + (defn macex "Expand macros completely. on-binding is an optional callback whenever a normal symbolic binding