1
votes

I am using a function that takes arguments as follows: (test-function '((gate 1) (gate 3) (gate 2)))

The list argument can contain any number of elements where each element is of the form (gate x) where x can be an integer from 0 to 8. I have a function, generate-gate-list, that generates lists of random length (up to 10) and content, although they are ALWAYS of the form above.

Example output of generate-gate-list: ((gate 2)), (()), ((gate 1) (gate 6)), etc.

I would like to be able to nest generate-gate-list inside test-function so that I can test a bunch of randomly generated lists without generating them all beforehand. In other words, I'd like something like this: (test-function '(generate-gate-list)) except where generate-gate-list has been evaluated. I've tried some sort of macro syntax-quote and unquoting, but that leads to resolved variables, like (user/gate 3) which screws up test-function. Here's my generate-gate-list code:

(defn generate-gate-list []
  (map symbol (repeatedly (rand-int 10) #(random-gate))))

random-gate outputs a gate element as a string, i.e "(gate 3)" or "(gate 2)".

So in short, I'd like (test-function (something-here (generate-gate-list))) or (test-function (modified-generate-gate-list)) to be equivalent to (test-function '((gate 1) (gate 4) (gate 2))) or some other arbitrary output of generate-gate-list. Thanks!

1
Is gate a function? If so, what does it do?Thumbnail
gate is a function, but I can't modify it.user3225710

1 Answers

7
votes

Quoting Produces Literal Lists

I believe your confusion is thinking that quoting is the only way to produce a list. While quoting can produce a literal list as in '((gate 1) (gate 2)), as you've likely discovered, nothing inside the list gets evaluated. Therefore, you can't produce a random list in this fashion, as your random variable will not be evaluated.

Symbol Produces Only Symbols

Invoking symbol on a text representation of a list "(gate 1)" as you are doing in your generate-gate-list function, does not work. It produces a symbol that looks like a list, not a list.

user=> (type (symbol "(gate 1)"))
clojure.lang.Symbol

Lists are created with list

If you want evaluation to occur, i.e. to populate your lists with variables, use the list function.

user=> (list 'gate 1)
(gate 1)

user=> (list 'gate (rand-int 10))
(gate 2)

Example

Not knowing what your test-function is, let's just do this

(defn test-function 
  [gate-list]
  "Turn a list of (gate n) pairs into a list of gate numbers" 
  (map second gate-list))

user=> (test-function '((gate 1) (gate 2)))
(1 2)

(defn generate-gate-list []
  (repeatedly (rand-int 10) #(list 'gate (rand-int 10))))

user=> (def a-random-list (generate-gate-list))
#'user/a-random-list

user=> a-random-list
((gate 2) (gate 5) (gate 2) (gate 8) (gate 4))

user=> (test-function a-random-list)
(2 5 2 8 4)