I’m about to suggest a simple solution to the problem of
From this list, it’s more or less evident why one might need this. But I’ll explain my context anyway:
Biological computations are fun:
So I ran one computation piece that took several hours. It wasn’t nice waiting for so long. (Even though I got some delicious cherry ice cream while waiting for it.) I’ve sworn to optimize it, or otherwise make it bearable to debug.
There was this one function,
It wasn’t enough.
I needed to somehow avoid the long-running computation altogether.
And just get the result.
I needed to pre-compute the results of CD(mph-em) and plug them into the program.
But what if it’s too deep into the program and I can’t feasibly pass anything from outside?
Lisps have a long tradition of dynamic vs. lexical binding wars.
Lexical bindings won, but there are uses for dynamic bindings.
Like temporary procedure/value overriding!
So I reached for Scheme’s take on dynamic bindings,
SRFI-39 Parameter objects
and came up with this macro:
So now I can
I was unsure whether this post should’ve been written altogether.
It’s quite obvious, right?
But it might be just my knowledge bias, so here goes nothing!
Tell me whether it’s obvious or not, in the feedback form below ↓
And hey, give this macro a go!
SRFI 39 is the only dependency and
is pretty well supported,
so no trouble in trying!
Memoization / caching.
The Solution: Parameterize
;; Define a NAMEd procedure and PARAMETER-NAMEd parameter
;; variable. Proceeds with running BODY with ARGS when PARAMETER-NAMEd
;; variable is #false. When PARAMETER-NAME is `parameterize'd to a new
;; procedure, call this procedure on ARGS instead. Useful to override
;; a procedure (like replacing the results for testing or providing
;; shortcut data for long-running computation.)
(define-syntax define-parameterized
(syntax-rules ()
((_ ((name parameter-name) . args) body ...)
(begin
(define parameter-name (make-parameter #f))
(define (name . rest)
(apply (or (parameter-name)
(lambda args body ...))
rest))))
((_ (name . args) body ...)
(define (name . args) body ...))
((_ name value)
(define name (make-parameter value)))))
(define-parameterized ((mph-em %mph-em) reml? eval x y vg ve b)
#|...|#)
(parameterize ((%mph-em (lambda args (mtx:alloc #(#|...|#)))))
(code-calling-mph-em))
;; Or, if you only need it to fire once
(parameterize ((%mph-em (lambda args
(%mph-em #f)
(mtx:alloc #(#|...|#)))))
(code-calling-mph-em))