Создание списка функций в текущем контексте

#clojure #clojurescript

#clojure #clojurescript

Вопрос:

Я довольно новичок в языках Clojurescript и LISPy, поэтому, пожалуйста, извините мой императивный образ мышления.

Я использую Raphael.js чтобы нарисовать некоторые вещи. Это позволяет вам определить набор, поместить в него объекты (скажем, круг, прямоугольник и контур), а затем выполнить операцию, которая воздействует на все элементы (пример: поворот, который применяется ко всем).

Таким образом, мы можем иметь (где paper — это в основном элемент svg):

 (-> (.set paper) 
    (.push (.ellipse paper 10 10 10 10))
    (.push (.circle paper 10 10 10 10))
    (.transform (format "r%.2f" 180)))
  

Который создаст набор и будет использовать несколько вызовов к push , который возвращает набор каждый раз, в конечном итоге вызывая transform . Теперь, что, если я хочу создать список, скажем, circle объектов во время выполнения и добавить их в набор? В идеале я хотел бы иметь возможность заменить, скажем, строку 3 приведенного выше блока кода чем-то вроде (очень грубо — я совершенно не уверен в том, как обращаться с .push )

 (.push (map (fn [i] (.ellipse paper 10 (* i 10) 10 10)) (range 5)))
  

для того, чтобы создать 5 кругов, спускающихся по оси y. Чего я не могу понять с моим ограниченным пониманием Clojure, так это как сделать такую вещь довольно простым способом, не прибегая к doseq чему-либо еще. Я не хочу побочных эффектов. Я хотел бы каким-то образом создать список нажатий, а затем заставить их все объединиться в мой блок на месте. Возможно ли это? Где-то в моем мышлении может быть огромный недостаток, и я был бы действительно очень благодарен любому, кто может указать на это.

Большое спасибо.

Ответ №1:

Избежать побочных эффектов немного сложно, поскольку push очевидно, что это приводит к изменению набора. Один из способов избежать doseq — использовать reduce . Например:

 (def shapes [ (.circle paper 10 10 10 10) (.ellipse paper 10 10 10 10) ] )

(defn push-all [set shapes] 
  (reduce #(.push %1 %2) set shapes))

(-> (.set paper) 
    (push-all shapes)
    (.transform (format "r%.2f" 180)))
  

Комментарии:

1. Большое вам спасибо. Я пытался использовать reduce для выполнения этого в какой-то момент. Я немного ошибся, сказав, что хотел избежать побочных эффектов, поскольку вы правы, сказав, что .push это в любом случае изменяет состояние. К сожалению, у меня недостаточно репутации, чтобы поддержать вас, поэтому вместо этого я посылаю вам немного реальной кармы.