14

The only thing I've found that works is

(eval `(vector ,@(mapcar #'1+ [1 2 3 4])))
=> [2 3 4 5]

but that seems far too complicated to be the 'right' way.

18

Use cl-map, instead:

(cl-map 'vector #'1+ [1 2 3 4])

A little extra background: cl-map is the Common Lisp map function that generalizes to sequence types:

(cl-map 'vector #'1+ '[1 2 3 4]) ;; ==> [2 3 4 5]
(cl-map 'list   #'1+ '(1 2 3 4)) ;; ==> (2 3 4 5)
(cl-map 'string #'upcase "abc")  ;; ==> "ABC"

It can also convert between sequence types (eg, here, the input is a list and the output is a vector):

(cl-map 'vector #'1+ '(1 2 3 4)) ;; ==> [2 3 4 5]
  • 1
    18 seconds the 'winner' :) Don't the cl libraries give compiler warnings, though? (Mostly because the FSF is obnoxious?) – Sean Allred Nov 1 '14 at 14:51
  • 1
    FWIW, I think the byte compilation problems were related to the old cl library rather than the rejiggered cl-lib library. I don't for example, get any warnings when I (defun fnx () (cl-map 'vector #'1+ '[1 2 3 4])) and then (byte-compile 'fnx). – Dan Nov 1 '14 at 15:01
  • 2
    Even if you use the compatibility cl-lib, I think you'll get warnings on older emacs (24.2). I wouldn't worry about it though, you have to pick your battles. – Malabarba Nov 1 '14 at 15:07
15

Since I was beat by 18 seconds, here's a simpler and safer way to do it without the cl library. It also doesn't evaluate the elements.

(apply #'vector (mapcar #'1+ [1 2 3 4])) ;; => [2 3 4 5]
  • That's also quite nice! Re: your earlier comment about older Emacs: it seems especially helpful if you have to anticipate legacy users. It seems most helpful if you only have to use it in a couple of spots, at which point you can trade off the slight inconvenience against avoiding the cl-lib dependency. – Dan Nov 1 '14 at 15:27
  • 1
    Very nifty!! I didn't think about using apply. – Sean Allred Nov 1 '14 at 22:51
  • I think (apply #'vector ...) might be ever so slightly faster, but for completeness, it can also be replaced with (vconcat ...). – Basil Nov 12 '18 at 20:03
1

The not so elegant inplace-variant for the case that the original vector is no longer needed afterwards and memory allocation is time-critical (e.g. the vector is big).

(setq x [1 2 3 4])

(cl-loop for var across-ref x do
         (setf var (1+ var)))

The result is stored in x. If you need the form to return x in the end you can add finally return x as follows:

(cl-loop for var across-ref x do
         (setf var (1+ var))
         finally return x)
1

For completeness, using seq:

(require 'seq)
(seq-into (seq-map #'1+ [1 2 3 4]) 'vector)
  • There is a deleted answer from Fólkvangr 2018-11-12 with the exact same seq-into line. The user has deleted his answer for the following reason: " My solution is less relevant because the seq library uses the underlying Common Lisp extensions. – Fólkvangr May 16 at 8:53" – Tobias Jun 19 at 7:28
  • @Tobias I guess I'd disagree with that logic. Everything is going to end up using vconcat or vector anyway, but the different interface paradigms are useful to have on record. – Sean Allred Jun 19 at 10:31
  • No problem. I just saw the deleted answer of Fólkvangr (almost) matching yours and wanted to notify you. For whatever reason seeing deleted answers requires 10000 rep:-(. – Tobias Jun 19 at 11:02
  • @Tobias yeah, I never really understood why those privileges were site-specific :-) – Sean Allred Jun 19 at 11:07
0

You can use loop

(let ((v (vector 1 2 3 4)))
  (dotimes (i (length v))
    (aset v i (1+ (aref v i))))
  v)
;; => [2 3 4 5]

Sometimes you don't want to modify the original vector, you can make a copy

(let* ((v0 (vector 1 2 3 4))
       (v (copy-sequence v0)))
  (dotimes (i (length v))
    (aset v i (1+ (aref v i))))
  (list v0 v))
;; => ([1 2 3 4] [2 3 4 5])

or create a new vector from scratch

(let* ((v0 (vector 1 2 3 4))
       (v (make-vector (length v0) nil)))
  (dotimes (i (length v))
    (aset v i (1+ (aref v0 i))))
  (list v0 v))
;; => ([1 2 3 4] [2 3 4 5])

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.