1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-04-30 03:40:34 +02:00

Write a proper vector-map and vector-for-each for (rnrs base)

* module/rnrs/base.scm (vector-map vector-for-each): Rewrite to not be
slow.
* NEWS: Update.
This commit is contained in:
Linus 2021-02-17 22:28:19 +01:00 committed by Andy Wingo
parent 5046385df8
commit 0bd7497b61
2 changed files with 81 additions and 9 deletions

9
NEWS
View file

@ -138,10 +138,6 @@ The Gnulib compatibility library has been updated, for the first time
since 2017 or so. We expect no functional change but look forward to since 2017 or so. We expect no functional change but look forward to
any bug reports. any bug reports.
** Optimized "eof-object?"
This predicate is now understood by the compiler.
* New interfaces and functionality * New interfaces and functionality
** `call-with-port' ** `call-with-port'
@ -180,6 +176,11 @@ See "Syntax Case" in the manual.
See "Syntax Transformer Helpers" in the manual. See "Syntax Transformer Helpers" in the manual.
* Optimizations
** eof-object?
** R6RS vector-map, vector-for-each
* Bug fixes * Bug fixes
** Fix reverse-list->string docstring ** Fix reverse-list->string docstring

View file

@ -1,6 +1,6 @@
;;; base.scm --- The R6RS base library ;;; base.scm --- The R6RS base library
;; Copyright (C) 2010, 2011, 2019 Free Software Foundation, Inc. ;; Copyright (C) 2010, 2011, 2019, 2021 Free Software Foundation, Inc.
;; ;;
;; This library is free software; you can redistribute it and/or ;; This library is free software; you can redistribute it and/or
;; modify it under the terms of the GNU Lesser General Public ;; modify it under the terms of the GNU Lesser General Public
@ -231,10 +231,81 @@
(and (rational-valued? x) (and (rational-valued? x)
(= x (floor (real-part x))))) (= x (floor (real-part x)))))
(define (vector-for-each proc . vecs) ;; Auxiliary procedure for vector-map and vector-for-each
(apply for-each (cons proc (map vector->list vecs)))) (define (vector-lengths who vs)
(define (vector-map proc . vecs) (let ((lengths (map vector-length vs)))
(list->vector (apply map (cons proc (map vector->list vecs))))) (unless (apply = lengths)
(error (string-append (symbol->string who)
": Vectors of uneven length.")
vs))
(car lengths)))
(define vector-map
(case-lambda
"(vector-map f vec2 vec2 ...) -> vector
Return a new vector of the size of the vector arguments, which must be
of equal length. Each element at index @var{i} of the new vector is
mapped from the old vectors by @code{(f (vector-ref vec1 i)
(vector-ref vec2 i) ...)}. The dynamic order of application of
@var{f} is unspecified."
((f v)
(let* ((len (vector-length v))
(result (make-vector len)))
(let loop ((i 0))
(unless (= i len)
(vector-set! result i (f (vector-ref v i)))
(loop (+ i 1))))
result))
((f v1 v2)
(let* ((len (vector-lengths 'vector-map (list v1 v2)))
(result (make-vector len)))
(let loop ((i 0))
(unless (= i len)
(vector-set! result
i
(f (vector-ref v1 i) (vector-ref v2 i)))
(loop (+ i 1)))
result)))
((f v . vs)
(let* ((vs (cons v vs))
(len (vector-lengths 'vector-map vs))
(result (make-vector len)))
(let loop ((i 0))
(unless (= i len)
(vector-set! result
i
(apply f (map (lambda (v) (vector-ref v i)) vs)))
(loop (+ i 1))))
result))))
(define vector-for-each
(case-lambda
"(vector-for-each f vec1 vec2 ...) -> unspecified
Call @code{(f (vector-ref vec1 i) (vector-ref vec2 i) ...)} for each index
in the provided vectors, which have to be of equal length. The iteration
is strictly left-to-right."
((f v)
(let ((len (vector-length v)))
(let loop ((i 0))
(unless (= i len)
(f (vector-ref v i))
(loop (+ i 1))))))
((f v1 v2)
(let ((len (vector-lengths 'vector-for-each (list v1 v2))))
(let loop ((i 0))
(unless (= i len)
(f (vector-ref v1 i) (vector-ref v2 i))
(loop (+ i 1))))))
((f v . vs)
(let* ((vs (cons v vs))
(len (vector-lengths 'vector-for-each vs)))
(let loop ((i 0))
(unless (= i len)
(apply f (map (lambda (v) (vector-ref v i)) vs))
(loop (+ i 1))))))))
(define-syntax define-proxy (define-syntax define-proxy
(syntax-rules (@) (syntax-rules (@)