mirror of
https://github.com/janet-lang/janet
synced 2024-11-28 11:09:54 +00:00
Add with-vars
This helps for temporarily setting vars in a safe manner that is guaranteed not to leave vars in a bad state (assuming that a fiber does not emit debug or use signal and is never resumed).
This commit is contained in:
parent
25a9804d91
commit
6ceaf9d28d
@ -2,6 +2,7 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## Unreleased
|
||||
- Add `with-vars` macro.
|
||||
- Add the `quickbin` command to jpm.
|
||||
- Create shell.c when making the amlagamated source. This can be compiled with
|
||||
janet.c to make the janet interpreter.
|
||||
|
@ -909,6 +909,25 @@
|
||||
~(setdyn ,(bindings i) ,(bindings (+ i 1)))))
|
||||
~(,resume (,fiber/new (fn [] ,;dyn-forms ,;body) :p)))
|
||||
|
||||
(defmacro with-vars
|
||||
"Evaluates body with each var in vars temporarily bound. Similar signature to
|
||||
let, but each binding must be a var."
|
||||
[vars & body]
|
||||
(def len (length vars))
|
||||
(unless (even? len) (error "expected even number of argument to vars"))
|
||||
(def temp (seq [i :range [0 len 2]] (gensym)))
|
||||
(def saveold (seq [i :range [0 len 2]] ['def (temp (/ i 2)) (vars i)]))
|
||||
(def setnew (seq [i :range [0 len 2]] ['set (vars i) (vars (+ i 1))]))
|
||||
(def restoreold (seq [i :range [0 len 2]] ['set (vars i) (temp (/ i 2))]))
|
||||
(with-syms [ret f s]
|
||||
~(do
|
||||
,;saveold
|
||||
(def ,f (,fiber/new (fn [] ,;setnew ,;body) :ei))
|
||||
(def ,ret (,resume ,f))
|
||||
,;restoreold
|
||||
(if (= (,fiber/status ,f) :error) (,propagate ,ret ,f))
|
||||
,ret)))
|
||||
|
||||
(defn partial
|
||||
"Partial function application."
|
||||
[f & more]
|
||||
@ -928,7 +947,7 @@
|
||||
"Reverses the order of the elements in a given array or tuple and returns a new array."
|
||||
[t]
|
||||
(def len (length t))
|
||||
(var n (dec len))
|
||||
(var n (- len 1))
|
||||
(def reversed (array/new len))
|
||||
(while (>= n 0)
|
||||
(array/push reversed (get t n))
|
||||
|
@ -184,4 +184,10 @@
|
||||
|
||||
(assert (= (string '()) (string [])) "empty bracket tuple literal")
|
||||
|
||||
# with-vars
|
||||
(var abc 123)
|
||||
(assert (= 356 (with-vars [abc 456] (- abc 100))) "with-vars 1")
|
||||
(assert-error "with-vars 2" (with-vars [abc 456] (error :oops)))
|
||||
(assert (= abc 123) "with-vars 3")
|
||||
|
||||
(end-suite)
|
||||
|
Loading…
Reference in New Issue
Block a user