Jason Sewall <
jason...@gmail.com> writes:
> On Friday, May 17, 2013 8:20:19 AM UTC-7, Jeff Barnett wrote:
>> Jason Sewall wrote, On 5/17/2013 1:15 AM:
>>
>> > Original message deleted - lines too long for me to post, sorry.
>
> Sorry about that; I was using the Google web interface and I assumed
> it could wrap lines for me. Actually, can't your reader wrap it?
>
>> A problem using rotatef or any of the ...f functions is that an array
>> row isn't a place. The expansions depend on a way to access a place as a
>> unit. On the other hand, if you had an array (1D) of lists, each array
>> element, now a row, would be a place. Of course, rotatef expects an
>> explicit list of places as arguments. So in my opinion, what you are
>> trying to do does not fit the ...f function model at all.
>
> I thought my 'sketch' of the way I'd like the code to look like was
> clear, and that I wasn't trying anything like (rotatef (row A 0) (row
> A 1)); even if that were possible, the underlying problem is that I
> can't build a 'call' to rotatef without knowing the number of rows
> I'll be permuting.
Yes, it was clear, and you correctly analysed the problem. The solution
would be indeed to generate the function with the hard-coded row indexes
at run-time, and to compile it before calling it (or have it
interpreted). In both cases, it would be slow.
> I agree that it doesn't fit the *f model (which is actually 'macro
> model'), but it is because there is no 'apply' for macros.
No, it is because macros are designed to work at compilation time. You
could write an apply for macro, but it would still means compilation or
interpretation of a run-time generated function.
> The best solution I know of is to write your own rotatef in the code
> for the job
Definitely, just write your own function.
> (using cl-iterate, and without any pesky error-checking):
>
> (defun rotate-rows (A rows)
> (dotimes (v (array-dimension A 1))
> (iter (with w = (aref A (car rows) v))
> (for r on rows)
> (while (cdr r))
> (setf (aref A (car r) v) (aref A (cadr r) v))
> (finally (setf (aref A (car r) v) w)))))
>
> I guess my point for posting this question here was see if the
> resident paren-ninjas knew a macro-wizardry trick that allows
> something like this to be written in terms of rotatef.
If you have to do permutations of rows a lot, you could instead
permutate the rows, using vectors of vectors.
(defun a->vv (a)
(loop
:with width = (array-dimension a 1)
:with height = (array-dimension a 0)
:with v = (make-array height)
:for i :below height
:do (setf (aref v i) (make-array width
:displaced-to a
:displaced-index-offset (* i width)))
:finally (return v)))
(a->vv #2A((1 2 3) (4 5 6) (7 8 9)))
;; --> #(#(1 2 3) #(4 5 6) #(7 8 9))
(aref #2A((1 2 3) (4 5 6) (7 8 9)) 1 2)
;; --> 6
(aref (aref (a->vv #2A((1 2 3) (4 5 6) (7 8 9))) 1) 2)
;; --> 6
(let ((v (a->vv #2A((1 2 3) (4 5 6) (7 8 9)))))
(rotatef (aref v 2) (aref v 0) (aref v 1))
v)
;; --> #(#(4 5 6) #(7 8 9) #(1 2 3))
Of course, if you also need to use aref a lot on those vectors of
vectors, you can also define:
(defun vvref (vv i j) (aref (aref vv i) j))
(defun (setf vvref) (nv vv i j) (setf (aref (aref vv i) j) nv))
(vvref (a->vv #2A((1 2 3) (4 5 6) (7 8 9))) 1 2)
;; --> 6
--
__Pascal Bourguignon__
http://www.informatimago.com/
A bad day in () is better than a good day in {}.
You can take the lisper out of the lisp job, but you can't take the lisp out
of the lisper (; -- antifuchs