I am using a function from an external library returning a vector of four numbers and I want to access these values directly like it would be possible with destructuring-bind. See this pointless example:
(defun a-vector ()
(vector 1 2 3 4))
(defun a-list ()
(list 1 2 3 4))
(destructuring-bind (a b c d)
(a-list)
(format t "~D ~D ~D ~D~%" a b c d))
(destructuring-bind (a b c d)
(coerce (a-vector) 'list)
(format t "~D ~D ~D ~D~%" a b c d))
If I coerce the vector into a list it is possible and as performance isn't a problem here, it is maybe fine. But I was wondering if there is a more simple way?
You can bind variables to each cell as follows:
(defmacro with-aref ((&rest indices) array &body body)
(let ((a (gensym)))
`(let ((,a ,array))
(symbol-macrolet
,(loop
for n from 0
for i in indices
collect (list i `(aref ,a ,n)))
,#body))))
You would use it as follows:
(with-aref (w x y z) vec
(setf w (+ x y z)))
With a bit more work, you can also support indices and different categories of accessors. Let's say each binding is a triple (i n k) where i is an identifier, n a number (or nil) that represents the numerical index and k is either :place, :value or nil; :place binds the symbol with symbol-macrolet, :value just binds it with let.
First, let's help the user by providing shortcut notations:
x stands for (x nil nil)
(x o) either stands for (x o nil) or (x nil o), depending on whether option o is a number or a symbol (at macroexpansion time).
Besides, we may want to automatically ignore the nil identifier, the empty symbol || or symbols starting with an underscore (e.g. _, _var).
Here is the normalization function:
(defun normalize-index (index)
(flet ((ret (i n k)
(let ((ignored (or (null i)
(string= i "")
(char= #\_ (char (string i) 0)))))
(list (if ignored (gensym) i) n k ignored))))
(let ((index (alexandria:ensure-list index)))
(typecase index
(null (ret nil nil nil))
(cons (destructuring-bind (i &optional n (k nil kp)) index
(if kp
(ret i n k)
(etypecase n
(symbol (ret i nil n))
((integer 0) (ret i n nil))))))))))
We can apply this normalization to a list of indices, and keep track of ignored symbols:
(defun normalize (indices)
(loop
for i in indices
for norm = (normalize-index i)
for (index number kind ignore) = norm
collect norm into normalized
when ignore
collect index into ignored
finally (return (values normalized ignored))))
Then, we take care of nil numbers in normalized entries. We want the indices to increase from the last used index, or be given explicitly by the user:
(defun renumber (indices)
(loop
for (v n k) in indices
for next = nil then (1+ index)
for index = (or n next 0)
collect (list v index k)))
For example:
(renumber (normalize '(a b c)))
((A 0 NIL) (B 1 NIL) (C 2 NIL))
(renumber (normalize '((a 10) b c)))
((A 10 NIL) (B 11 NIL) (C 12 NIL))
(renumber (normalize '((a 10) (b 3) c)))
((A 10 NIL) (B 3 NIL) (C 4 NIL))
We do the same for the kind of variable we bind:
(defun rekind (indices)
(loop
for (v n k) in indices
for next = nil then kind
for kind = (or k next :place)
collect (list v n kind)))
For example:
(rekind (normalize '(a b c)))
((A NIL :PLACE) (B NIL :PLACE) (C NIL :PLACE))
(rekind (normalize '(a (b :value) c)))
((A NIL :PLACE) (B NIL :VALUE) (C NIL :VALUE))
Finally, all those steps are combined in parse-indices:
(defun parse-indices (indices)
(multiple-value-bind (normalized ignored) (normalize indices)
(values (rekind (renumber normalized))
ignored)))
Finally, the macro is as follows:
(defmacro with-aref ((&rest indices) array &body body)
(multiple-value-bind (normalized ignored) (parse-indices indices)
(labels ((ignored (b) (remove-if-not #'ignoredp (mapcar #'car b)))
(ignoredp (s) (member s ignored)))
(loop
with a = (gensym)
for (i n k) in normalized
for binding = `(,i (aref ,a ,n))
when (eq k :value) collect binding into values
when (eq k :place) collect binding into places
finally (return
`(let ((,a ,array))
(let ,values
(declare (ignore ,#(ignored values)))
(symbol-macrolet ,places
(declare (ignore ,#(ignored places)))
,#body))))))))
For example:
(let ((vec (vector 0 1 2 3 4 5 6 7 8 9 10)))
(prog1 vec
(with-aref ((a 2) (b :value) c _ _ d (e 0) (f 1)) vec
(setf a (list a b c d e f)))))
The above is macroexpanded as:
(LET ((VEC (VECTOR 0 1 2 3 4 5 6 7 8 9 10)))
(LET ((#:G1898 VEC))
(LET ((#:G1901 VEC))
(LET ((B (AREF #:G1901 3))
(C (AREF #:G1901 4))
(#:G1899 (AREF #:G1901 5))
(#:G1900 (AREF #:G1901 6))
(D (AREF #:G1901 7))
(E (AREF #:G1901 0))
(F (AREF #:G1901 1)))
(DECLARE (IGNORE #:G1899 #:G1900))
(SYMBOL-MACROLET ((A (AREF #:G1901 2)))
(DECLARE (IGNORE))
(LET* ((#:G19011902 #:G1901)
(#:NEW1 (LIST (AREF #:G1901 2) B C D E F)))
(FUNCALL #'(SETF AREF) #:NEW1 #:G19011902 2)))))
#:G1898))
It produces the following result
#(0 1 (2 3 4 7 0 1) 3 4 5 6 7 8 9 10)
coredump's answer is lovely. This is a variant of it which binds variables rather than accessors, and also lets you optionally specify indices. So
(with-vector-elements ((a 3) b) x
...)
will bind a to the result of (aref x 3) and b to the result of (aref x 4), for instance.
This is really only useful over coredump's answer if you're intending to (a) not write back to the vector and (b) use the bindings a lot, so you want to avoid a lot of possible arefs (which I don't think compilers can generally optimize away without some fairly strong assumptions).
(defmacro with-vector-elements ((&rest indices) vector &body forms)
(let ((canonical-indices
(loop with i = 0
for index in indices
collect (etypecase index
(symbol
(prog1
`(,index ,i)
(incf i)))
(cons
(destructuring-bind (var idx) index
(assert (and (symbolp var)
(typep idx '(and fixnum (integer 0))))
(var idx) "Invalid index spec")
(prog1
index
(setf i (1+ idx))))))))
(vname (gensym "V")))
`(let ((,vname ,vector))
(let ,(loop for (var index) in canonical-indices
collect `(,var (aref ,vname ,index)))
,#forms))))
There is also a package called metabang-bind - with nickname bind - in which the function bind can handle much more destructuring situations:
(ql:quickload :metabang-bind)
(in-package :metabang-bind)
(bind ((#(a b c) #(1 2 3)))
(list a b c))
;; => (1 2 3)
If not using in-package, you can call the function as bind:bind.
The function bind you can think of roughly as a destructuring-let* (similar idea to clojure's let, however not so clean in syntax but understandable because it has also to handle structs and classes and also values).
All the other use cases it can handle are described here.
Related
A library function returns seven values. I only need the first four and the last one. Is there a more elegant way than:
(multiple-value-bind (a b c d e f g)
(library-call)
(declare (ignore e f))
(rest-of-code a b c d g))
You can keep a "mvb" look and feel with the metabang-bind library (a let on steroïds which allows more destructing and bindings) and use the _ placeholder.
Below, we "bind" on a multiple-value with `(:values …):
(metabang.bind:bind (((:values _ b) (values 1 2)))
b)
;; => 2
You can use MULTIPLE-VALUE-LIST and SUBSEQ:
(defun library-call () (apply #'values '(a b c d e f g)))
(defun rest-of-code (&rest rest)
(print rest))
(let ((lst (multiple-value-list (library-call))))
(apply #'rest-of-code
`(,#(subseq lst 0 4) ,(car (last lst)))))
=> (A B C D G)
I think the only way to do this without consing some intermediate structure is what you suggest. Of course this is easy to define syntax for if it happens a lot.
As an example here's a thing called mvb which is like multiple-value-bind except that variables whose name is "_" are ignored (so this doesn't rely on exporting a symbol _). This relies on org.tfeb.hax.collecting: it could be redone not to.
(defmacro mvb (bindings form &body forms)
(multiple-value-bind (vars ignores)
(with-collectors (var ignore)
(let ((i 1))
(dolist (b bindings)
(typecase b
(symbol
(cond
((string= (symbol-name b) "_")
(let ((g (make-symbol (format nil "_~D" i))))
(incf i)
(var g)
(ignore g)))
(t
(var b))))
(t
(error "mutant binding ~A" b))))))
`(multiple-value-bind ,vars ,form
,#(if ignores `((declare (ignore ,#ignores))))
,#forms)))
With this your call would be
(mvb (a b c d _ _ g)
(library-call)
(rest-of-code a b c d g))
Which turns into
(multiple-value-bind (a b c d #:|_1| #:|_2| g)
(library-call)
(declare (ignore #:|_1| #:|_2|))
(rest-of-code a b c d g))
Note that my binding macro now supports something similar to this, using nil as the 'don't bind anything' placeholder:
(binding
(bind/values (a nil b) (values 1 2 3))
(print a)
(bind c (+ a b))
c)
nil is a nice choice I think because it can't break any existing program since nil can't be bound.
I am writing an iterative version of the Pell numbers and I need to print out the output of the numbers in a list. I have done everything right up until the list. Instead of returning a flat list, it returns individual lists of the Pell numbers.
I tried to append all the individual lists but it does not work. What am I missing?
(defun iterPell (n)
(let ((a 0) (b 1) (c n))
(loop for i from 2 to n do
(setq c (+ a (* 2 b))
a b
b c))
c))
(dotimes (n 7)
(write(append(list(iterPell n))))
)
>>(0)(1)(2)(5)(12)(29)(70)
(loop for n from 0 to 7
collect (iterPell n))
;; => (0 1 2 5 12 29 70 169)
(let ((res)) ;; initialize collector = ((res nil))
(dotimes (n 7)
(setf res (cons (iterPell n) res))) ;; setf the result new-value-consed
(nreverse res)) ;; revert it (after all consing to beginning of list)
;; => (0 1 2 5 12 29 70 169)
;; or write recursive function
(defun apply-on-0-to-n (n func acc)
(cond ((zerop n) (cons (funcall func 0) acc))
(t (apply-on-0-to-n (1- n) func (cons (funcall func n) acc)))))
(apply-on-0-to-n 7 #'iterPell '())
;; => (0 1 2 5 12 29 70 169)
In order to understand functional programing, please help me to write a function that output nth element of a list,
Allowed command:
define lambda cond else empty empty? first rest cons list
list? = equal? and or not + - * / < <= > >=
Sample output:
(fourth-element '(a b c d e)) => d
(fourth-element '(x (y z) w h j)) => h
(fourth-element '((a b) (c d) (e f) (g h) (i j))) => (list 'g 'h)
or ‘(g h)
(fourth-element '(a b c)) => empty
I could write this in python, but I am not family with racket syntax,
def element(lst, x=0):
counter = x;
if (counter >= 3):
return lst[0]
else:
return element(lst[1:],x+1)
a = [1,2,3,4,5,6]
print(element(a))
The Output is 4
Comparing with code above in python. What is equivalent behavior in function that create local variable counter. What is "keyword" for return
It looks like you came up with an answer of your own. Nice work! I would recommend a more generic nth procedure that takes a counter as an argument. This allows you to get any element in the input list
(define (nth lst counter)
(cond ((null? lst) (error 'nth "index out of bounds"))
((= counter 0) (first lst))
(else (nth (rest lst) (- counter 1)))))
Now if you want a procedure that only returns the 4th element, we create a new procedure which specializes the generic nth
(define (fourth-element lst)
(nth lst 3))
That's it. Now we test them out with your inputs
(define a `(1 2 3 (4 5) 7))
(define b `(1 2 3))
(define c `((a b)(c d)(e f)(g h)(i j)))
(define d `(a b c))
(fourth-element a) ; '(4 5)
(fourth-element b) ; nth: index out of bounds
(fourth-element c) ; '(g h)
(fourth-element d) ; nth: index out of bounds
Note, when the counter goes out of bounds, I chose to raise an error instead of returning a value ("empty") like your program does. Returning a value makes it impossible to know whether you actually found a value in the list, or if the default was returned. In the example below, notice how your procedure cannot differentiate the two inputs
(define d `(a b c))
(define e `(a b c ,"empty"))
; your implementation
(fourth-element e) ; "empty"
(fourth-element d) ; "empty"
; my implementation
(fourth-element e) ; "empty"
(fourth-element d) ; error: nth: index out of bounds
If you don't want to throw an error, there's another way we can encode nth. Instead of returning nth element, we can return the nth pair whose head contains the element in question.
Below, nth always returns a list. If the list is empty, no element was found. Otherwise, the nth element is the first element in the result.
(define (nth lst counter)
(cond ((null? lst) '())
((= counter 0) lst)
(else (nth (rest lst) (- counter 1)))))
(define (fourth-element lst)
(nth lst 3))
(define a `(1 2 3 (4 5) 7))
(define b `(1 2 3))
(define c `((a b)(c d)(e f)(g h)(i j)))
(define d `(a b c))
(define e `(a b c ,"empty"))
(fourth-element a) ; '((4 5) 7)
(fourth-element b) ; '()
(fourth-element c) ; '((g h) (i j))
(fourth-element d) ; '()
(fourth-element e) ; '("empty")
Hopefully this gets you to start thinking about domain (procedure input type) and codomain (procedure output type).
In general, you want to design procedures that have natural descriptions like:
" nth takes a list and a number and always returns a list" (best)
" nth takes a list and a number and returns an element of the list or raises an exception if the element is not found" (good, but now you must handle errors)
Avoid procedures like
" nth takes a list and a number and returns an element of the list or a string literal "empty" if the element is not found" (unclear codomain)
By thinking about your procedure's domain and codomain, you have awareness of how your function will work as it's inserted in various parts of your program. Using many procedures with poorly-defined domains lead to disastrous spaghetti code. Conversely, well-defined procedures can be assembled like building blocks with little (or no) glue code necessary.
Here is how to write it in Python:
def nth(lst, idx=0):
if (len(lst) == 0):
return "empty"
elif (idx == 0):
return lst[0]
else:
return nth(lst[1:], idx - 1)
nth([1,2,3], 1)
# ==> 2
def fourth-element(lst):
return nth(lst, 4)
Same in Scheme/Racket:
(define (nth lst idx)
(cond ((empty? lst) empty) ; more effiecent than (= (length lst) 0)
((= idx 0) (first lst))
(else (nth (rest lst) (- idx 1))))
(nth '(1 2 3) 1)
; ==> 2
(define (fourth-element lst)
(nth lst 4))
There is no keyword for return. Every form returns the last evaluated code:
(if (< 4 x)
(bar x)
(begin
(display "print this")
(foo x)))
This if returns either the result of (bar x) or it prints "print this" then returns the result of (foo x). The reason is that for the two outcomes of the if they are the tail expressions.
(define (test x)
(+ x 5)
(- x 3))
This function has two expressions. The first is dead code since it has no side effect and since it's not a tail expression, but the (- x 3) is what this function returns.
(define (test x y)
(define xs (square x))
(define ys (square y))
(sqrt (+ xs ys)))
This has 3 expressions. The first two has side effects that it binds two local variables while the third uses this to compute the returned value.
(define a `(1 2 3 (4 5) 7))
(define b `(1 2 3))
(define c `((a b)(c d)(e f)(g h)(i j)))
(define d `(a b c))
(define (my-lst-ref lst counter)
(cond[(>= counter 3) (first lst)]
[else (my-lst-ref (rest lst)(+ counter 1))]
)
)
(define (fourth-element lst)
(cond[(>= (list-length lst) 4) (my-lst-ref lst 0)]
[else "empty"]))
(fourth-element a)
(fourth-element c)
(fourth-element d)
Output:
(list 4 5)
(list 'g 'h)
"empty"
I am by most standards a novice lisp programmer, however, I don't feel what I am trying to do is particularly complex and I do not understand why it is not working.
I am trying to create a database of events that occur throughout time and are connected based on how they appear in relation to one another. This concept is highly experimental and not what I'm looking for feedback on.
The idea is to generate a random name for the event (which are referred to as symbols in the program, bad style, I know), generate a random number of appearances for the event (which have a start time, a duration, and a period of time that elapses until the event occurs again). Then once I have created a random number of event types, and a random number of appearances for each, I'd like to organize them in a list in chronological order, but I am not getting very far because the name I am creating is generating a type error in sym-aprs-h, in the sym-appearances accessor function. It is trying to tell me that it is not of expected type sym, but when I run tests such as calling type-of on ran-sym-name it returns symbol. So I really have no idea what is going on.
(defun initialize ()
(defvar *alphabet* '#(a b c d e f g h i j k l m n o p q r s t u v w x y z))
(defvar *symbol-names* nil)
(defvar *moment-chain* nil))
(defun ran-let ()
(Coerce (aref *alphabet* (random 26)) 'character))
(defun ran-sym-name ()
(intern (coerce (list (ran-let) (ran-let) (ran-let) (ran-let) (ran-let) (ran-let)) 'string)))
(defstruct sym
(name nil)
(appearances nil)
(connections nil))
(defun ran-sym-gen ()
(let ((x (ran-sym-name)))
(cond ((member x *Symbol-names*) (ran-sym-gen))
(t (push x *Symbol-names*)(make-sym :name x)(sym-aprs x)))))
(defun sym-aprs-h (s tm n)
(let ((dr (+ 1 (random 7200))))
(cond ((= n 0) nil)
(t (push (list tm dr nil) (sym-appearances s)) (push (list tm dr s nil) *moment-chain*) (sym-aprs-h s (+ tm dr (random 14400)) (- n 1))))))
(defun sym-aprs (s)
(sym-aprs-h s (get-universal-time) (+ 1 (random 101))))
(defun mchain-org ()
(sort *moment-chain* #'< :key #'car))
(defun mchain-con (n)
(cond ((= 0 n) nil)
(t (ran-sym-gen) (mchain-con (- n 1)))))
As I said I'm new to the language and teaching myself by taking on a smidge more than I can handle. Any constructive criticism would be appreciated, however, I'm primarily interested in getting sym-appearances to not generate a type error.
(defun initialize ()
(defvar *alphabet* '#(a b c d e f g h i j k l m n o p q r s t u v w x y z))
(defvar *symbol-names* nil)
(defvar *moment-chain* nil))
DEFVAR does not belong inside a DEFUN. DEFVAR is a toplevel macro.
(defun ran-let ()
(Coerce (aref *alphabet* (random 26)) 'character))
Coerce over and over.
(defun ran-sym-name ()
(intern (coerce (list (ran-let) (ran-let) (ran-let) (ran-let) (ran-let) (ran-let))
'string)))
Just pick characters from a string and append them.
(defstruct sym
(name nil)
(appearances nil)
(connections nil))
(defun ran-sym-gen ()
(let ((x (ran-sym-name)))
(cond ((member x *Symbol-names*) (ran-sym-gen))
(t (push x *Symbol-names*)
(make-sym :name x)
(sym-aprs x)))))
The result of (make-sym :name x) disappears in the Lisp nirvana. You pass the symbol to sym-aprs is that really what you want?
(defun sym-aprs-h (s tm n)
(let ((dr (+ 1 (random 7200))))
(cond ((= n 0) nil)
(t (push (list tm dr nil) (sym-appearances s))
(push (list tm dr s nil) *moment-chain*)
(sym-aprs-h s (+ tm dr (random 14400)) (- n 1))))))
(defun sym-aprs (s)
(sym-aprs-h s (get-universal-time) (+ 1 (random 101))))
(defun mchain-org ()
(sort *moment-chain* #'< :key #'car))
(defun mchain-con (n)
(cond ((= 0 n) nil)
(t (ran-sym-gen) (mchain-con (- n 1)))))
Why not use DOTIMES or LOOP?
Style: you might want to check the types of s and other variables. It might also be useful to use speaking names and/or documentation.
If you look at the code in a week you won't be able to tell what it is supposed to do...
You also want to format the code differently. See my version.
I am learning Lisp. I have implemented a Common Lisp function that merges two strings that are ordered alphabetically, using recursion. Here is my code, but there is something wrong with it and I didn't figure it out.
(defun merge (F L)
(if (null F)
(if (null L)
F ; return f
( L )) ; else return L
;else if
(if (null L)
F) ; return F
;else if
(if (string< (substring F 0 1) (substring L 0 1)
(concat 'string (substring F 0 1)
(merge (substring F 1 (length F)) L)))
(
(concat 'string (substring L 0 1)
(merge F (substring L 1 (length L)) ))
))))
Edit :
I simply want to merge two strings such as the
inputs are string a = adf and string b = beg
and the result or output should be abdefg.
Thanks in advance.
Using string< is an overkill, char< should be used instead, as shown by Kaz. Recalculating length at each step would make this algorithm quadratic, so should be avoided. Using sort to "fake it" makes it O(n log n) instead of O(n). Using concatenate 'string all the time probably incurs extra costs of unneeded traversals too.
Here's a natural recursive solution:
(defun str-merge (F L)
(labels ((g (a b)
(cond
((null a) b)
((null b) a)
((char< (car b) (car a))
(cons (car b) (g a (cdr b))))
(t (cons (car a) (g (cdr a) b))))))
(coerce (g (coerce F 'list) (coerce L 'list))
'string)))
But, Common Lisp does not have a tail call optimization guarantee, let alone tail recursion modulo cons optimization guarantee (even if the latter was described as early as 1974, using "Lisp 1.6's rplaca and rplacd field assignment operators"). So we must hand-code this as a top-down output list building loop:
(defun str-merge (F L &aux (s (list nil)) ) ; head sentinel
(do ((p s (cdr p))
(a (coerce F 'list) (if q a (cdr a)))
(b (coerce L 'list) (if q (cdr b) b ))
(q nil))
((or (null a) (null b))
(if a (rplacd p a) (rplacd p b))
(coerce (cdr s) 'string)) ; FTW!
(setq q (char< (car b) (car a))) ; the test result
(if q
(rplacd p (list (car b)))
(rplacd p (list (car a))))))
Judging by your comments, it looks like you're trying to use if with a series of conditions (like a series of else ifs in some other languages). For that, you probably want cond.
I replaced that if with cond and cleaned up some other errors, and it worked.
(defun empty (s) (= (length s) 0))
(defun my-merge (F L)
(cond
((empty F)
(if (empty L)
F
L))
((empty L)
F)
(t
(if (string< (subseq F 0 1) (subseq L 0 1))
(concatenate 'string (subseq F 0 1) (my-merge (subseq F 1 (length F)) L))
(concatenate 'string (subseq L 0 1) (my-merge F (subseq L 1 (length L))))))))
Your test case came out as you wanted it to:
* (my-merge "adf" "beg")
"abdefg"
There were quite a few good answers, so why would I add one more? Well, the below is probably more efficient then the other answers here.
(defun merge-strings (a b)
(let* ((lena (length a))
(lenb (length b))
(len (+ lena lenb))
(s (make-string len)))
(labels
((safe-char< (x y)
(if (and x y) (char< x y)
(not (null x))))
(choose-next (x y)
(let ((ax (when (< x lena) (aref a x)))
(by (when (< y lenb) (aref b y)))
(xy (+ x y)))
(cond
((= xy len) s)
((safe-char< ax by)
(setf (aref s xy) ax)
(choose-next (1+ x) y))
(t
(setf (aref s xy) by)
(choose-next x (1+ y)))))))
(choose-next 0 0))))
(merge-strings "adf" "beg")
It is more efficient specifically in the sense of memory allocations - it only allocates enough memory to write the result string, never coerces anything (from list to string or from array to string etc.) It may not look very pretty, but this is because it is trying to do every calculation only once.
This is, of course, not the most efficient way to write this function, but programming absolutely w/o efficiency in mind is not going to get you far.
A recursive way to do it (fixed according to comment- other solutions can get an IF form as well).
(defun merge-strings (a b)
(concatenate 'string
(merge-strings-under a b)))
(defun merge-strings-under (a b)
(when (and
(= (length a)
(length b))
(> (length a) 0))
(append (if (string< (aref a 0) (aref b 0))
(list (aref a 0) (aref b 0))
(list (aref b 0) (aref a 0)))
(merge-strings-under (subseq a 1)
(subseq b 1)))))
Here's a iterative way to do it.
(concatenate 'string
(loop for i across "adf" for j across "beg" nconc (list i j)))
Note that these rely on building the string into a list of characters, then vectorizing it ( a string is a vector of characters).
You can also write a more C-esque approach...
(defun merge-strings-vector (a b)
(let ((retstr (make-array (list (+
(length a)
(length b)))
:element-type 'character)))
(labels ((merge-str (a b i)
(when (and
(= (length a)
(length b))
(/= i (length a)))
(setf (aref retstr (* 2 i)) (aref a i))
(setf (aref retstr (1+ (* 2 i))) (aref b i))
(merge-str a b (1+ i)))))
(merge-str a b 0)
retstr)))
Note that this one - unlike the other 2 - has side effects within the function. It also, imo, is more difficult to understand.
All 3 take varying numbers of cycles to execute on SBCL 56; each seems to take between 6K and 11K on most of my trials. I'm not sure why.