I am VERY green to Clojure. But I am trying to learn the syntax by creating some functions. I am having issues with the parentheses and syntax in general...
This function is supposed to take a list and a position and return the list with that position removed--but I am getting an error that I don't fully understand. I have done some reading and it seems like its an issue with nested parentheses.. but I'm not sure how to fix it.
Any feedback would be greatly appreciated.
The error:
ClassCastException java.lang.Long cannot be cast to clojure.lang.IPersistentCollection clojure.core/conj (core.clj:83)
The code:
(defn delete-at
"accepts a list and position--returns the list with
value at that position removed"
(
[L, pos]
(cond
(empty? L) nil
(zero? pos) (rest L)
:else (
delete-at (first L) (rest L) (- pos 1))
)
)
([L-new, L2, pos]
(cond
(zero? pos) (conj L-new (rest L2))
:else (
(delete-at (conj L-new (first L2)) (rest L2) (- pos 1))
)
)
)
)
giving it a pass through emacs' formatter makes the problem jump out to me: an extra set of () around the last call to delete-at and the arguments to the first conj call are reversed.
(defn delete-at
"accepts a list and position--returns the list with
value at that position removed"
([L, pos]
(cond
(empty? L) nil
(zero? pos) (rest L)
:else (delete-at (first L) (rest L) (- pos 1))))
([L-new, L2, pos]
(cond
(zero? pos) (conj L-new (rest L2))
:else ((delete-at (conj L-new (first L2)) (rest L2) (- pos 1))))))
when reading Clojure, lots of stacked closing parens ))))) is normal and looks good to the eye (once you get used to it) and stacked opening parens (( jumps out as suspicious. It mainly comes up when you are calling a function that returns a function, and then you want to call the resulting function.
user> (defn delete-at
"accepts a list and position--returns the list with
value at that position removed"
([L, pos]
(cond
(empty? L) nil
(zero? pos) (rest L)
:else (delete-at (first L) (rest L) (- pos 1))))
([L-new, L2, pos]
(cond
(zero? pos) (conj (rest L2) L-new)
:else (delete-at (conj L-new (first L2)) (rest L2) (- pos 1)))))
#'user/delete-at
user> (delete-at [1 2 3] 1)
(1 3)
It's well worth getting emacs setup with cider, clojure-mode, and paredit (paredit is very useful and getting used to it is a bit of an accomplishment) This is a good place to start learning, and many people choose to use a starter kit of some sort such as emacs starter kit or emacs live
Related
Essentially I am trying to remove the first and last element in a list. I have currently been able to determine how to remove the last element in the list but i'm struggling how to remove the first element in the list with the last element in the list.
Here is the code I have so far. Is there a way I can modify my code so I am able to include removing the first element in the list.
(define (rid L)
(cond
[(empty? L) '()]
[(empty? (rest L)) '()]
[(cons (first L) (rid (rest L)))]))
Here is the results I am expecting with my code
(check-expect (rid (list 1 2 3 4 5)) (list 2 3 4))
(check-expect (rid (list "cat" "dog" "giraffe")) (list "dog"))
Just for fun - In Racket you can solve this problem without using explicit recursion. Always try to use existing procedures to solve your problems:
(define (rid L)
(rest (drop-right L 1)))
(rid '(1 2 3 4 5 6))
=> '(2 3 4 5)
With many recursive algorithms, it is not uncommon to actually implement them with two procedures: one to set up the initial conditions and a second one to do the actual recursion, like so:
(define (rid-inner li)
(cond
[(empty? li) '()]
[(empty? (rest li)) '()]
[(cons (first li) (rid-inner (rest li)))]))
(define (rid1 L)
(define r (if (empty? L) '() (rest L)))
(rid-inner r))
With (define r (if (empty? L) '() (rest L))) we strip off the first element of the list; no recursion is actually necessary for this step. Then we define the same procedure you had before with a different name and call it with our new list that already has the first element stripped off. If you want the first element stripped off, just strip off the first element; don't overthink it :) .
In a language like Racket that allows closures and nested procedures, you don't actually even need to define both procedures at the top "global" module scope; just define your recursive procedure inside your initial procedure and call it from there. Example:
(define (rid2 L)
(define r (if (empty? L) '() (rest L)))
(define (rid-inner li)
(cond
[(empty? li) '()]
[(empty? (rest li)) '()]
[(cons (first li) (rid-inner (rest li)))]))
(rid-inner r))
Another, somewhat cleaner, way to do the above is to use a named let, which allows us to simultaneously set up our initial conditions, create a named procedure, and then call that procedure immediately from within itself. We do that like so:
(define (rid3 L)
(let rid-inner ([li (if (empty? L) '() (rest L))])
(cond
[(empty? li) '()]
[(empty? (rest li)) '()]
[(cons (first li) (rid-inner (rest li)))])))
To those unfamiliar with Racket, Scheme, or a related Lisp, the named let in rid3 may be more cryptic at first since it is really doing two or three things at once. You can find the docs for it here. Don't be fooled though, it works exactly the same as rid2. Named let exists precisely because this pattern is so common.
(define (rid L)
(if (< (length L) 3)
'()
(reverse (rest (reverse (rest L))))))
;;; recursion inside and more general
;;; you can setting which position 0~n-1 you want to remove
(define (rid-v2 L)
(local ((define remove-index-list (list 0 (- (length L) 1)))
(define (auxf L k)
(cond
[(empty? L) '()]
[(memq k remove-index-list) (auxf (rest L) (+ k 1))]
[else (cons (first L)
(auxf (rest L) (+ k 1)))])))
(auxf L 0)))
tail call recursive version
(define (rid lst (acc '()))
(cond ((empty? lst) acc)
((empty? (cdr lst)) (cdr (reverse acc)))
(else (rid (cdr lst) (cons (car lst) acc)))))
with elementar lisp (not the most efficient)
(define (rid1 lst)
(cdr (reverse (cdr (reverse lst))))
I have a deeply nested list and I want to delete a given element from all its occurrences in the list. I have this code:
(defn eliminate [value lst]
(defn sub-eliminate [lst]
(def currentItem (first lst))
(if-not (empty? lst)
(if (seq? currentItem)
(cons (sub-eliminate currentItem) (sub-eliminate (rest lst)))
(if (= value currentItem)
(sub-eliminate (rest lst))
(cons currentItem (sub-eliminate (rest lst)))
)
)
'()
)
)
(sub-eliminate lst)
)
But, it doesn't delete at inner levels. Why??
My guess is that you're using vectors as sequences.
(eliminate 3 [3 3])
;()
(eliminate 3 [3 [3]])
;([3])
This would have been trivial to find had you shown us an example: tut, tut!
What's going on?
Although vectors are seqable, they are not sequences:
(seq? [])
;false
At the outer level, you treat lst as a sequence, so first and rest work, since they wrap their argument in an implicit seq. But seq? will fail on any immediately enclosed vector, and those further in won't even be seen.
If you replace seq? with sequential?, lists and vectors will work.
(sequential? [])
;true
More serious, as #noisesmith noted, is your use of def and defn at inner scope. Replace them with let or letfn.
You could also improve your style:
Replace (if-not (empty? lst) ... ) with (if (seq lst) ...).
Use cond to flatten your nested ifs. This requires inverting
the test in (1), so removes the need for it.
Use recur for the tail-recursive case where you find value, as
#Mark does.
If you don't want to see the result, look away now:
(defn eliminate [value lst]
(letfn [(sub-eliminate [lst]
(let [current-item (first lst)]
(cond
(empty? lst) '()
(sequential? current-item) (cons (sub-eliminate current-item)
(sub-eliminate (rest lst)))
(= value current-item) (recur (rest lst))
:else (cons current-item (sub-eliminate (rest lst))))))]
(sub-eliminate lst)))
There is a remaining tender spot:
You invoke (first lst) before you know that lst is not empty. No
harm done: you'll just get nil, which you ignore.
An Alternative Apporach using Destructuring
You can often use destructuring to abbreviate recursive processing of sequences. I'd be inclined to express your function thus:
(defn eliminate [x xs]
((fn rem-x [xs]
(if-let [[y & ys] (seq xs)]
(if (= x y)
(recur ys)
(cons
(if (sequential? y) (rem-x y) y)
(rem-x ys)))
()))
xs))
For the sake of learning take a look at this function:
(define rember*
(lambda (x l)
(cond ((null? l) '())
((atom? (car l))
(if (eq? (car l) x)
(rember* x (cdr l))
(cons (car l)
(rember* x (cdr l)))))
(else (cons (rember* x (car l))
(rember* x (cdr l)))))))
This is a simple recursive function from book 'The Little Schemer', which is a good source to learn how to write such recursive functions.
Let's see if we can translate it into Clojure:
(defn rember* [x l]
(cond (empty? l) '()
(seq? (first l)) (cons (rember* x (first l))
(rember* x (rest l)))
:else (if (= (first l) x)
(recur x (rest l))
(cons (first l)
(rember* x (rest l))))))
user> (rember* 'x '((x y) x (z (((((x))))))))
;; => ((y) (z ((((()))))))
(defn expel [victim xs]
(mapcat (fn [x]
(cond
(sequential? x) [(expel victim x)]
(= x victim) []
:else [x]))
xs))
I'm trying to add a given variable x to a list L. Both of which are parameters of the function ADDV. The code I have so far is as follows:
(defun addV(L x)
(cond
((eq L nil) nil)
((eq (cdr L) nil) (list(+(car L) x)))
(+ x (first(last L)))
(butlast L)
(append L x) ) )
With the parameters
L = '(1 2 3 4)
x = 2
When the statement: (+ x (first(last L)))) is evaluated, it's value is 4. The final goal should be
L = '(1 2 3 6)
I'm not sure what I'm doing wrong. Any help would be greatly appreciated. Thanks.
Your code is badly formatted. Re-indenting, we get
(defun addV(L x)
(cond
((eq L nil)
nil)
((eq (cdr L) nil)
(list (+ (car L) x)))
(+
x
(first (last L)))
(butlast
L)
(append
L
x) ) )
do you see the problem now?
Since (not +) is NIL, the corresponding clause in the COND form is entered. Its body's forms (x and (first (last L))) are evaluated for effects, of which there are none. Then the last form's value is returned.
What you evidently wanted it to be, is
(defun addV (L x)
(cond
((eq L nil)
nil)
((eq (cdr L) nil)
(list (+ (car L) x)))
(T
(append
(butlast L)
(list (+ x (first (last L))))))))
Coincidentally, the 2nd clause it completely unnecessary and may just be omitted, making it
(defun addV (L x)
(if (not (null L))
(append (butlast L)
(list (+ x (first (last L)))))))
If you can do this destructively, then you can use incf and last:
(defun increment-last (list x)
(prog1 list ; return the list
(incf (first (last list)) x)))
If you do need to make a new list, you'll have to walk to the end of the list to get to the last element. While you're doing that, you could keep track of the elements you've already seen (in reverse order) and efficiently use that reverse order list to construct the new list for you using nreconc:
(defun plus-last (list x)
(do ((list list (rest list))
(rhead '() (list* (first list) rhead)))
((endp (rest list))
(nreconc rhead (list (+ x (first list)))))))
CL-USER> (plus-last '(1 2 3 4) 2)
(1 2 3 6)
If you're not so comfortable with do syntax, you could use a tail recursive function, too (which some Common Lisp implementations can optimize into a loop):
(defun plus-last (list x)
(labels ((pl (list rhead)
(if (endp (rest list))
(nreconc rhead (list (+ x (first list))))
(pl (rest list)
(list* (first list) rhead)))))
(pl list '())))
You could also use loop, and express the logic pretty clearly:
(defun plus-last (list x)
(loop for (a . b) on list
if (null b) collect (+ a x)
else collect a))
This could also be done with maplist:
(defun plus-last (list x)
(maplist (lambda (list)
(if (endp (rest list))
(+ x (first list))
(first list)))
list))
I'm working on 4clojure problems and a similar issue keeps coming up. I'll write a solution that works for all but one of the test cases. It's usually the one that is checking for lazy evaluation. The solution below works for all but the last test case. I've tried all kinds of solutions and can't seem to get it to stop evaluating until integer overflow. I read the chapter on lazy sequences in Joy of Clojure, but I'm having a hard time implementing them. Is there a rule of thumb I'm forgetting, like don't use loop or something like that?
; This version is non working at the moment, will try to edit a version that works
(defn i-between [p k coll]
(loop [v [] coll coll]
(let [i (first coll) coll (rest coll) n (first coll)]
(cond (and i n)
(let [ret (if (p i n) (cons k (cons i v)) (cons i v))]
(recur ret coll))
i
(cons i v )
:else v))))
Problem 132
Ultimate solution for those curious:
(fn i-between [p k coll]
(letfn [(looper [coll]
(if (empty? coll) coll
(let [[h s & xs] coll
c (cond (and h s (p h s))
(list h k )
(and h s)
(list h )
:else (list h))]
(lazy-cat c (looper (rest coll))))
))] (looper coll)))
When I think about lazy sequences, what usually works is thinking about incremental cons'ing
That is, each recursion step only adds a single element to the list, and of course you never use loop.
So what you have is something like this:
(cons (generate first) (recur rest))
When wrapped on lazy-seq, only the needed elements from the sequence are realized, for instance.
(take 5 (some-lazy-fn))
Would only do 5 recursion calls to realize the needed elements.
A tentative, far from perfect solution to the 4clojure problem, that demonstrates the idea:
(fn intercalate
[pred value col]
(letfn [(looper [s head]
(lazy-seq
(if-let [sec (first s)]
(if (pred head sec)
(cons head (cons value (looper (rest s) sec)))
(cons head (looper (rest s) sec)))
(if head [head] []))))]
(looper (rest col) (first col))))
There, the local recursive function is looper, for each element tests if the predicate is true, in that case realizes two elements(adds the interleaved one), otherwise realize just one.
Also, you can avoid recursion using higher order functions
(fn [p v xs]
(mapcat
#(if (p %1 %2) [%1 v] [%1])
xs
(lazy-cat (rest xs) (take 1 xs))))
But as #noisesmith said in the comment, you're just calling a function that calls lazy-seq.
I'm trying to implement deep-reverse in clojure. If lst is (1 (2 (3 4 5)) (2 3)), it should return ((3 2) ((5 4 3) 2) 1). This is what I have so far:
defn dRev [lst]
( if (= lst ())
nil
( if (list? (first lst))
( dRev (first lst) )
( concat
( dRev (rest lst)) (list (first lst))
)
)
)
)
However, my implementation only works if the nested list is the last element, but the resulted list is also flattened.
For eg: (dRev '(1 2 (3 4)) will return (4 3 2 1).
Otherwise, for eg: (dRev '(1 (2 3) 4)) will return (3 2 1) only.
I hit this brick wall for a while now, and I can't find out the problem with my code. Can anyone please help me out?
The other answer gave you the best possible implementation of a deep-reverse in Clojure, because it uses the clojure.walk/postwalk function which generalizes the problem of deep-applying a function to every element of a collection. Here I will instead walk you through the problems of the implementation you posted.
First, the unusual formatting makes it hard to spot what's going on. Here's the same just with fixed formatting:
(defn dRev [lst]
(if (= lst ())
nil
(if (list? (first lst))
(dRev (first lst))
(concat (dRev (rest lst))
(list (first lst))))))
Next, some other small fixes that don't yet fix the behaviour:
change the function name to conform to Clojure conventions (hyphenation instead of camel-case),
use the usual Clojure default name for collection parameters coll instead of lst,
use empty? to check for an empty collection,
return () in the default case because we know we want to return a list instead of some other kind of seq,
and use coll? instead list? because we can just as well reverse any collection instead of just lists:
(If you really want to reverse only lists and leave all other collections as is, reverse the last change.)
(defn d-rev [coll]
(if (empty? coll)
()
(if (coll? (first coll))
(d-rev (first coll))
(concat (d-rev (rest coll))
(list (first coll))))))
Now, the formatting fix makes it obvious what's the main problem with your implementation: in your recursive call ((d-rev (first coll)) resp. (dRev (first lst))), you return only the result of that recursion, but you forget to handle the rest of the list. Basically, what you need to do is handle the rest of the collection always the same and only change how you handle the first element based on whether that first element is a list resp. collection or not:
(defn d-rev [coll]
(if (empty? coll)
()
(concat (d-rev (rest coll))
(list (if (coll? (first coll))
(d-rev (first coll))
(first coll))))))
This is a working solution.
It is terribly inefficient though, because the concat completely rebuilds the list for every element. You can get a much better result by using a tail-recursive algorithm which is quite trivial to do (because it's natural for tail-recursion over a sequence to reverse the order of elements):
(defn d-rev [coll]
(loop [coll coll, acc ()]
(if (empty? coll)
acc
(recur (rest coll)
(cons (if (coll? (first coll))
(d-rev (first coll))
(first coll))
acc)))))
As one final suggestion, here's a solution that's halfways towards the one from the other answer by also solving the problem on a higher level, but it uses only the core functions reverse and map that applies a function to every element of sequence but doesn't deep-recurse by itself:
(defn deep-reverse [coll]
(reverse (map #(if (coll? %) (deep-reverse %) %) coll)))
You can build what you are writing with clojure.walk/postwalk and clojure.core/reverse. This does a depth-first traversal of your tree input and reverses any seq that it finds.
(defn dRev [lst]
(clojure.walk/postwalk #(if (seq? %) (reverse %) %) lst))
Here is my version of the problem, if you enter something like this:
(deep-reverse '(a (b c d) 3))
It returns
=> '(3 (d c b) a)
The problem is taken from Ninety-Nine Lisp Problems
My code ended up like this, though, they might be better implementations, this one works fine.
(defn deep-reverse
"Returns the given list in reverse order. Works with nested lists."
[lst]
(cond
(empty? (rest lst)) lst
(list? (first lst)) (deep-reverse(cons (deep-reverse (first lst)) (deep-reverse (rest lst))))
:else
(concat (deep-reverse (rest lst)) (list (first lst)))))
Hope this is what you were looking for!