Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I test to see if a function has side effects in Clojure?

Tags:

clojure

Is there a function or a macro where I can do the following:

(has-side-effects?  my-function  my-function-args)

: or something like it which can return true or false, or {:side-effects true/false, :result return_value)

I just need an easy way to test to see which functions are side effect free.

like image 618
yazz.com Avatar asked Jan 02 '11 16:01

yazz.com


3 Answers

If it is one of your functions add some metadata to mark if it has side effects.

Then you can check it with ((meta f) :side-effects)

If it is a third party function there is no way that I know of (other that changing their code to use the solution described above).

Actually, there is even then but it isn't pretty. You can wrap the function with your own, which has metadata.

Also, keep in mind that a pure function has one additional property besides not having side effects. Its evaluation depends only on its parameters, and not some global shared state, like an external variable or system time. You might want to add this to your metadata, too. Then you can check if it is really pure by checking for both metadata entries.

However, be warned:

This simply wouldn't work for functions that take other functions as parameters. Here's an example: Does calling map have side effects?

It doesn't here: (map inc [1 2 3])

But it does here: (map println [1 2 3])

Because the passed function may or may not have side effects.

like image 175
Goran Jovic Avatar answered Nov 06 '22 05:11

Goran Jovic


This isn't possible in the general case (unless you also manage to solve the halting problem.... :-) )

However, there are various techniques that you might consider using in specific circumstances:

  • Create a "whitelist" of functions that you know to be side effect free - e.g. most of the core Clojure APIs are side effect free
  • Use metadata to tag your own functions as suggested by Goran
  • Use annotations on Java classes / functions that you control
  • Use watches on Clojure references (with add-watch) if you want to check for side effects on specific Clojure references
like image 7
mikera Avatar answered Nov 06 '22 07:11

mikera


Clojure is not a purely functional language. It does not force the purity on the functions using the type system like Haskell does. So, no, there is no (straightforward) way to know if a function is side-effect free or not in Clojure.

like image 5
Abhinav Sarkar Avatar answered Nov 06 '22 06:11

Abhinav Sarkar