Alex--
The reason I'm starting with macros is that they're the
high-risk/less-understood part of this; the rest is more or less
straightforward, so I want to get a vertical slice working as soon as
possible and expand from there.
1. Start with data - what are the entities (bits? gates?), and how do you
> represent them? It's ok (actually better) for these to be verbose. Plan for
> extension (maps are open, which is why they're so common in representing
> data in Clojure).
>
Mostly done, as above--gates as keywords (with optional parameters), bits
as integers, operations as a sequence of gate and bit, so (:H 1) or (:CNOT
1 2) or ((:RX (/ pi 2)) 3). Honestly if I could just output a sequence of
those in the end, I'm Ok with that; I could scan that for the highest-index
bit and know that's how much I'd need. Yes, there are extra fun things to
add for representation and such, but that's the bare-bone version that
would get the job done.
> 2. Create functions that manipulate that take and return that data.
> 3. Decide what you actually want to write to capture the domain operations
> - how do you represent these in "function-like" forms.
>
Right, and as above I'd like the gates represented as functions, so (H 1)
would be represented as (:H 1), and you could do (map (partial CNOT 1) [2 3
4]) to output [(:CNOT 1 2) (:CNOT 1 3) (:CNOT 1 4)].
> 4. Write macros that translate #3 into #2 using #1.
>
Aaaand this is where I falter, in both Clojure and Hy. We'll leave Hy
aside, but in Clojure if I just do something like
(defmacro defgate [gate nbits]
(cond
(= nbits 1)
`(do (defn ~gate [bit#]
(list ~(keyword gate) bit#))
... similar for 2-bit, 3-bit gates, and a similar thing for parameterized
gates)
I can happily do something like
(defn bellpair [b1 b2]
(H b1)
(CNOT b1 b2))
And (bellpair 1 2) will of course just give me (CNOT b1 b2) because clojure
just returns the last thing in a sequence. Okay, there are ways to do this
and trivially get that result ("make the whole thing a vector!" ie (defn
bellpair [b1 b2] [(H b1...) and wrap that in a macro, but that runs into
trouble if trivially done when mixed with other Clojure code.
My best success so far has been something like
(def code-atom (atom []))
(defn emit [op] (swap! code-atom conj op))
(defmacro defgate [gate nbits]
(cond
(= nbits 1)
`(do (defn ~gate [bit#] (emit (list ~(keyword gate) bit#) ...
...
(defmacro qcomp [form]
`(do
(reset! code-atom [])
(eval ~form)
@code-atom))
But this is a problem because I don't like the stateful "need an atom"
implementation, and also we get issues like (qcomp [(H 1) (CNOT 1 2)]) work
fine, but (qcomp (map H [1 2 3])) fails with ArityException.
So it's not clear to me the prettiest way to go with this translation from
"functional form" to "data structure". The "emit" solution just seems
ugly, but I also don't want to walk a structure representing the code tree
and selectively pick out operations and manually expand partial function
applications, so I was wondering what suggestions anyone would have.
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/clojure/6cf8eb90-8cee-4a55-9a92-71b2163fcad6%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.