Tips for golfing in Clojure

16

3

What are your tips for code golfing using Clojure?

The aim of this question is to collect a list of techniques that are specific to Clojure and can be used in general code-golfing problems.

mikera

Posted 2011-06-12T18:06:16.540

Reputation: 1 233

Hmm.. shouldn't these types of posts be in meta (granted I'm not sure meta existed 5+ years ago) – Albert Renshaw – 2017-03-30T00:14:32.473

Answers

6

Use reader syntax for lambdas.
So use

#(+ % %2 %3)

instead of

(fn [x y z] (+ x y z))

You can also eliminate whitespace some of the time:

#(if (< % 0) (- %) %)
#(if(< % 0)(- %)%)

user2429260

Posted 2011-06-12T18:06:16.540

Reputation: 61

by the way #(+ % %2 %3) is equivalent to +. – bfontaine – 2019-11-30T12:37:08.903

4

Where you can remove whitespace:

  • Between a string and anything else:

    (println(+"Hello, World!"1))
    
  • Between brackets and anything else:

    (for[x(range 5)](* x x))
    
  • Between a number and everything other than builtins or variable names:

    Allowed:
    (+ 1"Example")
    (map{1"-1"2"-2"}[1 2 3])
    
    Not allowed:
    (+1 2)
    
  • Between @ (dereference for atoms) and brackets.

clismique

Posted 2011-06-12T18:06:16.540

Reputation: 6 600

Also before the deref reader macro @ – ASCII-only – 2017-03-29T22:19:56.003

1Also at times you might be able to re-arrange stuff at a let and get rid of some spaces. – NikoNyrh – 2017-12-14T21:56:23.827

Also before parameters in anonymous functions: #(+ 1(first%)) = #(+ 1 (first %)) – bfontaine – 2019-11-15T20:27:27.863

3

Strings can be treated as a sequence of chars

e.g. to sort the characters in a string alphabetically:

(sort "hello")
=> (\e \h \l \l \o)

mikera

Posted 2011-06-12T18:06:16.540

Reputation: 1 233

1Strings are by definition a sequence of chars in almost every language, but you can't apply this trick in all of them :-) – mellamokb – 2011-06-12T21:44:52.557

3Or rather, "sequence" has a special meaning in Clojure than means you can apply extra tricks ::-) – mikera – 2011-06-13T11:24:34.160

2

Use nth ... 0 instead of first

To get the first element of a collection, using (nth ... 0) over first saves a byte:

(first[2 3 4]): 14 bytes
(nth[2 3 4]0): 13 bytes (saves a byte!)

clismique

Posted 2011-06-12T18:06:16.540

Reputation: 6 600

same goes for second (2 bytes) – Uriel – 2017-12-14T22:12:43.007

1Also you can use vectors as functions, so ([2 3 4]1) returns the element at index 1. This should be benefitical if for example the input format is flexible. – NikoNyrh – 2017-12-15T20:30:12.790

1

Use apply instead of reduce

For example #(apply + %) is one byte shorter than #(reduce + %).

NikoNyrh

Posted 2011-06-12T18:06:16.540

Reputation: 2 361

1

Bind long function names at let to a single-byte symbol

For example if you need to use partition or frequencies multiple times, it could be beneficial to bind them to a single-byte symbol in a let macro. Then again it might not be worth it if you don't need the let otherwise, and the function name is relatively short.

NikoNyrh

Posted 2011-06-12T18:06:16.540

Reputation: 2 361

1

Avoid let if you already have a for

For example: #(for[a[(sort %)]...) instead of #(let[a(sort %)](for ...)).

For does also have a :let construct but it is too verbose for code golf.

NikoNyrh

Posted 2011-06-12T18:06:16.540

Reputation: 2 361

1

Use + and - instead of inc and dec

This saves 1 byte if you're using inc/dec on an expression with parens:

(inc(first[1 3 5]))
(+(first[1 3 5])1)

clismique

Posted 2011-06-12T18:06:16.540

Reputation: 6 600

1

Use maps instead of ifs when testing for equality

;; if n=3 then A else B
(if (= 3 n) A B) ; (if(=3n)AB)
({3 A} n B)      ; ({3A}nB) -> -3 chars

;; if n=2 or n=3 then A else B
(if (#{2 3} n) A B) ; (if(#{23}n)AB)
({2 A 3 A} n B)     ; ({2A3A}nB) -> -4 chars

bfontaine

Posted 2011-06-12T18:06:16.540

Reputation: 133

0

Use for instead of map

For instance #(for[i %](Math/abs i)) is a lot shorter than the map equvalent.

NikoNyrh

Posted 2011-06-12T18:06:16.540

Reputation: 2 361