Использование канала в case

(let [a (clojure.core.async/chan)]
  (case a
    a :foo
    :bar))
#=> :bar

Я бы ожидал :foo здесь. Что я делаю не так?

С другой стороны, (condp = chan ...) выполняет свою работу.

PS:

В основном я пытаюсь сделать следующее:

(require '[clojure.core.async :as a])
(let [chan1 (a/chan 10)
      chan2 (a/chan 10)]
  (a/>!! chan1 true)
  (let [[v c] (a/alts!! [chan1 chan2])]
    (case c
      chan1 :chan1
      chan2 :chan2
      :niether)))
#=> :neither

person fl00r    schedule 06.03.2017    source источник
comment
Никогда не читайте источник. ;) Просто прочитайте документы (см. ниже).   -  person Alan Thompson    schedule 07.03.2017
comment
@AlanThompson Удаление. Я пытался что-то придумать во время остановки автобуса. Очевидно, это не сработало. И мне нравится читать основной источник! Там много интересного, хотя многое запутано.   -  person Carcigenicate    schedule 07.03.2017


Ответы (2)


В документации для case есть ответ

Тест-константы не оцениваются. Они должны быть литералами времени компиляции и не должны заключаться в кавычки.

Правильное решение - использовать cond:

(let [chan1 (ca/chan 10)
      chan2 (ca/chan 10)]
    (ca/>!! chan1 true)
    (let [[v c] (ca/alts!! [chan1 chan2])]
      (spyx (cond
              (= c chan1) :chan1
              (= c chan2) :chan2
              :else :neither))))

;=> :chan1
person Alan Thompson    schedule 06.03.2017
comment
(condp = c более лаконичен, я полагаю - person fl00r; 07.03.2017

Case использует неоцененные тестовые константы для левой части предложения. Простые символы, такие как chan1 здесь, будут соответствовать только символу с таким же именем, а не значению локальной привязки с этим именем; chan1 будет соответствовать 'chan1

person Joost Diepenmaat    schedule 06.03.2017