Search code examples
javascriptclojureclojurescriptom

Om.next: apply vs directly passing children


In the Om.next wiki, there is example code like this (code listing at the bottom of the linked page):

(apply dom/ul nil
    (map person list))

Since dom/ul takes a variable number of arguments, what is the benefit of using apply vs this:

(dom/ul nil (map person list))

This second approach seems more analogous to passing an array as children in vanilla React, which is supported.

Actual question (response to comment): Is apply necessary? If so, why doesn't the latter approach work? If not, what benefit is gained from using apply like in the example?


Solution

  • The ClojureScript signature of dom/ul is apparently something like (defn ul [attrs & children] ...). Here children is a vararg. The caller can pass in 0 or more children. Therefore, the following invocations are valid:

    (dom/ul nil (person jack))
    (dom/ul nil (person jack) (person jill))
    (dom/ul nil)
    

    Now suppose you have a collection of elements that you'd like to wrap in a ul. The collection maybe comes from (map person list), which returns a sequence of elements. If ul is invoked like (dom/ul nil (map person list)), only a single child argument is passed to ul, and it is of the wrong type. Each child is expected to be an element, but a collection of element is passed in instead.

    apply to the rescue. The job of apply is deal with the situation where we have a collection of arguments, which must be passed in individually. So, (dom/ul nil (person jack) (person jill)) is equivalent to (apply dom/ul nil (map person [jack jill])). apply is necessary in this case to make sure the arguments are passed to ul as that function is expecting them. Skipping apply is not an option.