# [ACCEPTED]-Idiomatic sequence slice in Clojure-slice

You can simplify all the ones using `count`

by 10 using `take-last`

or `drop-last`

instead:

```
(def a (take 10 (iterate inc 1)))
(take 3 a) ; get first 3 elements
(drop 3 a) ; get all elements except the first 3
(drop-last 3 a) ; get all elements except the last 3
(take-last 3 a) ; get last 3 elements
(drop 3 (take 7 a)) ; get 4 elements starting from 3
(drop 3 (drop-last 3 a)) ; get all elements except the first and the last 3
```

And as suggested in the 9 comments below, you can use the `->>`

macro to 8 "thread" several operation together. For 7 example, the last two lines could also be 6 written like this:

```
(->> a (take 7) (drop 3)) ; get 4 elements starting from 3
(->> a (drop-last 3) (drop 3)) ; get all elements except the first and the last 3
```

I think the two methods 5 are both very readable if you are only applying 4 two operations to a list, but when you have 3 a long string like `take`

, `map`

, `filter`

, `drop`

, `first`

then using the 2 `->>`

macro can make the code much easier to 1 read and probably even easier for to write.

Python's notion of a sequence is very different 10 from Clojure's.

In Python,

- a
*sequence*is a*finite ordered set indexed by non-negative numbers*; and - a
*list*is a mutable sequence which you can add slices to or remove slices from.

In Clojure,

- a
*sequence*is an interface supporting`first`

,`rest`

, and`cons`

; - a
*list*is an immutable sequential collection with`cons`

(or`rest`

) adding (or removing)`first`

elements (returning lists so modified, anyway).

The 9 nearest thing in Clojure to a Python list 8 is a *vector*. As Adam Sznajder suggests, you can slice it using `subvec`

, though 7 you can't add or remove slices as you can 6 in Python.

`subvec`

is a fast constant-time operation, whereas 5 `drop`

makes you pay for the number of elements 4 bypassed (`take`

makes you pay for the elements 3 you traverse, but these are the ones you 2 are interested in).

Your examples become 1 ...

```
(def a (vec (range 1 (inc 10))))
(subvec a 0 3)
; [1 2 3]
(subvec a 3)
; [4 5 6 7 8 9 10]
(subvec a 0 (- (count a) 3))
; [1 2 3 4 5 6 7]
(subvec a (- (count a) 3))
; [8 9 10]
(subvec a 3 (+ 3 4))
; [4 5 6 7]
(subvec a 3 (- (count a) 3))
; [4 5 6 7]
```

There is a function `subvec`

. Unfortunately, it 2 only works with vectors so you would have 1 to transform your sequence:

Slicing a sequence is a bit of a "code 7 smell" - a sequence in general is designed 6 for sequential access of items.

If you are 5 going to do a lot of slicing / concatenation, there 4 are much better data structures available, in 3 particular checkout the RRB-Tree vector 2 implementation:

This supports very efficient 1 `subvec`

and `catvec`

operations.

More Related questions

We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.