This is copied to the Gambit mail list (as was the original message).
On May 10, 2007, at 8:32 PM, Marc Feeley wrote:
And what makes you think it is OK to
(define (##vector-copy v) (let* ((n (vector-length v)) (result (make-vector n))) (do ((i (- n 1) (- i 1))) ((< i 0) result) (vector-set! result i (vector-ref v i)))))
"##vector-copy" is supposed to accept any vector-like object as argument, including structures such as readtables. Just chuck that definition.
So how am I supposed to know that ##vector-copy has been defined somewhere in the gambit runtime? In the main gambc-4.0b22 directory I see
euler-7% grep -r vector-copy `find . -name '*.scm'` ./gsc/_gvm.scm: (left-to-schedule (stretchable-vector-copy (bbs-basic-blocks bbs)))) ./gsc/_utils.scm:(define (stretchable-vector-copy sv) ./gsc/_utils.scm:(define (stretchable-vector-copy sv) ./lib/_eval#.scm: '(##vector (##vector-copy ##step-handlers) ./lib/_io.scm: (let ((copy (##vector-copy rt))) ./lib/_io.scm: (##vector-copy obj)) ./lib/gambit#.scm:f32vector-copy ./lib/gambit#.scm:f64vector-copy ./lib/gambit#.scm:s16vector-copy ./lib/gambit#.scm:s32vector-copy ./lib/gambit#.scm:s64vector-copy ./lib/gambit#.scm:s8vector-copy ./lib/gambit#.scm:u16vector-copy ./lib/gambit#.scm:u32vector-copy ./lib/gambit#.scm:u64vector-copy ./lib/gambit#.scm:u8vector-copy ./lib/gambit#.scm:vector-copy
I presume that there's some macro somewhere that expands to a definition of ##vector-copy. Perhaps the compiler should remark if (standard-bindings) or (extended-bindings) are declared and a standard or gambit-specific function is (re-)defined in a user file.
Brad
Afficher les réponses par date
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 10-May-07, at 11:59 PM, Bradley Lucier wrote:
I presume that there's some macro somewhere that expands to a definition of ##vector-copy.
Yes it is the macro define-prim-vector-procedures, which defines [string|vector|u8vector|s8vector|...]-[ref|set!|copy|append|...].
Perhaps the compiler should remark if (standard-bindings) or (extended-bindings) are declared and a standard or gambit-specific function is (re-)defined in a user file.
The compiler would have to keep a database of all the Gambit-specific functions in the runtime. But this would tie the compiler to a specific runtime **implementation** which is not desirable. Gambit is designed to support multiple runtime systems.
There is a simple rule you can follow to avoid this kind of problem. Never redefine or mutate a variable whose name starts with "##" because this is the Gambit internals namespace. I guess the compiler could give a warning for this case.
Marc
Marc Feeley wrote:
Never redefine or mutate a variable whose name starts with "##"
Just a note to Brad: I'm prefixing my own unsafe functions with @ (I've never (mis)used ## for this purpose since I've always been using namespaces for module separation purposes (through chjmodule)).
Christian.
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 11-May-07, at 7:04 AM, Christian Jaeger wrote:
Marc Feeley wrote:
Never redefine or mutate a variable whose name starts with "##"
Just a note to Brad: I'm prefixing my own unsafe functions with @ (I've never (mis)used ## for this purpose since I've always been using namespaces for module separation purposes (through chjmodule)).
Another way to avoid name clashes is to use Gambit's "namespace" declaration. You normally would split the code of a module into 2 files, the interface file and the implementation file. By convention the name of the interface file is the name of the implementation file followed by "#" before the extension. So if you are implementing a module "brad" which exports the functions "foo" and "vector-copy" you would write:
interface file: - ------------------------------------------------------- ;;; File: "brad#.scm" (namespace ("brad#" foo vector-copy)) ;; "exports" - -------------------------------------------------------
implementation file: - ------------------------------------------------------- ;;; File: "brad.scm" (namespace ("brad#")) (##include "~~/lib/gambit#.scm") (include "brad#.scm")
(define (foo x) 999) (define (vector-copy y) (list->vector (baz (vector->list y)))) (define (baz z) (reverse z)) ;; baz is a private function - -------------------------------------------------------
To use this module from the file "client.scm" you need to do:
- ------------------------------------------------------- ;;; File: "client.scm" (include "brad#.scm")
(pp (vector-copy '#(1 2 3))) ;; calls brad#vector-copy - -------------------------------------------------------
So "include"ing an interface file has the effect of "importing" a module's exports.
Marc
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 11-May-07, at 7:34 AM, Marc Feeley wrote:
Another way to avoid name clashes is to use Gambit's "namespace" declaration.
Forgot to mention that, of course, there is also Snow:
- ------------------------------------------------------- ;;; File: "brad.scm" (package* brad/v1.0.0 (provide: (define (foo x)) (define (vector-copy y))))
(define (foo x) 999) (define (vector-copy y) (list->vector (baz (vector->list y)))) (define (baz z) (reverse z)) ;; baz is a private function - -------------------------------------------------------
To use this module from the file "client.scm" you need to do:
- ------------------------------------------------------- ;;; File: "client.scm" (package* client/v1.0.0 (require: brad/v1))
(pp (vector-copy '#(1 2 3))) ;; calls brad#vector-copy - -------------------------------------------------------
Marc Feeley wrote:
Another way to avoid name clashes is to use Gambit's "namespace" declaration.
Sure. That's what I've been meaning to tell Brad Lucier: don't misuse the namespacing feature (by using the ## namespace) as decoration for unsafe function names. Use e.g. @ instead. Example:
(##namespace ("foo#"))
(define (@string-copy! s1 start1 s2 start2 len) (let lp ((i 0)) (if (##fixnum.>= i len) s1 (begin (##string-set! s1 (##fixnum.+ start1 i) (##string-ref s2 (##fixnum.+ start2 i))) (lp (##fixnum.+ i 1))))))
(##namespace (""))
(foo#@string-copy! a b c d)
;; (Or put @string-copy! into the "" or whatever namespace or use snow (or use chjmodule until I've looked into merging with snow))
The @ is my visual indicator that a function does not check the type (or sometimes also the lengths) of it's arguments. It is visually somewhat similar to ##, but doesn't interfere with namespacing.
Christian.
(PS. I've recently referred to "namespaces" using the colon, in the context of SXML templates, example |xhtml:p|; I consider it best to use colons for user visible namespacing, and only use the # based namespacing behind the scence for package separation. This allows flexibility: import some html handling package with a "user-namespace" prefix like |xhtml:| into package foo, |xhtml:p| is then actually |foo#xhtml:p| there, and distinct from someone else writing a bar package who imports some other html handling package providing |p| as |bar#xhtml:p|. (Well in the example I mention from lately those were not actually bindings, but just syntax handled by the custom expander, but I hope the idea gets through.))
On May 11, 2007, at 6:59 AM, Marc Feeley wrote:
There is a simple rule you can follow to avoid this kind of problem. Never redefine or mutate a variable whose name starts with "##" because this is the Gambit internals namespace. I guess the compiler could give a warning for this case.
That would be very nice. I first reported this problem on February 28, 2006:
https://webmail.iro.umontreal.ca/pipermail/gambit-list/2006-February/ 000630.html
That's a long time to be working around a non-bug.
Brad