Added cond function to Userlib

Added the cond function to Userlib, also added the associated tests
and documentation.
This commit is contained in:
dariof4 2023-06-13 00:18:11 +02:00
parent fb724ccee4
commit bd23198009
3 changed files with 68 additions and 1 deletions

View file

@ -126,6 +126,29 @@ Example:
(eq? (some-big-calculation) expected-result))
#+END_SRC
*** Cond
*Cond* is a function defined in the *Userlib* that acts as syntax sugar for nested *if form*s.
Given a list of pairs consisting of a condition and a form to execute *cond* will iterate trough the list evaluating the conditions in order, Upon encountering a condition that evaluates to ~true~ the corresponding form will be evaluated and its result returned, thus halting the loop so no further forms are evaluated.
If no conditions evaluate to true then *cond* won't execute anything
The argument to *cond* must be given using *quote*, otherwise it will be evaluated before being passed to *cond*, thus making it not work.
Example:
#+BEGIN_SRC lisp
(let ((list (1 2 3 4)))
(cond (q
(((gt? (car list) 2) (echo "The first number of this list is greater than 2")) ;; The first condition returns false so this expression won't be evaluated
((gt? (len list) 3) (echo "This list's length is greater than 3" )) ;; Since the second condition returns true this form will be evaluated and its result will be returned
(true (echo "This list is rather unremarkable")))))) ;; This form will be evaluated if none of the previous conditions return true
;; This is what the equivalent if form would look like
(let ((list (1 2 3 4)))
(if (gt? (car list) 2)
(echo "The first number of this list is greater than 2")
(if (gt? (len list) 3)
(echo "This list's length is greater than 3")
(echo "This list is rather unremarkable"))))
#+END_SRC
*** Not quite control flow
Several other functions use lazy evaluation of their arguments. The below list is non-exhaustive:
- toggle
@ -274,7 +297,7 @@ The following table is up to date as of Relish 0.3.0. For latest information try
|----------------+---------------+----------------+---------+--------+-----------+-----------+-----------+--------|
| | set? | fg | dq | div | concat | or | get-paths | |
|----------------+---------------+----------------+---------+--------+-----------+-----------+-----------+--------|
| | | | pop | gte? | string | | | |
| | | | pop | gte? | string | | cond | |
|----------------+---------------+----------------+---------+--------+-----------+-----------+-----------+--------|
| | | | | int | | | | |
|----------------+---------------+----------------+---------+--------+-----------+-----------+-----------+--------|

View file

@ -55,6 +55,36 @@
(adder (lambda (x y) (add x y))))
(eq? (reduce adder list) (add 1 2 3)))))
('cond evaluates the first branch that returns true'
(quote
(let ((switch-one false)
(switch-two false)
(switch-three false))
(cond (q
((false (toggle switch-one))
(true (toggle switch-two))
(true (toggle switch-three)))))
(and (not switch-one) switch-two (not switch-three)))))
('cond doesnt do anything if all the branches are false'
(quote
(let ((switch-one false)
(switch-two false)
(switch-three false))
(cond (q
((false (toggle switch-one))
(false (toggle switch-two))
(false (toggle switch-three)))))
(and (not switch-one) (not switch-two) (not switch-three)))))
('cond returns the result of the branch that is evaluated'
(quote
(let ((variable false))
(set (q variable)
(cond (q
((true true)))))
variable)))
('contains? finds elem in list'
(quote
(contains? (1 2 3) 1)))

View file

@ -84,6 +84,20 @@ this will continue iuntil the list is exhausted.'
(set (q list-iter) (pop remaining)))))
result))
(def cond
'Takes one argument: a list of pairs consisting of a form returning a bool and a form to execute
The function iterates over the list checking if the first form of a pair evaluates to true, in which
case it will execute the second form of the pair, returning its result, and stop the loop.'
(list)
(let ((iter list))
(while (gt? (len iter) 0)
(let ((current (car iter))
(remaining (pop iter)))
(if (eval (car current))
(car (pop ((set (q iter) ())
(eval (cdr current)))))
(set (q iter) (cdr remaining)))))))
(def contains?
'Takes two arguments: a list and an element.
Returns true if the list contains the element.'