user8370684
user8370684

Reputation:

Can Lisp be easily used in an immutable, functional manner?

I come from a background in Haskell, and I want to learn Common Lisp.

It's well discussed that CL is "not a functional language", but I would like to know whether it can be used as a functional language.

For example, is it possible to use all of the data types in an immutable manner? Common Lisp hash-tables seem to be set using setf, which is decidedly of the mutable orientation. Is there a way to use it in an immutable manner?

Aside from the "IO" aspect of Common Lisp (the "purely" aspect of Haskell) where I interact with files, networks, etc., can I comfortably write code in Lisp and be assured that the code will have referential transparency?

Can I expect these kinds of properties from the popular libraries available in Common Lisp?

Are there common idioms or aspects of the language that will make these difficult?

Upvotes: 7

Views: 1599

Answers (1)

Svante
Svante

Reputation: 51501

Yes, of course, but depending on how much you want restrictions to be enforced, your mileage may vary.

Just don't mutate

You can simply avoid setf and all the places machinery. If you have to use hash-tables or vectors, you will be copying a lot, but for many applications, the garbage collection overhead can be still manageable. In many places, you can use alists or plists, which can be handled almost like functional data structures. Some useful utilities are in alexandria, e. g. copy-hash-table, which has a key argument to actually do something like a hypothetical map-hash-table. All the other functional goodness, like higher order functions, map, reduce, remove etc. are available in many flavours. Also, certain use cases can be solved quite declaratively in loop.

There are also libraries that make this style explicitly easier, e. g. modf.

This can take you quite far. I perceive it as easy to see where you break referential transparency and avoid that.

Use functional data structures

There is FSet, which gives you a lot of functional data structures, and there is sycamore, which gives some more.

Use transducers

SERIES appeared in CLtL2 in 1990 and almost made it into the standard in 1994. There is also taps, which adds some useful functionality.

Meditate

Personally, I am not so hard after purity any more. Sometimes, mutating a place in a loop is easier to understand than juggling multiple bindings in different extents. I just keep the mutation confined; this is similar to a data ownership concept. However, I like to have purity on a larger scale, both in memory and on disk, e. g. append-only logs, databases (bknr.datastore).

Upvotes: 16

Related Questions