For example, in David's final gist, we have:
(defprotocol ISlice
(-shift [this]))
(deftype Slice [start end]
ISlice
(-shift [_] (Slice. (inc start) (inc end)))
IFn
(-invoke [_ x]
(cond
(string? x) (.substring x start end)
(vector? x) (subvec x start end))))
(def s (Slice. 0 5))
(def v ["List Processing" [0 1 2 3 4 5 6]])
(map s v)
;; >> ("List " [0 1 2 3 4])
(map (-shift s) v)
;; >> ("ist P" [1 2 3 4 5])
When I think there's a good case to be made for the clarity of this alternative: slice = (start, end) ->
(list) ->
if typeof list is 'string'
list.substring start, end
else
list.slice start, end
vector = ["List Processing", [0, 1, 2, 3, 4, 5, 6]]
vector.map slice 0, 5
# ["List ",[0,1,2,3,4]]
vector.map slice 1, 6
# ["ist P",[1,2,3,4,5]]
... but with careful compile-to-JS languages, it's pretty great that each can do it their own way, and the resulting code can play nicely together.