Fork me on GitHub
#core-async
<
2020-05-17
>
Ben Sless17:05:57

Hi all, is there a reason this snippet throws Could not resolve var: -has?

(macroexpand-1
 '(go
    (let [[v ch :as ret] (a/alts! [-has -insert])]
      ret)))

alexmiller17:05:53

What are -has and -insert here? They should be channels

Ben Sless17:05:24

They are. Taken from vectors of channels, like (has i) with has being (vec (repeatedly (+ 1 limit) chan)), and -insert is similarly defined. I drilled down into this trying to debug why I was takeing from nil in a much larger piece of code:

(defn rec-set
  [limit]
  (let [has (vec (repeatedly (+ 1 limit) chan))
        insert (vec (repeatedly (+ 1 limit) chan))
        s0 (chan)]
    (loop [i 0]
      (when (< i limit)
        (let [i+1 (inc i)
              -has (has i)
              +has (has i+1)
              -insert (insert i)
              +insert (insert i+1)]
          (go
            (let [n
                  (loop []
                    (a/alt!
                      -has ([_] (>! s0 false) (recur))
                      -insert ([v] v)))]
              (loop [n n]
                (a/alt!
                  -has
                  ([m]
                   (cond
                     (<= m n) (>! s0 (= m n))
                     (> m n)  (>! +has m))
                   (recur n))
                  -insert
                  ([m]
                   (cond
                     (< m n) (do (>! +insert n) (recur m))
                     (> m n) (do (>! +insert m) (recur n))
                     (= m n) (recur n)))))))
          (recur (inc i)))))
    {:has (has 1) :insert (insert 1) :s0 s0})) 
Still trying to find the error here

hiredman17:05:57

macroexpand-1 may just not not work on go macro calls with free variables (because the go macro is very complicated internally, even doing its own macro expansion)

hiredman17:05:26

Which is to say, symbol resolution errors typically occur later in the compilation process than macro expansion, so you can usually expand macros with free symbols just fine, but the go macro is a compiler in a macro, which means when macro expanding it you can get errors from later stages in the compilation process. Just a guess, I am not at a repl to test it out

Ben Sless18:05:57

damn, makes debugging the big form harder

hiredman18:05:19

If that is the case you just need to make the symbols not free

hiredman18:05:09

But I doubt macroexpand core async forms is ever going to make it easier to understand

Ben Sless18:05:15

That would be tricky because the error I'm getting is that I'm trying to take! from nil, meaning one of the alt s is borked

Ben Sless18:05:00

But if I just print all the -+has and -+insert chans non of them are nil

hiredman18:05:24

I would start by sticking asserts before each alt

Ben Sless18:05:47

That's an excellent idea

Ben Sless18:05:21

won't it throw in the executor pool, though?

hiredman18:05:31

That is fine

hiredman18:05:50

And I would double check that your error is actually coming from that code

hiredman18:05:08

I forget if vectors as functions behave like get or nth

hiredman18:05:40

Get returns nil for unkown indices, nth throws

hiredman18:05:30

So if vectors as functions act like get, you can replace with calling nth to get earlier errors to track things back closer to the source

Ben Sless18:05:57

I found the error

Ben Sless18:05:59

it's so silly

Ben Sless18:05:21

My error was in the api. The code is good

Ben Sless18:05:16

Thanks for giving it a look over 🙃

hiredman18:05:43

Looking over macro expanded go blocks is extremely tedious, and ideally only something to do if you are sure there is a bug in the go macro

Ben Sless18:05:13

Well, the bug was as it most often is, between the chair and the keyboard