From bd23198009ae07e4eae8634c9c1a07d462c2b902 Mon Sep 17 00:00:00 2001 From: dariof4 Date: Tue, 13 Jun 2023 00:18:11 +0200 Subject: [PATCH] Added cond function to Userlib Added the cond function to Userlib, also added the associated tests and documentation. --- Writing.org | 25 ++++++++++++++++++++++++- snippets/userlib-tests.rls | 30 ++++++++++++++++++++++++++++++ snippets/userlib.rls | 14 ++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/Writing.org b/Writing.org index 578baea..18c193a 100644 --- a/Writing.org +++ b/Writing.org @@ -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 | | | | | |----------------+---------------+----------------+---------+--------+-----------+-----------+-----------+--------| diff --git a/snippets/userlib-tests.rls b/snippets/userlib-tests.rls index cb93c5d..93ed8f8 100644 --- a/snippets/userlib-tests.rls +++ b/snippets/userlib-tests.rls @@ -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))) diff --git a/snippets/userlib.rls b/snippets/userlib.rls index b038835..16d8a5f 100644 --- a/snippets/userlib.rls +++ b/snippets/userlib.rls @@ -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.'