Clojure precondition with local variable - optimization

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)

Related

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

If function in common lisp

I have the following function
(defun testIf (n)
(if (<= n 0) t)
print "Hello World")
My issue is when I test (testIf -1), it returns "Hello World". Therefore I am wondering why the if was completely ignored. Keep in mind, I just want an if in this program, no else chain. Any help would be appreciated.
To clear up confusion I am attempting to do something similar to this in lisp(as java has data types I had to compensate for this in this example)
public int testIf(n)
{
if(n <= 0)
return 5;
System.out.println("Hello "World");
return 0;
}
testIf(-1);
In Java the 5 would be returned and the next line would never be read..
The IF is not ignored; its return value is just discarded, because there is another form after it. A function returns the value(s) from the last form of the body. Consider this function
(defun foo ()
1
2)
Would you expect that to return 1? Of course not. That would be completely counterintuitive. An IF is just a form like any other, so why would its result be returned in your function?
You could use RETURN-FROM to do an early return from the function:
(defun test-if (n)
(when (<= n 0) ; You should use WHEN instead of IF when there's no else-branch.
(return-from test-if t))
(print "Hello World"))
However, in most situations that is not idiomatic. Remember that Lisp is a very different language from Java and you should not try to write Java in Lisp. It's better to just put the PRINT in the else-branch. If the else-branch has multiple forms, you can use COND instead:
(defun test-if (n)
(cond ((<= n 0) t)
(t (print "Hello World")
:foo
:bar
:quux)))
In java the 5 would be returned and the next line would never be read..
jkiiski's answer correctly explains the behavior, but it's worth pointing out that the Lisp code you wrote is not like the Java code that you wrote. If you wanted to translate the Java code literally, you'd do:
(defun testIf (n)
(if (<= n 0)
(return-from testIf 5))
(print "Hello World")
(return-from testIf 0))
which does return 5 when n is less or equal to 0.

How to know whether a racket variable is defined or not

How you can have a different behaviour if a variable is defined or not in racket language?
There are several ways to do this. But I suspect that none of these is what you want, so I'll only provide pointers to the functions (and explain the problems with each one):
namespace-variable-value is a function that retrieves the value of a toplevel variable from some namespace. This is useful only with REPL interaction and REPL code though, since code that is defined in a module is not going to use these things anyway. In other words, you can use this function (and the corresponding namespace-set-variable-value!) to get values (if any) and set them, but the only use of these values is in code that is not itself in a module. To put this differently, using this facility is as good as keeping a hash table that maps symbols to values, only it's slightly more convenient at the REPL since you just type names...
More likely, these kind of things are done in macros. The first way to do this is to use the special #%top macro. This macro gets inserted automatically for all names in a module that are not known to be bound. The usual thing that this macro does is throw an error, but you can redefine it in your code (or make up your own language that redefines it) that does something else with these unknown names.
A slightly more sophisticated way to do this is to use the identifier-binding function -- again, in a macro, not at runtime -- and use it to get information about some name that is given to the macro and decide what to expand to based on that name.
The last two options are the more useful ones, but they're not the newbie-level kind of macros, which is why I suspect that you're asking the wrong question. To clarify, you can use them to write a kind of a defined? special form that checks whether some name is defined, but that question is one that would be answered by a macro, based on the rest of the code, so it's not really useful to ask it. If you want something like that that can enable the kind of code in other dynamic languages where you use such a predicate, then the best way to go about this is to redefine #%top to do some kind of a lookup (hashtable or global namespace) instead of throwing a compilation error -- but again, the difference between that and using a hash table explicitly is mostly cosmetic (and again, this is not a newbie thing).
First, read Eli's answer. Then, based on Eli's answer, you can implement the defined? macro this way:
#lang racket
; The macro
(define-syntax (defined? stx)
(syntax-case stx ()
[(_ id)
(with-syntax ([v (identifier-binding #'id)])
#''v)]))
; Tests
(define x 3)
(if (defined? x) 'defined 'not-defined) ; -> defined
(let ([y 4])
(if (defined? y) 'defined 'not-defined)) ; -> defined
(if (defined? z) 'defined 'not-defined) ; -> not-defined
It works for this basic case, but it has a problem: if z is undefined, the branch of the if that considers that it is defined and uses its value will raise a compile-time error, because the normal if checks its condition value at run-time (dynamically):
; This doesn't work because z in `(list z)' is undefined:
(if (defined? z) (list z) 'not-defined)
So what you probably want is a if-defined macro, that tells at compile-time (instead of at run-time) what branch of the if to take:
#lang racket
; The macro
(define-syntax (if-defined stx)
(syntax-case stx ()
[(_ id iftrue iffalse)
(let ([where (identifier-binding #'id)])
(if where #'iftrue #'iffalse))]))
; Tests
(if-defined z (list z) 'not-defined) ; -> not-defined
(if-defined t (void) (define t 5))
t ; -> 5
(define x 3)
(if-defined x (void) (define x 6))
x ; -> 3

Can I include a message in pre and postconditions

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.

Why can't I delete the current element when iterating over a list?

I want to iterate over a list, perform an action with the elements and based on some criteria, I want to get rid of the active element. However, when using the function below I end up in an infinite loop.
(defun foo (list action test)
(do ((elt (car list) (car list)))
((null list))
(funcall action elt)
(when (funcall test elt)
(delete elt list))))
(setq list '(1 2 3 4))
(foo list #'pprint #'oddp)
-> infinite loop
Is it not possible as it points to itself? In the end, elt is (car list) of course.
Is this a correct assessment? And how could I solve this efficiently?
The loop is infinite since you are not iterating over anything, you apply the action repeatedly, but if it doesn't mutate the element, as pprint obviously doesn't, then if the test result is negative then it will remain so and the list wouldn't empty even if the deletion worked as you attempt it.
DELETE is a destructive function. In Common Lisp destructive operations are allowed to destroy their argument. You are supposed to discard any references to the argument and use only the return value. After the operation is completed there are no guarantees about the state of the argument. In particular, there might be no effect as implementations are also allowed to act identically to a non-destructive counterpart, but usually the component parts of the sequence will be reassembled in some difficult to predict way. You are also destroying a literal in your example, which has undefined behaviour and it should be avoided.
It is generally best to treat lists in Common Lisp as immutable and destructive operations as a microoptization which should only be used when you are sure they won't break anything. For this problem you might want to iterate over the list using LOOP assembling the result list with conditional COLLECT. See the LOOP chapter of PCL.
Actually you can alter the state of your list while iterating over it. You will just have to use rplacd in addition to delete, and control the advancement along the list not in the iteration clause, but inside the do body:
(defun nfoo (lst action test)
(do* ((list (cons 1 lst))
(elt (cadr list) (cadr list)))
((null (cdr list))
(if (funcall test (car lst)) (cdr lst) lst))
(funcall action elt)
(if (funcall test elt)
(rplacd list (delete elt (cddr list)))
(setf list (cdr list)))))
You should call it via copy-list if you don't want it to destroy the argument list.
If you want to remove from your list not all elements equal to elt that passed the test, but rather all such that will pass the test, then the delete call will need to be passed the test function as the :test argument.
(edit:) and even much simpler and straightforward, like this (non-destructive) version:
(defun foo (list action test)
(do* ((elt (car list) (car list)))
((null list))
(funcall action elt)
(if (funcall test elt)
(setf list (delete elt list))
(setf list (cdr list)))))
I'm a bit new to lisp, so perhaps I'm missing something in your question. Still, I think I understand what you're asking, and I wonder why you're not using some existing structures for this... namely remove-if-not (or remove-if if I have things backwards) and mapcar...
(mapcar #'pprint (remove-if-not #'oddp '(1 2 3 4))
The above prints 1 and 3 (and returns (nil nil), but presumably you can ignore that... or you could do a defun that does the above and ends with (values)). (If you wanted the evens, change remove-if-not to remove-if.)
This strikes me as perhaps a more sensible way to go about things, unless you're doing this for pedagogical reasons or I'm missing something... either of which I admit is quite possible. :)
P.S. Hyperspec info on remove-if, remove-if-not, etc.