Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make list of not-nil entries

say I have a function like this:

(defn my-f [a & [b]]
   (if (nil? b)
      (my-other-f a)
      (my-other-f a b)))

This of course is a simplification. It's a wrapper function for another function - and in reality a is processed inside this function. If the optional argument b is not passed to my-f, it should also not be passed to my-other-f.

I was thinking of another way to achieve this:

(defn my-f [a & [b]]
   (apply my-other-f (make-list-of-not-nil-entries a b)))

Is there maybe a built-in function doing this job?


Example

Sometimes, being too abstract is confusing, so I'm providing the real case here. The following ClojureScript code works, it's purpose is obviously to try different browser-specific options in order to get a "webgl" context from an HTML canvas element.

(defn create-ctx [canvas & [options]]
  (some (if options
          #(.getContext canvas % (clj->js options))
          #(.getContext canvas %))
        ["webgl" "experimental-webgl" "webkit-3d" "moz-webgl"]))

The given Canvas element's method getContext awaits actually one argument, and another one which is optional. The above wrapper functions has the same arity.

I just wanted to see, if there is a quick way to avoid the explicit switch for the 1 and the 2 arity function call.

like image 486
Anton Harald Avatar asked Apr 14 '16 17:04

Anton Harald


1 Answers

I would argue that your first solution is much more readable and explicit about its intention. It will also have much better performance than the one with apply.

If you still want to go with apply, the shortest solution using clojure.core would be:

(remove nil? [a b]) 

Or

(keep identity [a b]) 

Or

(filter some? [a b]) 

I am not aware of any built in function which takes varargs and returns a seq of only non nil elements. You could create one:

(defn non-nils [& args] 
  (remove nil? args) 

Or use ignoring-nils from flatland.useful.fn.

like image 196
Piotrek Bzdyl Avatar answered Nov 12 '22 07:11

Piotrek Bzdyl