Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lazy evaluation issue in Clojure

Tags:

clojure

It tried the following in REPL and got no error (because of lazy evaluation):

(defn square [n] (* n n))
  (if (= 0 0) 
    (println "hello")
    (map square ["a" "b"]))

The following gives error (because it gets evaluated):

(defn square [n] (* n n))
  (if (= 0 1)
    (println "hello")
    (map square ["a" "b"]))

My concern is that if in a large piece of code, there are some parts which my test cases could never touch, then for example, a code like above will crash in production! Is there a way to check these things at compile time?

Thanks

like image 953
user855 Avatar asked Nov 18 '25 20:11

user855


2 Answers

It's not lazy evaluation. It's conditional evaluation.

Special form (if condition expr1 expr2) evaluates expr2 only if condition was false.

Your concern is not related to Clojure nor laziness.

Try this in Ruby:

irb(main):003:0> raise "wannabe error" if false
=> nil  

[edit: answering your question more precisely]

You can hardly have such error detection at compile time in a dynamic language.

At runtime you can evaluate tests with different values of conditions to reach possibly all revelant code branches. I guess the situation is the same in all dynamic languages. It's the reason we write the tests for.

So you'd want to cover both cases, true and false, for the condition you're concerned about in your tests.

Personally I'm a fan of solutions like QuickCheck which generate a wide range of possible values (guarded by some conditions if you need) for the purpose of testing. In the case above you'd only want to test 2 cases, true and false, but imagine other tests triggered by a wide range of input values. Unfortunately there are not many implementations of such generators. The only QuickCheck clones for dynamic typing languages I know are for Erlang (proprietary and quite expensive) and RushCheck for Ruby. The Clojure implementation is in its infancy.

like image 192
Wojciech Kaczmarek Avatar answered Nov 20 '25 15:11

Wojciech Kaczmarek


Nope. Then again, if code behaves bad in cases not tested by test cases, it will not be caught by the test cases.

You could add a type system on top of Clojure using macros, but then you run into limitations that the type system has and the limitations it would impose.

(Side note: this isn't really lazy evaluation; this is the behavior of the if special form)

like image 44
Brian Avatar answered Nov 20 '25 15:11

Brian



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!