IMPORTANT: This question is motivated solely by my wanting to learn Common Lisp. Beyond this autodidactic goal, it has no ulterior practical purpose.
If, at my REPL1, I evaluate the following expression
CL-USER> (random-state-p
#S(random-state
:state #.(make-array 627
:element-type '(unsigned-byte 32)
:initial-element 7)))
...I get T
. In other words, the literal
#S(random-state
:state #.(make-array 627
:element-type '(unsigned-byte 32)
:initial-element 7))
...evaluates to a valid random-state
object.
So far so good.
Now, I try to define a function, silly-random-state
, so that the expression (silly-random-state 7)
will produce the same random-state
object as that produced by the literal above, like this:
(defun silly-random-state (some-int)
#S(random-state
:state #.(make-array 627
:element-type '(unsigned-byte 32)
:initial-element some-int)))
...but my REPL will have none of it! It won't even evaluate this defun
! It complains that some-int
is undefined2.
On further thought, I guess it makes sense that one cannot stick a variable inside a literal and expect the resulting expression to make sense... Maybe I need a macro for this?
So then I try to define a macro that, given an integer argument, will expand to such a random-state
object, like this:
(defmacro silly-random-state-macro (some-int)
`#S(random-state
:state #.(make-array 627
:element-type '(unsigned-byte 32)
:initial-element ,some-int)))
Again, my REPL will have none of it. The evaluation of the expression above fails with
Comma inside backquoted structure (not a list or general vector.)
Each of the two failures above leads to a corresponding question:
- how can I define a function
silly-random-state
that takes an integerSOME-INT
as argument, and returns therandom-state
equal to the one the REPL would produce if I gave it the expression below after replacingPLACEHOLDER
with the integerSOME-INT
?
#S(random-state
:state #.(make-array 627
:element-type '(unsigned-byte 32)
:initial-element PLACEHOLDER))
- how can I define a macro
silly-random-state-macro
such that(silly-random-state-macro some-int)
expands to a the samerandom-state
object described in (1)?
(To repeat, my motivation here is only to better understand what can and cannot be done with Common Lisp3.)
1 SBCL + SLIME/Emacs running on Darwin.
2 BTW, my REPL had never been so picky before! For example, it will evaluate something like (defun foo () undefined-nonsense)
. Granted, it does grouse a bit over the undefined variable in the body, but in the end it will evaluate the defun
.
3 In fact, I debated whether I should include [prng] among the tags for this question, since its topics are really literals, functions, and macros, and the role of CL's default PRNG in it is only incidental. I finally opted to keep this tag just in case the role of the PRNG in the question is less incidental than it seems to me.
EDIT: OK, I think I found a way to define the function I described in (1); it's not very elegant, but it works:
(defun silly-random-state (some-int)
(read-from-string
(format nil "#S(random-state :state #.(make-array 627 :element-type '(unsigned-byte 32) :initial-element ~A))" some-int)))
Aucun commentaire:
Enregistrer un commentaire