I'm stuck trying to write a Clojure function that takes a span from a collection or vector.
For example I'd like to manipulate a collection such as
(:a :b :c :d :e :f :g :h)
by taking the second element through the fifth in steps of two.
Thus, outputting
(:b :d).
If you haven't figured it out by now, here is a function that does what you want.
(defn take-span
[start end step coll]
(take-nth step (take (- end start) (drop start coll))))
(take-span 1 4 2 '(:a :b :c :d :e :f :g :h))
Hope this helps!
Have a look at (take-nth n coll) function
(take-nth n coll)
Returns a lazy seq of every nth item in coll.
user=> (take-nth 2 (range 10))
(0 2 4 6 8)
It is not an exact match for your question but it is a good starting point for inspiration.
Of course, you can check the source code via:
(source take-nth)
Related
Given x and y, both designed to match a map with the same matching clauses. The only difference is in the order of the clauses:
(ns so.example
(:require
[clojure.core.match :refer [match]]))
(defn x [m]
(match m
{:a _} :a0
{:a _ :b _} :ab0))
(defn y [m]
(match m
{:a _ :b _} :ab0
{:a _} :a0))
I want to match {:a 1 :b 2}:
(x {:a 1 :b 2})
;=> :a0
(y {:a 1 :b 2})
;=> :ab0
The function y has produced the expected result for the given map.
Admittedly I may not understand how the algorithm works but I was under the impression that clojure.core.match would somehow work out that {:a _ :b _} is somewhat more specific than {:a _} and would therefore try that first.
Which is why I'm surprised to see that the order of the matching clauses seems to matter.
Why is that or what am I doing wrong?
The way the match calculates a pattern score can't discern {:a _} from {:a _ :b _}, which it probably should. What you can do instead, is to tell it specifically there is no :b in the map.
(m/match [{:a 1 :b 2}]
[({:a _} :only [:a])] :a0
[{:a _ :b _}] :ab0)
from the sample code of core.match, url:https://github.com/clojure/core.match/wiki/Basic-usage
(let [x {:a 1 :b 1}]
(match [x]
[{:a _ :b 2}] :a0
[{:a 1 :b 1}] :a1
[{:c 3 :d _ :e 4}] :a2
:else nil))
;=> :a1
why we can just match a `x' ? any reason why we can't do that ?
(let [x {:a 1 :b 1}]
(match x
{:a _ :b 2} :a0
{:a 1 :b 1} :a1
{:c 3 :d _ :e 4} :a2
:else nil))
;=> :a1
You can; or at least that's what I'm inferring from reading the source and documentation of match.
The source of match starts with the lines:
(defmacro match
. . .
[vars & clauses]
(let [[vars clauses]
(if (vector? vars) ; If it's a vector...
[vars clauses] ; leave it alone,
[(vector vars) ; else wrap it in a vector
. . .]
The documentation also contains the bit:
. . . Optionally may take a single
var not wrapped in a vector, questions then need not be wrapped in a
vector.
So why are they showing examples with vectors? Likely for consistency of the syntax. That likely help comprehension in a simple, basic overview like that. Switching back and forth between using and not using a vector would necessitate explaining when a vector is necessary, and that would detract from the main point of the page.
Edit: Actually, it does explicitly explain on that page at the top that you can match on an unwrapped value. You can find it by searching for match x on that page.
In Scheme, I'm running (quote (+ 2 3)) returns (+ 2 3). From what I understood, the quote just told Scheme to not evaluate my expression for some purpose. I'm trying to make the list (+ 2 3) without the use of quote. So I tried:
Typed: (cons '+' (cons 2 (cons 3 '())))
Scheme's return:(+ cons 2 (cons 3 (quote ())))
- I don't understand why I got this return value. I was hoping for (+ 2 3)
Typed: (cons '+' (2,3))
Scheme's return:(+ 2 3)
- I don't understand how this worked. So, is (cons '+' (2,3)) the same as (quote (+ 2 3))?
'expression is the same a (quote expression) and it becomes expression unevaluated.
When you write (cons '+ '(cons 2 (cons 3 '()))) you are quoting both + and the second argument, (cons 2 (cons 3 '())). The ' has no end marker.
When displaying pairs a Lisp system will default to displaying pairs with a pair tail as a list if you wondered why it didn't turn into (+ . (cons 2 (cons 3 (quote ()))))
An implementation can choose how to display '(quote ()) and ''(). Mine show '() while yours show (quote ()). They represent the exact same so it's not really different in other things than the visualization.
`(1 , 2) is the same as (list '1 2) since you are unquoting 2. Luckily for you it's a number and it always evaluates to itself. It might be that you though the comma was some sort of separation between elements, but it's not. It's just to simplify writing a large data structure where only a few elements are variable.
(define (test e)
`(a list with ,e representing some wanted structure))
(test 'test) ; ==> (a list with test representing some wanted structure)
I know that in Lisp a list must end with nil, but expression like
(print (cons 1 (cons 3 2)))
does not throw any errors. It prints:
(1 3 . 2)
Is it correct?
I'm using GNU Clisp.
In Lisp, a proper list ends with NIL, but you also have improper lists. One kind of improper list is a list where the last cons cell has an atom other than NIL in its CDR. (1 3 . 2) is exactly such an improper list.
You can even have improper lists where it doesn't have a last cell at all. CARs and CDRs are basically just pointers, so you can have circular lists!
In Common Lisp (which is the language CLISP implements), many standard functions won't work with improper lists as arguments.
What you have is a dotted list, which is a kind of improper list.
A chain of CONS cells where the last CDR is NIL is a proper list.
It's also interesting to note what happens when evaluating proper lists:
;; A proper list
(cons '+ (cons 5 (cons 10 '())))
⇒ (+ 5 10)
(eval (+ 5 10))
⇒ 15
versus evaluating dotted lists:
;; A dotted list
(cons '+ (cons 5 (cons 10 5000)))
⇒ (+ 5 10 . 5000)
(eval (+ 5 10 . 5000))
⇒ 15
It ignores the terminating atom.
When you iterate over a list you know you reached the end when you hit nil.
What you have is a list with a car and a point pair.
How would I get something similar to the following?:
(evaluate-text "(+ 1 2)") ; resolves to 3
(load-string "(+ 1 2)")
user> (eval (read-string "(+ 1 2)"))
3
You probably shouldn't ever need to do this. Macros and fns make this kind of thing unnecessary 99% of the time. This is quite brittle, and can be unsafe if these strings are coming from user input, and so on.
How similar does it have to be? Clojure's eval works on lists, so:
(eval (list + 1 2)) #=> 3