Can I include a message in pre and postconditions - error-handling

I have this (not (some #(= (:length %1) 0) %)) as a postcondition. Written like this it's pretty clear, but when this condition isn't met I get this:
Assert failed: (not (some (fn* [p1__17852#] (= (:length p1__17852#) 0)) %))
Which isn't very readable. Is there a way to define the message for a postcondition, or for a precondition?
Edit 1:
Following noahlz and noisesmiths suggestion, (but using an external named function):
(defn not-zero-length
[evseq]
(not (some (fn [item] (= (:length item) 0)) evseq)))
(defn my-func
[evseq]
{:post [(not-zero-length %)]}
evseq)
(my-func '({:length 3}{:length 0}))
gives:
AssertionError Assert failed: (not-zero-length %)
Which is alot clearer.

This is discussed in the following clojure mailing list thread.
Looking at the clojure.core source you can see the fn macro only passes in a boolean to the assert function, and does not include an optional parameter for passing an additional message argument in.
So it looks like there is no way to do this cleanly yet.

This post in the same thread suggests the use of the clojure.test/is macro, which returns a meaningful error message.
(require '[clojure.test :refer [is]])
(defn get-key [m k]
{:pre [(is (map? m) "m is not a map!")]}
(m k))
(get-key [] 0)
returns
FAIL in clojure.lang.PersistentList$EmptyList#1 (form-init8401797809408331100.clj:2)
m is not a map!
expected: (map? m)
actual: (not (map? []))
AssertionError Assert failed: (is (map? m) "m is not a map!")

expanding on a suggestion above:
(not (some (fn zero-length [item] (= (:length item) 0)) %))
when you name an anonymous function, any errors involving that fn will be more readable
also, how is it that you have two % substitutions above? #() does not nest.

Related

Error - unbound symbol modulo (Scheme) when using Repl online IDE

A homework problem needs me to calculate gcd of 2 numbers. But using the modulo keyword in the function for gcd gives the above error when run on Repl.it (online IDE).
I looked at other answers, but they don't exactly provide a solution to the problem. I tried to run the program using jdoodle.com (another online IDE) and it works perfectly there. So, I don't know why it won't work on Repl.
;; My gcd function
(define (gcd a b)
(cond
[
(= b 0) a
]
[else
(gcd b (modulo a b))
]
)
)
I would like to know why this doesn't work for Repl IDE and if there is any way how I can make it work there without simply switching to another website.
modulo function is not implemented in BiwaScheme used by repl.it. However good new is - mod function is! So, with some reasonable reformatting, this should work:
(define (gcd a b)
(cond [(= b 0) a]
[else (gcd b (mod a b))]))

clojure threading macro with failure form

I have a few operations I want to thread where each can fail. I would much rather get the error as a value instead of using try-catch which breaks the flow of execution.
I can do the naive version and make my functions use nil as failure:
(if-let (op1 ...)
(if-let (op2 ...)
...
err1)
err2)
but this is nested and makes it harder to read.
I could use some-> which seems like the closest solution but it doesn't say what failed:
(if-let [res (some-> arg
op1
op2)]
res
somethin-failed) ;; what failed though?
I also looked at ->, and cond-> but they don't seem to help.
I know there are macros online to do these kind of things but I would much rather not add macros if something exists to solve this. Hopefully there is something of the form:
(some-with-err-> arg
op1 err1
op2 err2
...)
I may be overlooking something simpler, but I can't seem to find something built-in to address this issue.
I can write a macro to do it but would rather avoid it for now.
There's nothing built-in for this, but there are libraries for monadic error handling (e.g. Failjure) which seems like what you're looking for.
You could derive a version some-with-err-> from the some-> macro definition. The only practical difference is the map function that binds to steps now partitions the forms/error values, wraps step invocations in try and returns a namespaced map on failure:
(defmacro some-with-err->
[expr & forms]
{:pre [(even? (count forms))]}
(let [g (gensym)
steps (map (fn [[step error]]
`(if (or (nil? ~g) (::error ~g))
~g
(try (-> ~g ~step)
(catch Exception _# {::error ~error}))))
(partition 2 forms))]
`(let [~g ~expr
~#(interleave (repeat g) (butlast steps))]
~(if (empty? steps)
g
(last steps)))))
It can be used like some-> but each form must be accompanied by an error return value:
(some-with-err-> 1
(+ 1) :addition
(/ 0) :division
(* 2) :multiplication)
=> #:user{:error :division}
(some-with-err-> " "
(clojure.string/trim) :trim
(not-empty) :empty
(str "foo") :append)
=> nil ;; from not-empty

Clojure - What can I do to correctly use Vars and/or Atoms?

I'm having a lot of trouble with Clojure since I'm new to it. I'm attempting to solve for an orthanormal vector from matrix [[i, j, k], [5, 2, 3], [8, 3, 2]]. I know what the algorithm is, but I'm confused about when to use atoms and vars. As a result, I continue to get errors. Could someone point out what I'm doing wrong and how I can improve the code?
Listed below the code is the error.
(defn solve [& rows]
(let [orthanormal-vector (atom [])]
(let [dimension-range (range (count rows))
determinant-argument (atom [])]
(doseq [[i row] (map list dimension-range rows)]
(let [row-range (range (count row))
determinant-vector (atom [])]
(doseq [[j e] (map list row-range (seq row))]
(if-not (= i j) (swap! determinant-vector (conj determinant-vector e)) (println "Do nothing")))
(var-set determinant-argument (conj determinant-argument determinant-vector)))
(def determinant-result (incanter-core/det (incanter-core/matrix (vec determinant-argument))))
(swap! orthanormal-vector (conj orthanormal-vector determinant-result))
))))
java.lang.ClassCastException: clojure.lang.Atom cannot be cast to clojure.lang.IPersistentCollection
core.clj:83 clojure.core/conj
/Users/chriskim/Desktop/promethix/src/promethix/orthanormal/solver.clj:14 promethix.orthanormal.solver/solve
RestFn.java:436 clojure.lang.RestFn.invoke
/Users/chriskim/Desktop/promethix/src/promethix/orthanormal/solver.clj:24 promethix.orthanormal.solver/eval16321
Compiler.java:6703 clojure.lang.Compiler.eval
Compiler.java:6666 clojure.lang.Compiler.eval
core.clj:2927 clojure.core/eval
eval.clj:77 lighttable.nrepl.eval/->result
AFn.java:156 clojure.lang.AFn.applyToHelper
AFn.java:144 clojure.lang.AFn.applyTo
core.clj:626 clojure.core/apply
core.clj:2468 clojure.core/partial[fn]
RestFn.java:408 clojure.lang.RestFn.invoke
core.clj:2559 clojure.core/map[fn]
LazySeq.java:40 clojure.lang.LazySeq.sval
LazySeq.java:49 clojure.lang.LazySeq.seq
RT.java:484 clojure.lang.RT.seq
core.clj:133 clojure.core/seq
core.clj:2595 clojure.core/filter[fn]
LazySeq.java:40 clojure.lang.LazySeq.sval
LazySeq.java:49 clojure.lang.LazySeq.seq
Cons.java:39 clojure.lang.Cons.next
RT.java:598 clojure.lang.RT.next
core.clj:64 clojure.core/next
core.clj:2856 clojure.core/dorun
core.clj:2871 clojure.core/doall
eval.clj:126 lighttable.nrepl.eval/eval-clj
RestFn.java:442 clojure.lang.RestFn.invoke
eval.clj:192 lighttable.nrepl.eval/eval10834[fn]
AFn.java:152 clojure.lang.AFn.applyToHelper
AFn.java:144 clojure.lang.AFn.applyTo
core.clj:624 clojure.core/apply
core.clj:1862 clojure.core/with-bindings*
RestFn.java:425 clojure.lang.RestFn.invoke
eval.clj:177 lighttable.nrepl.eval/eval10834[fn]
eval.clj:176 lighttable.nrepl.eval/eval10834[fn]
MultiFn.java:227 clojure.lang.MultiFn.invoke
core.clj:98 lighttable.nrepl.core/queued[fn]
core.clj:2402 clojure.core/comp[fn]
interruptible_eval.clj:138 clojure.tools.nrepl.middleware.interruptible-eval/run-next[fn]
AFn.java:22 clojure.lang.AFn.run
ThreadPoolExecutor.java:895 java.util.concurrent.ThreadPoolExecutor$Worker.runTask
ThreadPoolExecutor.java:918 java.util.concurrent.ThreadPoolExecutor$Worker.run
Thread.java:680 java.lang.Thread.run
The specific error resulting in clojure.lang.Atom cannot be cast to clojure.lang.IPersistentCollection is:
(swap! determinant-vector (conj determinant-vector e))
shoudl be written:
(swap! determinant-vector conj e)
swap! takes an atom as it's first argument and a function as a second argument. It then builds a function call by passing the current value in the atom as the first argument to that function and appends the rest of the arguments after that. this will be translated into a function call somewhat like this:
(conj #determinant-vector e)
ps: # is a reader macro for calling deref to get the current value out of one of the mutable state types.
PPS: Charles Duffy is correct that loop/recur are much better tools for this task than using an atom. It should be about 100x faster, at least in terms of overhead.
This is not quite answering your question but I'd suggest using core.matrix for matrix computation / algorithms in Clojure. This gives you at least two big advantages:
A lot of vector / matrix operations are already implemented. There isn't much point reinventing the wheel if you don't need to.
It allows you to use optimised implementations that are much more efficient than regular Clojure data structures. This includes native BLAS libraries (e.g. Clatrix) and fast pure-JVM matrix libraries (e.g. Vectorz)
Disclaimer: I'm a maintainer on some of the above projects.

Clojure precondition with local variable

Is there any way to store the result of a computation performed in a precondition so that it can be used in the actual function body.
This is awful (costly-computation runs twice):
(defn bar [x]
{:pre [(> (costly-computation x) 1337)]}
(costly-computation x))
I would like to do something along these lines. But this doesn't work.
(defn smartbar [x]
(let [res (costly-computation x)]
{:pre [(> res 1337)]}
res))
You have multiple ways to tackle this. For example you can compute (costly-computation x) outside of (bar) function and pass it as a parameter to (bar) function.
Or you can compute (costly-computation x) inside (bar) function and validate there, no {:pre} condition.
Or write a Macro to do exactly what you want!
Your smartbar isn't going to work because that isn't how defn macro is created to do.
Try this inside the REPL:
(source defn)

How to implement a try-catch block in scheme?

I'm trying to implement a try-catch block in scheme using (call-cc) method but i'm not sure how it can be used for that. I could not find any example.
And found examples contains just error-handling but what i want to do is: if an error occurred, the scheme program has to give a message to user (via display for-example) without suspending the program.
Is that possible?
Typically you'd use the with-handlers form. This lets you display an error message or take any other action before returning a value.
#lang racket
(define (foo x)
(with-handlers ([exn:fail? (lambda (exn)
(displayln (exn-message exn))
#f)])
(/ 1 x)))
(foo 1)
; 1
(foo 0)
; "/: division by zero"
; #f
If you really want to use a continuation directly for some reason, you could use call/ec for an error/escape continuation instead of the general call/cc.
Docs:
with-handlers
call/ec
Since you want to catch all errors, such as ones raised by both raise and raise-continuable you'd need both an exception handler (to deal with raised conditions) and an exit continuation (to avoid continuing with the try body). Simple syntax for try would be:
(import (rnrs base) ; define-syntax
(rnrs exceptions)) ; get `with-exception-handler`
(define-syntax try
(syntax-rules (catch)
((_ body (catch catcher))
(call-with-current-continuation
(lambda (exit)
(with-exception-handler
(lambda (condition)
catcher
(exit condition))
(lambda () body)))))))
This gets used as, for example:
> (try (begin (display "one\n")
(raise 'some-error)
(display "two\n"))
(catch (display "error\n")))
one
error
some-error # the return value.
Note: this is R6RS (and R7RS) Scheme.