guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: exporting GOOPS generic functions, was: [ANN] guile-file-names 0.2


From: Mark H Weaver
Subject: Re: exporting GOOPS generic functions, was: [ANN] guile-file-names 0.2
Date: Fri, 24 May 2019 21:21:12 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/26.2 (gnu/linux)

Hi Brandon,

Brandon Invergo <address@hidden> writes:

> I can try something like this:
>
>     (let ((old-absolute-file-name? absolute-file-name?))
>       (define-generic absolute-file-name?)
>       (define-method (absolute-file-name? (f <file-name>))
>         (proper-list? (route f)))
>       (define-method (absolute-file-name? (f <string>))
>         (old-absolute-file-name? f)))
>
> But that strangely gives me this upon compiling the module:
>
>     While compiling expression:
>     Unbound variable: absolute-file-name?
>
> I'm not sure what to make of that.  A compile-time error, but why?

It's because you tried to export a binding that doesn't exist at the
top-level of your module.  That's because the definitions you gave above
are not in a top-level context.  They are local variables.

One easy solution is to use Guile's (@ module var) syntax to explicitly
reference a variable from a particular module.  For example:

    (define-method (absolute-file-name? (f <string>))
      ((@ (guile) absolute-file-name?) f)))

Here, the reference (@ (guile) absolute-file-name?) explicitly asks for
the binding from the (guile) module.

Another option is to *rename* bindings while importing them, using
either #:prefix or #:select.  For example, see
module/system/repl/command.scm in Guile's source, which includes the
following lines in its 'define-module' form:

  #:use-module ((ice-9 pretty-print) #:select ((pretty-print . pp)))
  #:use-module ((system vm inspect) #:select ((inspect . %inspect)))

Those modules include 'pretty-print' and 'inspect' among their exported
bindings, but the bindings will be visible as 'pp' and '%inspect' within
command.scm.

When using #:select, the imports are limited to the bindings you
specifically asked for.  Sometimes it's more convenient to add a prefix
to every binding imported from a given module, like the following
example from Guile's module/ice-9/streams.scm:

(define-module (ice-9 streams)
  #:use-module ((srfi srfi-41) #:prefix srfi-41:)

Bindings can also be renamed when they are exported, and (ice-9 streams)
does this.

> ps - You say that I should use #:export and #:replace, but according to
> the manual, #:replace "[exports] all identifiers in LIST ... and mark[s]
> them as “replacing bindings”."  So, shouldn't be unnecessary to put the
> symbol in both lists?

Yes, you're right.  If a binding is listed in the #:replace list,
there's no need to add it to the #:export list.

* * *

Finally, I wanted to mention that, in my opinion, the degree to which
this library modifies existing Guile bindings is regrettable.  I'm glad
that Guile is hackable in this way, but I generally prefer to avoid
libraries that do these kinds of hacks, unless there is a compelling
reason to justify it.

In my opinion, it would be better to use plain strings as the
representation for file names, and instead provide procedures to
conveniently manipulate those strings.

Consider:

(1) Your <file-name> objects are much larger than plain strings in terms
of their memory use.

(2) Every time you pass a <file-name> object to a file system primitive,
it needs to be converted back into a string, which makes them slower to
use as well.

(3) If Guile ever extends our file system primitives in the future,
e.g. by adding additional keyword or optional arguments, your library
will likely cause problems with that.  For example, a few years ago we
added the #:guess-encoding and #:encoding keyword arguments to
'open-file' and several other similar procedures.

Also, I had a question: a big part of your library seems to be aimed at
supporting Windows drive letters and separators.  Have tested your
library on Guile running on Windows?

One thing I know is that there's no need for us to use backslash as the
file separator on Windows.  My understanding is that the POSIX
compatibility layer, used in Guile's Windows port, automatically handles
interpreting forward slashes as a directory separator.  Guile already
includes code to try to ensure that from the perspective of Guile code,
we will see and use forward slashes uniformly, regardless of platform.
For example, see 'scm_i_mirror_backslashes' in libguile/load.c and its
associated comment.

      Regards,
        Mark



reply via email to

[Prev in Thread] Current Thread [Next in Thread]