Skip to content

Commit

Permalink
Added "(while)" and "(if2)" macros.
Browse files Browse the repository at this point in the history
Macros are awesome!
  • Loading branch information
skx committed Sep 23, 2022
1 parent 1c67ad1 commit 380b38b
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 7 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Although this implementation is clearly derived from the [make a lisp](https://g
* Via a `:type` suffix. For example `(lambda (a:string b:number) ..`.
* Support for macros.
* See [mtest.lisp](mtest.lisp) for some simple tests/usage examples.
* The standard library uses macros, sparingly, for example to implement the `(while)` function.

Here's what optional parameters, inspired by Emacs, look like in practice:

Expand Down Expand Up @@ -193,7 +194,7 @@ We have a reasonable number of functions implemented, either in our golang core

Building upon those primitives we have a larger standard-library of functions written in Lisp such as:

* `abs`, `apply`, `append`, `filter`, `lower`, `map`, `min`, `max`, `nat`, `neg`, `now`, `nth`, `reduce`, `reverse`, `seq`, `upper`, etc.
* `abs`, `apply`, `append`, `filter`, `lower`, `map`, `min`, `max`, `nat`, `neg`, `now`, `nth`, `reduce`, `repeat`, `reverse`, `seq`, `upper`, `while`, etc.

Although the lists above should be up to date you can check the definitions to see what is currently available:

Expand Down Expand Up @@ -268,3 +269,5 @@ For longer runs add `-benchtime=30s`, or similar, to the command-line.
* Very helpful "inspiration" for writing primitives in Lisp.
* https://github.com/kanaka/mal/
* Make A Lisp, very helpful for the quoting, unquoting, and macro magic.
* http://soft.vub.ac.be/~pcostanz/documents/08/macros.pdf
* The source of the cute "while" macro, and a good read beyond that.
53 changes: 48 additions & 5 deletions stdlib/stdlib.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,57 @@


;;
;; if2 is a simple macro which allows you to run two actions if an
;; (if ..) test succeeds.
;;
;; This means you can write:
;;
;; (if2 true (print "1") (print "2"))
;;
;; Instead of having to use (begin), like so:
;;
;; (if true (begin (print "1") (print "2")))
;;
;; The downside here is that you don't get a negative branch, but running
;; two things is very common - see for example the "(while)" and "(repeat)"
;; macros later in this file.
;;
(define if2 (macro (pred one two)
`(if ~pred (begin ~one ~two))))


;;
;; Part of our while-implementation.
;; If the specified predicate is true, then run the body.
;;
;; NOTE: This recurses, so it will eventually explode the stack.
;;
;; NOTE: We use "if2" not "if".
;;
(define while-fun (lambda (predicate body)
(if2 (predicate)
(body)
(while-fun predicate body))))

;;
;; Now a macro to use the while-fun body as part of a while-function
;;
;; NOTE: We use "if2" not "if".
;;
(define while (macro (expression body)
(list 'while-fun
(list 'lambda '() expression)
(list 'lambda '() body))))


;; Setup a simple function to run a loop N times
;;
;; NOTE: We use "if2" not "if".
;;
(define repeat (lambda (n body)
(if (> n 0)
(begin
(body n)
(repeat (- n 1) body)
))))
(if2 (> n 0)
(body n)
(repeat (- n 1) body))))

;; A useful helper to apply a given function to each element of a list.
(define apply (lambda (lst:list fun:function)
Expand Down
13 changes: 12 additions & 1 deletion test.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,21 @@

;;
;; Use our "repeat" function, from the standard library, to run a block
;; N times. The number of the attempt is given as a parameter.
;; N/10 times. The number of the attempt is given as a parameter.
;;
(repeat 10 (lambda (n) (print "I'm in a loop %s" n)))

;;
;; Use our "while" function, from the standard library, to run a block
;; of code N/5 times.
;;
(let ((a 5))
(while (> a 0)
(begin
(print "(while) loop - iteration %s" a)
(set! a (- a 1) true))))


;; Define a function, `fact`, to calculate factorials.
(define fact (lambda (n)
(if (<= n 1)
Expand Down

0 comments on commit 380b38b

Please sign in to comment.