Know your Knodes
Some of the strongest constructs (for golfing) in functional languages are let ... in ...
.
Clean of course, has this, and something better - the #
.
What is a node?
Clean's #
, and the ubiquitous |
(pattern guard) are both known as 'node expressions'.
Notably, they allow you to program imperatively-ish in Clean (which is really good here!).
The #
(let-before):
These both compute the value of an integer given as a string, multiplied by the sum of its chars
f s=let i=toInt s;n=sum[toInt c\\c<-:s]in n*i
f s#i=toInt s
#s=sum[toInt c\\c<-:s]
=s*i
Note how the version with #
is shorter, and how we can redefine s
. This is useful if we don't need the value that a variable has when we receive it, so we can just re-use the name. (let
can run into issues when you do that)
But using let
is easier when you need something like flip f = let g x y = f y x in g
The |
(pattern guard):
Clean's pattern guard can be used like those in many other functional languages - however it can also be used like an imperative if ... else ...
. And a shorter version of the ternary expression.
For example, these all return the sign of an integer:
s n|n<>0|n>0=1= -1
=0
s n=if(n<>0)if(n>0)1(-1)0
s n|n>0=1|n<0= -1=0
Of course, the last one which uses the guard more traditionally is the shortest, but the first one shows that you can nest them (but only two unconditional return clauses can appear on the same line in layout rule), and the second shows what the first one does logically.
A note:
You can use these expressions basically anywhere. In lambdas, case ... of
, let ... in
, etc.