Finding optimal row sequence for a melody on 5-row Bayan Accordion, v2.0 Another try at this problem in LISP. This time rather than generating every possible row combination for the melody I tried to calculate the best combination directly. Unfortunately there's a problem - the output is a messy list full of vectors and single values. Is there a good way to concatenate vectors together with value between them?

(proclaim '(type (vector (vector symbol 4) 3) *rows*))
(defparameter *rows* #( #(:c :ds :fs :a) #(:cs :e :g :as) #(:d :f :gs :b)))

(defun row-for-note (note)
  (declare (symbol note)) 
  "Returns the lower row on which a note is played."
  (position-if (lambda (row) (find note row)) *rows*))

(defun equivalent-row (row)
  (declare (fixnum row))
  "Returns the equivalent upper row to a given lower row."
  (case row (1 -2) (2 -1) (0 0)))

(defun rows-for-notelist (notelist)
  (declare ((vector symbol) notelist)) 
  "Returns the sequence of lower rows on which a sequence of notes are played."
  (map 'vector #'row-for-note notelist))

(defun flip-sequence (rowlist)
  (declare ((vector fixnum) notelist))
  "Returns the sequence of upper rows equivalent to a sequence of lower rows."
  (map 'vector #'equivalent-row rowlist))

(defun vector-last (thevec)
  (declare (vector thevec))
  "Returns the last element of a vector."
  (elt thevec (- (length thevec) 1)))

(defun vector-first (thevec)
  (declare (vector thevec))
  "Returns the first element of a vector."
  (elt thevec 0))

(defun should-flip-block (rowlist)
  (declare ((vector fixnum) rowlist))
  "Determines if a sequence of rows starts and ends on row 2 or not."
  "These sequences are more easily played on upper rows because they will then start and end on row -1."
  (if (= (length rowlist) 0) nil 
    (let* ((exithigh (= (vector-last rowlist) 2))
           (enterhigh (= (vector-first rowlist) 2)))  
      (and exithigh enterhigh))))


(defun flip-block-if-should (rowlist)
  (declare ((vector number) rowlist))
  (if (should-flip-block rowlist) (flip-sequence rowlist) (eval rowlist)))

(defun optimal-sequence (notelist)
  (declare ((vector symbol) notelist))
  (let* ((baserows (rows-for-notelist notelist))
         (blocks (split-sequence '(0) baserows))
         (flipped (mapcar #'flip-block-if-should blocks))) 
    (loop for x in flipped collect x collect 0)))
To concatenate vectors, you can do this:

(apply #'concatenate 'vector 
       (mapcar (lambda (x) 
                 (typecase x 
                   (vector x) 
                   (t (vector x))))
               list-of-vectors-or-numbers))


PS. Since this is CR, here are some notes on your code:


Doc string (no more than one, but it can be multi-line!) usually comes before the declarations. Please see Syntactic Interaction of Documentation Strings and Declarations: (defun foo (...) (declare ...) "doc") will define a function foo which has no docstring and return "doc", while (defun foo (...) "doc" (declare ...)) will declare a function with a docstring, returning nil.
(declare ((vector number) rowlist)) should be (declare (type (vector number) rowlist)).
elt should not be used if you know that the object is a vector; use aref instead.
There is no need to bind exithigh and enterhigh in should-flip-block since they are used just once.
declaim is, I think, more "idiomatic" than proclaim in your case.
It is clearer to use 1- in vector-last.