Update: Now part of brev-separate.
This is something that is sometimes cozy:
(with-result
(print 1 2 (save 3) 4 5 6)
(print 7 8))
Prints 123456 and 78, returns 3
(define ht (make-hash-table))
(define (frobnicate x) `(my expensive computation ,x))
(with-result
(hash-table-set! ht 'key (save (frobnicate 'hi))))
Sets key in ht to the result of frobnicate ‘hi, and returns that result.
If you call save multiple times, it’ll overwrite the previous results and the expression will return the last evaluated call to save. This is sometimes useful.
Here’s the implementation:
(define-ir-syntax with-result
`(let* ((ret #f)
(,( inject 'save)
(lambda (val)
(set! ret val)
val)))
,@(cdr exp)
ret))
Using define-ir-syntax.
Putting it together with define-closure, we can make a memoizer.
(define-closure
(ht (make-hash-table))
((memoize f) . args)
(if (hash-table-exists? ht args)
(hash-table-ref ht args)
(with-result (hash-table-set! ht args (save (apply f args))))))
(define mlist (memoize list))
(mlist 1 2 3 4)