I am new to Clojure and attempting to write a program that is supposed to simplify logical expressions. For example:
(or x false) => x
(or true x) => true
(or x y z) => (or x(or y z))
I believe, that I have figured out how to simplify expressions up to two arguments. However, I don't know how to simplify expressions that consist of more than two arguments. I attempted to use the nth function to try and partition the expression, but that seems to complicate things further:
(defn pre-simplify [expression n]
(cond
(= n 0) (nth expression 0)
(= n 1) (nth expression 1)
(= n 2) (nth expression 2)
(= n 3) (nth expression 3)
)
)
This is the code for the Simplify Function:
(defn simplify
([op arg1]
(cond
(and (= arg1 'true) (= op 'not)) false
(and (= arg1 'false) (= op 'not)) true
(= arg1 'true) true
(= arg1 'false) false)
;not not x -> x
)
([op arg1 arg2]
(cond
(seq? arg1) (let [arg1 (simplify op arg1)]))
(cond
(seq? arg2) (let [arg2 (simplify op arg2)]))
(cond
(= op 'or) (
(cond
(and (= arg1 'false) (= arg2 'false)) false
(or (= arg1 'true) (= arg2 'true)) true
(and (= arg1 'false) (and (not= arg2 'false) (not= arg2 'true))) arg2
(and ((not= arg1 'false) (not= arg1 'true)) (= arg2 'false)) arg1
)
)
(= op 'and') (
(cond
(and (= arg1 'true) (= arg2 'true)) true
(or (= arg1 'false) (= arg2 'false)) false
(and (= arg1 'false) (and (not= arg2 'false) (not= arg2 'true))) arg2
(and ((not= arg1 'false) (not= arg1 'true)) (= arg2 'false)) arg1
)
)
)
)
Also, I am thinking of using recursion on the rest of the list after the first two arguments. For example, this is how I am attempting to do it on more than two arguments:
([op arg1 arg2 & rest]
(simplify op (list (op arg1 (op arg2 rest))))))
This looks like homework, so let me just invite you to consider the problem from another angle.
In Clojure,
an and expression is a list (or other sequence) of expressions that starts with the symbol 'and;
an or expression is a list of expressions that starts with the
symbol 'or;
... .
An expression may also be
a symbol for an argument or other local name, or
the literal true or false.
To simplify an expression:
If it's a sequence (use seq? to test this), simplify its
arguments (all the elements of the list but the first - rest will give you those). You can use map to make the recursive call.
Then, for example, if the operator (the first element) is an and symbol,
If there are any false literals among the operands (you can use
some to test this), replace the whole expression with false.
If not, remove any true literals.
These simplifications may open the way for others. For example,
(and) is just true and
(and x) is just x.
Whatever you do, test your function as you develop it, making sure it does what you think it does. I got caught leaving out the operator in one case. And I fell over the (and x) case.
What's also up for grabs is how and how far you are expected to verify that the expression is valid.
What about unknown operators?
Are you expected to verify that symbols refer to something. If so,
how?
Notes
I'm assuming we can ignore side effects: all the expression does is
return a value.
I wouldn't replace (or x y z) with (or x (or y z)). This achieves
nothing and uses an extra token: the opposite of simplification.
Any Clojure value - a number, even a function - acts as logically
true, except false and nil, which act as logically false. Whether
this is relevant to your problem, I don't know.
If you're feeling smart, you may be able to parameterise how and
and or behave in terms of the literal you ignore (true and
false respectively), the one you conclude with, and the one you return
when there are no arguments.
The problem as whole is considered intractable. If you find an efficient solution to it, you'll be world famous!
Related
I was browsing the source of clojure.core:
(defmacro and
([] true)
([x] x)
([x & next]
`(let [and# ~x]
(if and# (and ~#next) and#))))
Why not just
(defmacro and
([] true)
([x] x)
([x & next]
`(if ~x (and ~#next) ~x)))
Because the argument x is a form, which might be any expression, that can be evaluated twice in (if ~x (and ~#next) ~x)). The letevaluates it once and uses the value x# thereafter.
So the actual code avoids the effects - the side effects in particular - of evaluating the arguments twice.
#amalloy points out that the second instance of form x in (if ~x (and ~#next) ~x)) is evaluated only if the first instance evaluates false(y).
This question already has an answer here:
Why such implementation of partial in clojure.core
(1 answer)
Closed 6 years ago.
I'm a beginner in clojure trying to understand it at a basic level for now.
I've been experimenting with partial and how it creates closures, and to get a deeper understanding I thought I should take a peek at the source code by doing a (source partial) .
There I get
(defn partial
"Takes a function f and fewer than the normal arguments to f, and
returns a fn that takes a variable number of additional args. When
called, the returned function calls f with args + additional args."
{:added "1.0"
:static true}
([f] f)
([f arg1]
(fn
([] (f arg1))
([x] (f arg1 x))
([x y] (f arg1 x y))
([x y z] (f arg1 x y z))
([x y z & args] (apply f arg1 x y z args))))
([f arg1 arg2]
(fn
([] (f arg1 arg2))
([x] (f arg1 arg2 x))
([x y] (f arg1 arg2 x y))
([x y z] (f arg1 arg2 x y z))
([x y z & args] (apply f arg1 arg2 x y z args))))
([f arg1 arg2 arg3]
(fn
([] (f arg1 arg2 arg3))
([x] (f arg1 arg2 arg3 x))
([x y] (f arg1 arg2 arg3 x y))
([x y z] (f arg1 arg2 arg3 x y z))
([x y z & args] (apply f arg1 arg2 arg3 x y z args))))
([f arg1 arg2 arg3 & more]
(fn [& args] (apply f arg1 arg2 arg3 (concat more args)))))
I find the whole definition to be redundant as I would only write it in a "varargs" fashion, ie the last 2 lines.
Is this a readability feature or am I missing something basic here?
It's not a readability feature but a matter of performance. Stuart Sierra explained it in Clojure Don’ts: Optional Arguments with Varargs:
Variable-arity function calls have to allocate a sequence to hold the arguments, then go through apply. Timothy Baldridge did a quick performance comparison showing that calls to a function with multiple, fixed arities can be much faster than variable-arity (varargs) function calls.
In that benchmark, the varargs version with 1 argument is around an order of magnitude slower than the multi-arity version with 1 arg, and with 3 args the difference goes up to ~ 2 orders of magnitude.
This is not to say that varargs should not be used at all: Sparsely calling a fn with varargs will probably not affect performance, but it could hit you hard when calling it from a tight loop.
I find the whole definition to be redundant as I would only write it
in a "varargs" fashion,
You are quite right. All but the varargs definition are redundant. As #nberger points out, the others are there to improve performance. You will find many such in clojure core: such as map, max, and comp.
In a function definition:
(defn ^boolean =
;;other arities omitted...
([x y]
(if (nil? x)
(nil? y)
(or (identical? x y)
^boolean (-equiv x y))))
what does the ^boolean part in function definition mean? Does it only extend the metadata and signify the type of return, or does it have any deeper meaning? In other words, does it add any more value than simply making the code more self-described?
It is a type hint. See
https://www.safaribooksonline.com/library/view/clojure-programming/9781449310387/ch09s05.html
http://clojure-doc.org/articles/language/functions.html
or your favorite book. PLEASE NOTE: the compiler does not enforce that the actual type matches the type hint! Example w/o type hint:
(defn go []
"banana" )
(println (go))
;=> banana
(defn ^long go []
"banana" )
(println (go))
;=> Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number,
I see this behavior in Clojure 1.2.1:
user=> (type '(1 2))
clojure.lang.PersistentList
user=> (type `(1 2)) ;; notice syntax-quote
clojure.lang.Cons
user=> (type '(1))
clojure.lang.PersistentList
user=> (type `(1))
clojure.lang.PersistentList
I expected `(1) to be a Cons just like `(1 2) is.
I also tried:
user=> (type (cons 1 nil))
clojure.lang.PersistentList
user=> (type (cons 1 `()))
clojure.lang.Cons
user=> (type (cons 1 '()))
clojure.lang.Cons
user=> (type (cons 1 []))
clojure.lang.Cons
So what is the reason for `(1) and (cons 1 nil) to be PersistentLists?
Like amalloy says, you shouldn't program against those exact types but against the seq abstraction.
However, I think I can take a guess at the reason. The Clojure forms that produce a PersistentList ultimately call RT.java, specifically the cons(Object x, Object coll) method. It begins with a pretty odd check: if(coll == null) return new PersistentList(x), after which it creates a Cons object if that check doesn't pass. If you look at earlier versions of the code, you can find this:
static public IPersistentCollection cons(Object x, IPersistentCollection y) {
if(y == null)
return new PersistentList(x);
return y.cons(x);
}
So in an earlier version of the function, the call was dispatched to the cons method of the second argument, so the case when the second argument was null (i.e. nil in Clojure) needed special handling. Later versions don't do that dispatching (or actually do it but in a different way, presumably to support a larger variety of collection types), but the check has been retained since it does not break any correctly written code.
If you care about the difference, your program is incorrect. They're both seqs, in the sense that (seq? x) returns true; the rest is implementation details you shouldn't depend on.
I want to repeatedly apply some function to some state until a condition holds true.
Function f takes a state, modifies it and returns it. Apply f again to the returned state and so on.
I think this would work.
(first (filter pred (iterate f x)))
But it's a bit ugly. Plus memory consumption is not ideal since iterator would be forced to evaluate and keep intermediate states until the state on which pred holds true is returned, at which point intermediate states should be garbage collected.
I know you can write a simple recursive function:
(loop [f x p] (if (p x) x (recur f (f x) p))
But I'm looking for a core library function (or some combination of functions) that does the same thing with the same memory efficiency.
What you really want is take-while:
take-while
function
Usage: (take-while pred coll)
Returns a lazy sequence of successive items from coll while
(pred item) returns true. pred must be free of side-effects.
EDIT
A way to use higher order functions to achieve the result you want might be to wrap your function into something to be consumed by trampoline, namely a function that will either return the final result or another function which will execute the next step. Here's the code:
(defn iterable [f] ; wraps your function
(fn step [pred x] ; returns a new function which will accept the predicate
(let [y (f x)] ; calculate the current step result
(if (pred y) ; recursion stop condition
(fn [] (step pred y)) ; then: return a new fn for trampoline, operates on y
y)))) ; else: return a value to exit the trampoline
The iterative execution would go as follows:
(trampoline (iterable dec) pos? 10)
Not sure what you mean by iterator - you're using it as if it were iterate, and I just want to be sure that's what you mean. At any rate, your solution looks fine to me and not at all ugly. And memory is not an issue either: iterate is free to throw away intermediate results whenever it's convenient because you aren't keeping any references to them, just calling filter on it in a "streaming" way.
I think you should just make your loop a simple recursive function:
(defn do-until [f x p]
(if (p x) x (recur f (f x) p)))
(do-until inc 0 #(> % 10)) ; => 11
How about drop-while
(first (drop-while (comp not pred) (iterate f x))
I don't think there is a core function that does this exactly and efficiently. Hence I would do this with loop/recur as follows:
(loop [x initial-value]
(if (pred x) x (recur (f x))))
Loop/recur is very efficient since it requires no additional storage and is implemented as a simple loop in the JVM.
If you're going to do this a lot, then you can always encapsulate the pattern in a macro.
Sounds like you want the while macro.
http://richhickey.github.com/clojure/clojure.core-api.html#clojure.core/while
Usage: (while test & body)
Repeatedly executes body while test expression is true. Presumes
some side-effect will cause test to become false/nil. Returns nil
In a slightly different use case the for macro supports :when and :while options too.
http://richhickey.github.com/clojure/clojure.core-api.html#clojure.core/for
Usage: (for seq-exprs body-expr)
List comprehension. Takes a vector of one or more
binding-form/collection-expr pairs, each followed by zero or more
modifiers, and yields a lazy sequence of evaluations of expr.
Collections are iterated in a nested fashion, rightmost fastest,
and nested coll-exprs can refer to bindings created in prior
binding-forms. Supported modifiers are: :let [binding-form expr ...],
:while test, :when test.
(take 100 (for [x (range 100000000) y (range 1000000) :while (< y x)] [x y]))