William James
4/3/2015 3:23:00 AM
Pascal Bourguignon wrote:
> > I wonder why they didn't allow the loop macro to genericaly iterate over a
> > sequence.
>
> Because there's no efficient generic iteration operator.
>
> You can use ELT, but it's O(N) on lists, for each access, therefore
> O(Nn++) for the loop.
>
>
> > Can't be much more of a syntactic mess than it is right now anyways =P
>
> This is not a syntax problem. You get the sequence at run time, so
> you have to choose between CDR or AREF at run time.
>
> You can do your own GLOOP (or checkout ITERATE or some similar package)
> which would map:
>
> (gloop for item inside sequence do (stuff item))
>
> to:
>
> (if (listp sequence)
> (loop for item in seqeunce do (stuff item))
> (loop for item on seqeunce do (stuff item)))
>
>
> Or you can write:
>
> (loop with iterator = (iterator container)
> for item = (iterator-next iterator)
> while item
> do (stuff item))
>
>
> (defun iterator-next (iterator) (funcall iterator))
>
> (defmethod iterator ((self null))
> (lambda () (values nil t)))
>
> (defmethod iterator ((self cons))
> (lambda () (let ((done (not self))) (values (pop self) done))))
>
> (defmethod iterator ((self vector))
> (let ((i 0))
> (lambda ()
> (if (< i (length self))
> (multiple-values-prog1 (values (aref self i) nil) (incf i))
> (values nil t)))))
>
> ;; and you can add a method of any kind of container...
When using Scheme's SRFI-42, it is optional to specify
the type of container.
Gauche Scheme:
(use srfi-42) ; do-ec
(define big-size 999888)
(for-each
(lambda (xs) (print "\nTiming without and with a specified type.")
(time (do-ec (: x xs) (identity x)))
(cond ((list? xs) (time (do-ec (:list x xs) (identity x))))
((vector? xs) (time (do-ec (:vector x xs) (identity x))))
(else (time (do-ec (:string x xs) (identity x))))))
(list
(make-list big-size 2)
(make-vector big-size 2)
(make-string big-size #\2)))
Timing without and with a specified type.
;(time (do-ec (: x xs) (identity x)))
; real 0.156
; user 0.156
; sys 0.000
;(time (do-ec (:list x xs) (identity x)))
; real 0.062
; user 0.063
; sys 0.000
Timing without and with a specified type.
;(time (do-ec (: x xs) (identity x)))
; real 0.156
; user 0.140
; sys 0.000
;(time (do-ec (:vector x xs) (identity x)))
; real 0.078
; user 0.094
; sys 0.000
Timing without and with a specified type.
;(time (do-ec (: x xs) (identity x)))
; real 0.219
; user 0.250
; sys 0.000
;(time (do-ec (:string x xs) (identity x)))
; real 0.125
; user 0.125
; sys 0.000