Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> My (incomplete) set of personal rules:

> - use contains? instead of using sets as functions,

[snip]

> An example. To understand this piece of code you need to know that possible-states is a set:

      (when (possible-states state)
        ... )
> By contrast, to understand following code you don’t need any context:

      (when (contains? possible-states state)
        ... )
I disagree. In the first example, it's clear from context that possible-states is a function (to be precise, an object that implements IFn) that returns a truthy or falsy value depending on the value of state; the name possible-states suggests it's checking that the value of state is valid, according to some criteria.

To determine what those criteria are, you'd have to look at the definition of possible-states: but that would also be true even if you used the more verbose contains? construct.

By not using contains?, you also retain the option to replace possible-states with an actual function, should you later discover you need further validation or processing not possible with a simple set.

For example, if state is a text string, and you find out further down the line that sometimes it's in the wrong case or has unwanted leading or trailing white space, you can replace

    (def possible-states #{"foo" "bar" "baz"})
with

    (defn possible-states [state]
      (->> state
        clojure.string/trim
        clojure.string/lower-case
        #{"foo" "bar" "baz"}))
without needing to change code elsewhere.

Even if you don't feel that this flexibility is worth the ambiguity, contains? offers little comfort, as it can take many things other than a set:

    (contains? #{"foo"} "foo")     ; true
    (contains? {"foo" 1} "foo")    ; true  ("foo" is a key of the map)
    (contains? {:bar "foo"} "foo") ; false ("foo" is a value but not a key)
    (contains? ["foo" "bar"] 1)    ; true  (vectors are keyed by integers)
    (contains? '("foo" "bar") 1)   ; false (but lists aren't)
    (contains? "foo" 1)            ; true  (but strings are)


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: