I thought that data/collection was meant to allow a set of functions to be collection type agnostic. There must be some syntactic trick that is not documented for doing so.
#lang racket/base
(require racket/flonum)
(require data/collection)
(define (vector-apply vec)
(data/collection:apply fl+ vec))
(define-syntax-rule (bench vector-sum)
(begin
(define (vector-bench len fval)
(let ((vec (make-flvector len fval)))
(vector-sum vec)))
(define (repeat n len fval)
(for ([_ (in-range n)])
(vector-bench len fval)))
(collect-garbage)
; use as follows:
'vector-sum
(time (repeat 1000 100000 0.5)) ; create vector 1000 times and sum
))
(#%declare #:unsafe)
(bench vector-apply)
Results in this error:
(bench vector-apply)
apply: contract violation
expected: sequence?
given: (flvector 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5...
in: the last argument of
(-> procedure? any/c ... sequence? any)
contract from:
<pkgs>/collections-lib/data/collection/collection.rkt
blaming: /Users/lewis/Library/CloudStorage/Dropbox/lisp-play/gambit-play/bench-new-racket.rkt
(assuming the contract is correct)
at: <pkgs>/collections-lib/data/collection/collection.rkt:52:3
[,bt for context]
Don't understand why. The documentation for sequences in 4.16.1 clearly says that flvectors, which I assume are mutable, can be sequences.
The Generic Collections library (actually called collections-lib and incorporated in code as data/collections[1] is less clear on the point. There is a reference to an any/c thing, which would appear to be an "object" that satisfies a flat-contract. So much conceptual overhead here... So, does an flvector satisfy a flat contract?
Lots of documentation on how to make specific kinds of contracts. Not a lot on how to test if an object satisfies a contract--it must be there, but it lost in the deep topic.
Without sorting out the docs, these simple examples confirm that an flvector fails to satisfy the contract:
(apply fl+ (flvector 1.0 2.0 3.0)) ; -> contract failure
(apply fl+ #(1.0 2.0 3.0)) ; -> 6.0 hallelujah!
So, should I conclude there is no efficiently implemented "apply" for flvectors? For/fold works great but apply would be more concise (uh-oh: I too despite typing!). I am about to try a named let.
As a general comment, Scheme not embracing method dispatch (a poor choice of concept names from Julia--it should just be called function/operator overloading...) and including the requisite functions in its libraries is a pretty big gap. Function and method overloading (with suitable contracts) would be far more useful than any CLOS-like thing: and much easier to use and likely more performant. This is seemingly too modern a feature though sbcl goes a bit further in providing it.
[1] This use of 3 names for what is surely e the same thing is unnecessarily confusing. Experienced programmers seem to viciously despise typing, so either use a short string everywhere or just bite the bullet and use the long string for clarity: typing is not that hard, especially as these strings will be entered only once in a module or source file...