Mark Needham

Thoughts on Software Development

Clojure: A few things I’ve been tripping up on

with 2 comments

In my continued playing with Clojure I’m noticing a few things that I keep getting confused about.

The meaning of parentheses

Much like Keith Bennett I’m not used to parentheses playing such an important role in the way that an expression gets evaluated.

As I understand it if an expression is enclosed in parentheses then that means it will be evaluated as a function.

For example I spent quite a while trying to work out why the following code kept throwing a class cast exception:

(if (true) 1 0)

If you run that code in the REPL you’ll get the following exception because ‘true’ isn’t a function and therefore can’t be applied as such:

java.lang.ClassCastException: java.lang.Boolean cannot be cast to clojure.lang.IFn (NO_SOURCE_FILE:0)

If we don’t want something to be treated this way then the parentheses need to disappear!

(if true 1 0)

Truthyness

Somewhat related to the above is understanding which expressions evaluate to ‘true’ or ‘false’.

I’m told there are some edge cases but that as a general rule everything except for ‘false’ and ‘nil’ evaluates to true.

I think that’s an idea which is more common in languages like Ruby but I’m not yet used to the idea that we can something like this and have it execute:

(if "mark" 1 0)

In C# or Java I would except to have to compare “mark” to something in order for it to evaluate to a boolean result.

It seems like a really neat way to reduce the amount of code we have to write though so I like it so far.

Character Literals

I’ve been working through Mark Volkmann’s Clojure tutorial and in one example he defines the following function:

(def vowel? (set "aeiou"))

I wanted to try it out to see if a certain character was a vowel so I initially did this:

=>(vowel? "a")
nil

“a” is actually a string though which means it’s an array of characters when what we really want is a single character.

I thought the following would be what I wanted:

(vowel? 'a')

Instead what I got was the following exception:

java.lang.Exception: Unmatched delimiter: )

This one just turned out to be a case of me not reading the manual very carefully and actually the following is what I wanted:

=> (vowel? \a)
\a
Be Sociable, Share!

Written by Mark Needham

November 20th, 2009 at 1:11 pm

Posted in Clojure

Tagged with

  • Steve Gilardi

    Regarding “edge cases” for truthiness, http://clojure.org/special_forms#if gives the full details. The potential gotcha is covered there: all instances of class java.lang.Boolean other than the canonical false instance Boolean/FALSE are logically true.

    ; clojure false is Boolean/FALSE
    user=> (identical? false Boolean/FALSE)
    true
    ; other Boolean instances are logically true
    user=> (Boolean. false)
    false
    user=> (if (Boolean. false) “truthy” “not truthy”)
    “truthy”
    ; always use Boolean/valueOf rather than the constructor
    user=> (Boolean/valueOf false)
    false
    user=> (if (Boolean/valueOf false) “truthy” “not truthy”)
    “not truthy”
    ; clojure.core/boolean will fix up any Boolean instance
    user=> (if (boolean (Boolean. false)) “truthy” “not truthy”)
    “not truthy”
    ; so will Boolean/valueOf
    user=> (if (Boolean/valueOf (Boolean. false)) “truthy” “not truthy”)
    “not truthy”
    user=>

    Pure Clojure code will always produce and consume canonical false. This subtlety only comes up when using Java interop either directly (calling a Boolean constructor, something you can and should always avoid) or when interfacing with Java libraries. When in doubt about a Boolean value returned from Java, casting using either clojure.core/boolean or Boolean/valueOf will ensure no surprises.

    Note that many (most?) Java libraries will return a boolean (primitive) value rather than a Boolean (object) value. Primitive false always works without surprises.

    user=> (identical? Boolean/FALSE (.booleanValue (Boolean. false)))
    true

  • Pingback: Tackling Clojure as a Rubyist | Spencer Rogers()