Calling reverse on the output of the following
(def seq-counter (atom 0))
(defn tokenize-data [data]
(reduce
(fn [out-data-map token]
(if (seq? token)
(conj out-data-map {(keyword (str "DIRECTIVE_" (reset! seq-counter (inc #seq-counter))))token})
(if-not (= token (first '(EQU)))
(conj out-data-map {(keyword (str "DATA_1")) token})
(conj out-data-map {:START '(EQU)}))))
{}
data))
called with
'(EQU (COLOR TABLE) ?)
produces
([:START (EQU)] [:DIRECTIVE_13 (COLOR TABLE)] [:DATA_1 ?])
My question is: What is the ? as a value and how do I compare it (other than what is below)?
I can't seem to test to see if ? is there using \?.
All I can do is compare it like this, and I get the result I want.
(= (last (nth (reverse (tokenize-data '(EQU (COLOR TABLE) ?))) 2)) (first '(?)))
You can prevent Clojure from evaluating any expression by just putting a quote ' in front of that expression. So '(?) quotes a list with ? as its first element without Clojure trying to call the ? function, and (first '(?)) accesses the ? in that list.
To get at the ? symbol directly, simply do '?, which will let you access the symbol itself without Clojure trying to return the value (if any) that is assigned to ?
user=> (= '? (first '(?)))
true
Related
Consider the following code:
(defn delete-last-line [list]
(take (- (count list) 1) list)
)
(->>
(create-list)
(delete-last-line))
Now i would like to replace delete-last-line by an anonymous function in thread-last. Something like the following, but this will not work. The problem is the i need to somehow have an identifier of the variable.
(take (- (count %) 1))
Put an extra pair of parens around your anonymous function so you're calling it; that way ->> threads into the invocation of the function, not its definition.
(->>
(create-list)
(#(take (- (count %) 1) %)))
I don't know what you mean by "somehow have an identifier of the variable", but if you want to give it a name instead of using %, you can always do that:
(println
(->>
(create-list)
((fn [lst] (take (- (count lst) 1) lst)))))
I have written a function in Clojure that is supposed to take a logical expression and return an equivalent expression where all not statements act directly on variables, like so:
(not (and p q r))
becomes
(or (not p) (not q) (not r))
It uses De Morgan's laws to push the nots inwards, and if a not acts directly on another not statement, they cancel out. The code looks like this:
(defn transform [expr]
(if
(list? expr)
(if
(=
'not
(first expr)
)
(if
(list? (nth expr 1))
(if
(=
'not
(first (nth expr 1))
)
(transform (first (rest (first (rest expr)))))
(if
(=
'and
(first (nth expr 1))
)
(cons
'or
(map
transform
(map
not-ify
(rest (first (rest expr)))
)
)
)
(if
(=
'or
(first (nth expr 1))
)
(cons
'and
(map
transform
(map
not-ify
(rest (first (rest expr)))
)
)
)
expr
)
)
)
expr
)
expr
)
expr
)
)
The problem lies in this part:
(map
transform
(map
not-ify
(rest (first (rest expr)))
)
)
The first map statement uses a function not-ify (excuse the pun) to basically put a not before each statement. That part works. However, the output doesn't work with the map transform, although the map transform part works by itself. Let me show you:
If I write the following in the REPL:
(def expr '(not (and q (not (or p (and q (not r)))))))
(map
not-ify
(rest (first (rest expr)))
)
I get the output ((not q) (not (not (or p (and q (not r))))))
If I then take that output and run (map transform '((not q) (not (not (or p (and q (not r))))))), I get the output ((not q) (or p (and q (not r)))). So far so good.
However if I run it all at once, like so:
(map
transform
(map
not-ify
(rest (first (rest expr)))
)
)
I get this output instead: ((not q) (not (not (or p (and q (not r)))))).
If run
(def test1
(map
not-ify
(rest (first (rest expr)))
)
)
(map transform test1)
I also get ((not q) (not (not (or p (and q (not r)))))).
However if I run
(def test2 '((not q) (not (not (or p (and q (not r)))))))
(map transform test2)
I once again get the correct result: ((not q) (or p (and q (not r)))).
My guess is that this is somehow related to the map not-ify output (test1) having the type LazySeq, while if I manually type the input (test2) it becomes a PersistentList. I've tried running (into (list)) on test1 to convert it to a PersistentList, as well as doRun and doAll, with no results. Can I somehow stop my map not-ify statement from returning a LazySeq?
The short answer is to use seq? instead of list?
Here is how I would implement it:
(defn push-not-down [expr]
(if (and (seq? expr) (seq? (second expr)))
(let [[outer-op & [[inner-op & inner-args] :as outer-args] :as expr] expr]
(if (= 'not outer-op)
(condp = inner-op
'and (cons 'or (map #(push-not-down (list 'not %)) inner-args))
'or (cons 'and (map #(push-not-down (list 'not %)) inner-args))
'not (first inner-args)
expr)
(if (#{'or 'and} outer-op)
(cons outer-op (map push-not-down outer-args))
expr)))
expr))
(deftest push-not-down-test
(testing "Not or and not and are transformed to and not and or not"
(is (= '(or (not :a) (not :b))
(push-not-down
'(not (and :a :b)))))
(is (= '(and (not :a) (not :b))
(push-not-down
'(not (or :a :b))))))
(testing "Double nots cancel"
(is (= :a
(push-not-down
'(not (not :a))))))
(testing "The rules work together in complex combinations"
(is (= '(and :a (and :b (not :c)))
(push-not-down
'(and (not (not :a)) (not (or (not :b) :c))))))
(is (= '(or (or (and (not :a))))
(push-not-down
'(or (or (and (not :a))))))))
(testing "Nested expressions that don't fit the rules are preserved"
(is (= '(not (inc 1))
(push-not-down
'(not (inc 1)))))
(is (= '(inc (or 2 1))
(push-not-down
'(inc (or 2 1)))))))
For forms and expressions, there is no significant difference between a list or a sequence. Alternatively if you did want to preserve listiness, you just need to be a bit more thorough in converting sequences to lists :)
For what it's worth, ...
First, let's define what a logical inverse becomes:
(def opposite {'and 'or, 'or 'and})
(defn inverse [expr]
(let [default (list 'not expr)]
(if (seq? expr)
(let [[op & args] expr]
(if (= op 'not)
(first args)
(cons (opposite op) (map inverse args))))
default)))
Let's test it:
(map inverse ['p '(not p) '(and a b) '(and (not a) b)])
;((not p) p (or (not a) (not b)) (or a (not b)))
It short-circuits double negatives as well as doing the DeMorgan thing.
Now we can express the transformation:
(defn transform [expr]
(if (seq? expr)
(let [[op & args] expr]
(if (= op 'not)
(inverse (first args))
(cons op (map transform args))))
expr))
For example,
(transform '(not (and p q r)))
;(or (not p) (not q) (not r))
Where it finds a not, it returns the inverse of the argument.
Otherwise, it reconstructs the expression, transforming
sub-expressions where it can, just as inverse does.
If we're not fussed about transforming sub-expressions, we can simplify to
(defn transform [expr]
(or (and (seq? expr)
(let [[op & args] expr]
(if (= op 'not) (inverse (first args)))))
expr))
I find pulling out the inverse manipulation easier to follow.
In the simple transform, I've played with and and or and
one-armed if to avoid repeating the do-nothing case that weighs
down OP's text.
How does this relate to #TimothyPratley's answer?
I shamelessly stole his observation on using seq? instead of
list?.
His throws an exception on unrecognised operations. Mine just makes
them nil.
I've factored the ands and ors into a single case.
I have tried to make it unnecessary to fully understand the code, so read the whole question first, then dig into the code if necessary.
I'm trying to make a macro for pattern matching.
It works by taking a list in which the first element is type of matching to be performed
Example: the first element in the list is "cons"; the macro would call a cons matching function.
A matching function takes an object and a function, calls the function with the matched value. With the cons matcher, it would call the function with the head and tail of the list.
I used a "num" matcher for testing. It's basically an identity matcher, so it could be nested inside itself arbitrarily, as I did below.
;a macro to make debugging easier
(defmacro log [item] `(do (print ~(join [(str item) ": "])) (println ~item)))
(defn make-pattern-matcher-iter [result bindings-queue]
(println "starting next iteration")
(log bindings-queue)
(if (first bindings-queue) (println "bindings-queue does contain an element") nil)
(if (first bindings-queue)
(let [[next-symbol pattern] (first bindings-queue)
pattern-name (first pattern)
pattern-items (next pattern)
pattern-matching-function (prepend-symbol "match-" pattern-name)
gensyms-attached-to-subpatterns (map (fn [pattern]
(if (symbol? pattern)
pattern
`(~(gensym "matchbinding") ~pattern)))
pattern-items)
all-bound-symbols (map (fn [sym]
(if (symbol? sym) sym (first sym)))
gensyms-attached-to-subpatterns)
gensyms-subpattern-pairs (filter list? gensyms-attached-to-subpatterns)
rest-of-bindings-queue (next bindings-queue)
updated-bindings-queue (concat rest-of-bindings-queue
gensyms-subpattern-pairs)
subpatterns (map second gensyms-subpattern-pairs)]
(log next-symbol)
(log all-bound-symbols)
(log updated-bindings-queue)
(log gensyms-attached-to-subpatterns)
(log gensyms-subpattern-pairs)
(log subpatterns)
`(~pattern-matching-function
~next-symbol
(fn [~#all-bound-symbols] ~(make-pattern-matcher-iter result updated-bindings-queue))))
result))
(defn make-pattern-matcher [object pattern result] (make-pattern-matcher-iter result [[object pattern]]))
(defn match-num [x f]
(if (number? x) (f x) nil))
(def this-m (make-pattern-matcher-iter '(+ x y) [['object '(pair x y)]]))
(def this-n (make-pattern-matcher '15 '(num (num z)) 'z))
(= this-n this-m)
(defmacro bind-match [object pattern result] (make-pattern-matcher object pattern result))
(bind-match 15 (num (num z)) z)
The problem is that the macro isn't properly binding "z"
the log gives on the second iteration:
gensyms-attached-to-subpatterns: ((matchbinding8210 (num z)))
gensyms-subpattern-pairs: ()
there are other log messages, but these seem to be the problem.
Take a look at how gensyms-subpattern-pairs is calculated. In the let block it says:
gensyms-subpattern-pairs (filter list? gensyms-attached-to-subpatterns)
this should take out everything but lists, which is all there is, so it shouldn't take out anything.
The filter seems to be too aggressive. Why?
As you noted, the elements of gensyms-attached-to-subpatterns are not IPersistentLists, but rather Conses. Sanity check:
(contains? (supers clojure.lang.Cons) clojure.lang.IPersistentList)
;=> false
So it looks like you'll need to use some other check than list?.
I need to define a function called
(get-all-pairs key seq)
It returns the list of all pairs in seq that have key as their first element. If no pairs match, then the empty list is returned.
For example,if I def pets
(def pets
'((cat 1) (dog 1) (fish 1) (cat 2) (fish 2))
)
(get-all-pairs 'cat pets) returns ((cat 1) (cat 2)), and (get-all-pairs 'bird pets) returns '().
Here is my try:
(defn get-all-pairs [key seq]
(cond
(= key (first(first(seq)))) (cons (first seq)
(get-all-pairs key (rest seq)))
:else '()))
But it doesnot work. If I call it, it messages as follow:
#'proj2.proj2/pets
=> (get-all-pairs 'cat pets)
ClassCastException clojure.lang.PersistentList cannot be cast to clojure.lang.IFn proj2.proj2/get-all-pairs (proj2.clj:20)
I don't know where the problem is. How to fix it?
The immediate error is because you have too many parens in your definition: (first (first (seq))) should just be (first (first seq)). Once you fix that, your function should run to completion, but give you the wrong answer: think about whether () is really what you want in your else case.
Once you've worked out your by-hand recursive approach, try to figure out what is going on in this solution:
(defn get-all-pairs [k pairs]
(filter #(= k (first %)) pairs))
You are on the right track, but sort of over-thinking this one. For allows you to abstract away many of the things you are attempting to do manually. In this case, we can generate a seq and iteratively use an if expression with :when.
(defn get-all-pairs [animal L]
(for [k L
:when (= animal (first k))]
k))
How do I get the index of any of the elements on a list of strings as so:
(list "a" "b" "c")
For example, (function "a") would have to return 0, (function "b") 1, (function "c") 2 and so on.
and... will it be better to use any other type of collection if dealing with a very long list of data?
Christian Berg's answer is fine. Also it is possible to just fall back on Java's indexOf method of class String:
(.indexOf (apply str (list "a" "b" "c")) "c")
; => 2
Of course, this will only work with lists (or more general, seqs) of strings (of length 1) or characters.
A more general approach would be:
(defn index-of [e coll] (first (keep-indexed #(if (= e %2) %1) coll)))
More idiomatic would be to lazily return all indexes and only ask for the ones you need:
(defn indexes-of [e coll] (keep-indexed #(if (= e %2) %1) coll))
(first (indexes-of "a" (list "a" "a" "b"))) ;; => 0
I'm not sure I understand your question. Do you want the nth letter of each of the strings in a list? That could be accomplished like this:
(map #(nth % 1) (list "abc" "def" "ghi"))
The result is:
(\b \e \h)
Update
After reading your comment on my initial answer, I assume your question is "How do I find the index (position) of a search string in a list?"
One possibility is to search for the string from the beginning of the list and count all the entries you have to skip:
(defn index-of [item coll]
(count (take-while (partial not= item) coll)))
Example: (index-of "b" (list "a" "b" "c")) returns 1.
If you have to do a lot of look-ups, it might be more efficient to construct a hash-map of all strings and their indices:
(def my-list (list "a" "b" "c"))
(def index-map (zipmap my-list (range)))
(index-map "b") ;; returns 1
Note that with the above definitions, when there are duplicate entries in the list index-of will return the first index, while index-map will return the last.
You can use the Java .indexOf method reliably for strings and vectors, but not for lists. This solution should work for all collections, I think:
(defn index-of
"Clojure doesn't have an index-of function. The Java .indexOf method
works reliably for vectors and strings, but not for lists. This solution
works for all three."
[item coll]
(let [v (if
(or (vector? coll) (string? coll))
coll
(apply vector coll))]
(.indexOf coll item)))
Do you mean, how do you get the nth element of a list?
For example, if you want to get the 2nd element on the list (with zero-based index):
(nth (list "a" "b" "c") 2)
yields
"c"
Cat-skinning is fun. Here's a low-level approach.
(defn index-of
([item coll]
(index-of item coll 0))
([item coll from-idx]
(loop [idx from-idx coll (seq (drop from-idx coll))]
(if coll
(if (= item (first coll))
idx
(recur (inc idx) (next coll)))
-1))))
This is a Lispy answer, I suspect those expert in Clojure could do it better:
(defn position
"Returns the position of elt in this list, or nil if not present"
([list elt n]
(cond
(empty? list) nil
(= (first list) elt) n
true (position (rest list) elt (inc n))))
([list elt]
(position list elt 0)))
You seem to want to use the nth function.
From the docs for that function:
clojure.core/nth
([coll index] [coll index not-found])
Returns the value at the index. get returns nil if index out of
bounds, nth throws an exception unless not-found is supplied. nth
also works for strings, Java arrays, regex Matchers and Lists, and,
in O(n) time, for sequences.
That last clause means that in practice, nth is slower for elements "farther off" in sequences, with no guarantee to work quicker for collections that in principle support faster access (~ O(n)) to indexed elements. For (clojure) sequences, this makes sense; the clojure seq API is based on the linked-list API and in a linked list, you can only access the nth item by traversing every item before it. Keeping that restriction is what makes concrete list implementations interchangeable with lazy sequences.
Clojure collection access functions are generally designed this way; functions that do have significantly better access times on specific collections have separate names and cannot be used "by accident" on slower collections.
As an example of a collection type that supports fast "random" access to items, clojure vectors are callable; (vector-collection index-number) yields the item at index index-number - and note that clojure seqs are not callable.
I know this question has been answered a million time but here is a recursive solution that leverages deconstructing.
(defn index-of-coll
([coll elm]
(index-of-coll coll elm 0))
([[first & rest :as coll] elm idx]
(cond (empty? coll) -1
(= first elm) idx
:else (recur rest elm (inc idx)))))
(defn index-of [item items]
(or (last (first (filter (fn [x] (= (first x) item))
(map list items (range (count items))))))
-1))
seems to work - but I only have like three items in my list