maybe this should go on the wiki, but a negator could be useful too. given a function, it returns a function which applies not to the result. And for example there is no need to define (elem?) and (not-elem?). Also useful for mapping, filtering, etc.
sketch:
Code: Select all
(define (negate fun)
(letex (fun fun)
(fn () (not (apply fun (args))))))
example:
Code: Select all
> (map number? '(1 2 3 "hi"))
(true true true nil)
> (map (negate number?) '( 1 2 3 "lol"))
(nil nil nil true)
EXTRA EDIT:
I've been playing around and after trying a lil bit to make an loop/iter macro for newLISP, I came to a better idea, I hope you like it!
It's the collector idea. In common lisp
(loop for e in lst collect (+ e 1))
does exactly what it seems to. It conses a all the elements in the list plus one. Identic to
(map (fn (e) (+ e 1) lst)
The cool thing about the loop macro is that you can mix thing a lil bit. Instead of iterating over a list you could iterate numbers. And write
(loop for e from 1 to 10 collect (+ e 1))
To do that you would have to use a sequence and map, build a list and throw it away, like this:
(map (fn (e) (+ e 1) (sequence 1 10))
But this way you have to replicate in sequence everything you could do with a normal for. And not to mention that besides collecting you can append, sum, etc. and you can insert ifs and then do filtering, everything with loop only
Now, instead of a overly complicated loop macro, I present you to the simple newLisp collector!
Code: Select all
(collector
(dolist (e lst)
(if (and (number? e) (> e 1))
(build (+ 1 e)))))
It does what it looks likes. Every call to build is macroexpanded to a call to (set), accumulating a list and then returning it.
for example, if lst would have been (1 2 3 "a b" k 13)) it would have evaluated to (3 4 14).
The cool thing here is that unlike map, you can iterate over anything.
Code: Select all
> [cmd]
(collector
(for (e 1 10)
(if (> e 3)
(build (+ 1 e)))))
[/cmd]
(5 6 7 8 9 10 11)
Now, the real thing here is that you can easily make you own builders.
(custom-builder) is a function that receives the base case and a function that receives the building value and the total count symbol, and returns a list of code so you can make you own builders. And (builder) is a simple macro that allows to make simple builders on-the-fly, instead of of the more general (custom-builder), it receives a function with is to be applied to the total and current value and the total is set to the value returned. E.G.
Code: Select all
> (builder * 1 (for (i 1 4) (build i)))
24
Maybe I'm reinventing the wheel, but it seems fun!
Oh, I almost forgot!
Code: Select all
(define-macro (collector)
(let (collector-list '())
(eval
(cons 'begin
(expand (args)
'((build
'(lambda (element)
(push element collector-list -1)))))))
collector-list))
(define (custom-builder)
(expand
'(let (building basecase)
(eval
(cons 'begin
(expand (args)
'((build
(fn (element)
(build-function element 'building)))))))
building)
(list (list 'build-function (args 0)) (list 'basecase (args 1)))))
(define-macro (builder fun base)
(letex (fun fun base base)
(eval (custom-builder
(fn (num total) (set total (fun num (eval total))))
base))))
(btw, I think they're not very hygenic and I'm not sure how nested builder works, besides maybe a "builder collector" would be good if I want to build on the outer collector, but that would be very rare I think.)