* Aliasing an identifier
@ 2018-11-15 16:55 Marc Nieper-Wißkirchen
2018-11-17 15:17 ` Marc Nieper-Wißkirchen
0 siblings, 1 reply; 3+ messages in thread
From: Marc Nieper-Wißkirchen @ 2018-11-15 16:55 UTC (permalink / raw)
To: guile-devel
[-- Attachment #1: Type: text/plain, Size: 1666 bytes --]
I would like to alias an identifier in Guile. By this, I mean the
following: Given a bound identifier `x', I want to lexically introduce
another identifier `y' with the same binding as `x' so that `x' and `y'
become `free-identifier=?'.
The following is one use case: I have written a macro `custom-quasiquote`,
which has a similar syntax and does similar things as `quasiquote' does.
Because I would like to use the special reader syntax for `quasiquote', I
would do:
(letrec-syntax ((quasiquote <custom-quasiquote-transformer>))
<body>)
In the <body>, whenever I write ``<template>', my
<custom-quasiquote-transformer> is being applied to <template>.
There may be parts in the <body> where I would like to use Scheme's
quasiquotation. One try is to surround these parts with:
(let-syntax ((quasiquote (identifier-syntax scheme-quasiquote)))
<expression>)
Here, `scheme-quasiquote' is bound to `quasiquote' as exported by
`(guile)'. However, this solution is not correct as the `quasiquote' local
to <expression> is not `free-identifier=?' to `scheme-quasiquote'. Thus
quasiquotations containing quasiquotes (that should become auxiliary
syntax) won't work right.
What I really need is to make the inner `quasiquote' a true alias of
`scheme-quasiquote' (or rather to restore the binding of `quasiquote' in
<expression> to what the binding outside the outer `letrec-syntax' was).
Chez Scheme has `alias' for this purpose:
https://cisco.github.io/ChezScheme/csug9.5/syntax.html#./syntax:h10.
What can I do in Scheme? If this is currently impossible, please consider
this post as a feature request for `alias' or a similar binding construct.
:-)
-- Marc
[-- Attachment #2: Type: text/html, Size: 2221 bytes --]
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: Aliasing an identifier
2018-11-15 16:55 Aliasing an identifier Marc Nieper-Wißkirchen
@ 2018-11-17 15:17 ` Marc Nieper-Wißkirchen
2018-11-18 11:15 ` Marc Nieper-Wißkirchen
0 siblings, 1 reply; 3+ messages in thread
From: Marc Nieper-Wißkirchen @ 2018-11-17 15:17 UTC (permalink / raw)
To: guile-devel
[-- Attachment #1: Type: text/plain, Size: 3379 bytes --]
Am Do., 15. Nov. 2018 um 17:55 Uhr schrieb Marc Nieper-Wißkirchen <
marc.nieper@gmail.com>:
> I would like to alias an identifier in Guile. By this, I mean the
> following: Given a bound identifier `x', I want to lexically introduce
> another identifier `y' with the same binding as `x' so that `x' and `y'
> become `free-identifier=?'.
>
> The following is one use case: I have written a macro `custom-quasiquote`,
> which has a similar syntax and does similar things as `quasiquote' does.
> Because I would like to use the special reader syntax for `quasiquote', I
> would do:
>
> (letrec-syntax ((quasiquote <custom-quasiquote-transformer>))
> <body>)
>
> In the <body>, whenever I write ``<template>', my
> <custom-quasiquote-transformer> is being applied to <template>.
>
> There may be parts in the <body> where I would like to use Scheme's
> quasiquotation. One try is to surround these parts with:
>
> (let-syntax ((quasiquote (identifier-syntax scheme-quasiquote)))
> <expression>)
>
> Here, `scheme-quasiquote' is bound to `quasiquote' as exported by
> `(guile)'. However, this solution is not correct as the `quasiquote' local
> to <expression> is not `free-identifier=?' to `scheme-quasiquote'. Thus
> quasiquotations containing quasiquotes (that should become auxiliary
> syntax) won't work right.
>
> What I really need is to make the inner `quasiquote' a true alias of
> `scheme-quasiquote' (or rather to restore the binding of `quasiquote' in
> <expression> to what the binding outside the outer `letrec-syntax' was).
>
> Chez Scheme has `alias' for this purpose:
> https://cisco.github.io/ChezScheme/csug9.5/syntax.html#./syntax:h10.
>
> What can I do in Scheme? If this is currently impossible, please consider
> this post as a feature request for `alias' or a similar binding construct.
> :-)
>
Typo. "What can I in GUILE?" was the question I intended to ask. :-)
I gave it a try to implement `define-alias' in Guile. My first
approximation to a solution was to add a clause like
((define-alias-form)
(let ((id (wrap value w mod))
(label (id-var-name e w mod)))
(extend-ribcage! ribcage id label)
(parse (cdr body) (cons id ids) labels var-ids vars vals bindings)))
to `expand-body' in `psyntax.scm'. (A similar clause is added to
`expand-top-sequence' and `syntax-type' is extended to recognize
`define-alias' and return `define-alias-form' for the type.)
With identifiers lexically bound in the same module, my change does what it
is supposed to do. The following test passes:
(pass-if "alias is free-identifier=?"
(let ((x #t))
(define-syntax foo
(syntax-rules (x)
((foo x) #t)
((foo _) #f)))
(let ()
(define-alias y x)
(foo y))))
My code, however, doesn't work when the aliased identifier is global and/or
comes from another module: The following test fails:
(pass-if-equal "alias is free-identifier=? with globals"
'(1 5)
(let ()
(define-alias comma unquote)
`(1 (comma (+ 2 3)))))
I see that my attempt to bind the identifier `y' to `x's label (if given
`(define-alias y x)') is too naive. I have taken a look at `free-id=?' and
`resolve-identifier' in `psyntax.scm', but the way modules are handled in
`psyntax.scm' is still new to me. Thus I'm glad about any hints.
-- Marc
[-- Attachment #2: Type: text/html, Size: 5460 bytes --]
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: Aliasing an identifier
2018-11-17 15:17 ` Marc Nieper-Wißkirchen
@ 2018-11-18 11:15 ` Marc Nieper-Wißkirchen
0 siblings, 0 replies; 3+ messages in thread
From: Marc Nieper-Wißkirchen @ 2018-11-18 11:15 UTC (permalink / raw)
To: guile-devel
[-- Attachment #1.1: Type: text/plain, Size: 5094 bytes --]
Am Sa., 17. Nov. 2018 um 16:17 Uhr schrieb Marc Nieper-Wißkirchen <
marc.nieper@gmail.com>:
> Am Do., 15. Nov. 2018 um 17:55 Uhr schrieb Marc Nieper-Wißkirchen <
> marc.nieper@gmail.com>:
>
>> I would like to alias an identifier in Guile. By this, I mean the
>> following: Given a bound identifier `x', I want to lexically introduce
>> another identifier `y' with the same binding as `x' so that `x' and `y'
>> become `free-identifier=?'.
>>
>> Typo. "What can I in GUILE?" was the question I intended to ask. :-)
>
> I gave it a try to implement `define-alias' in Guile. My first
> approximation to a solution was to add a clause like
>
> ((define-alias-form)
> (let ((id (wrap value w mod))
> (label (id-var-name e w mod)))
> (extend-ribcage! ribcage id label)
> (parse (cdr body) (cons id ids) labels var-ids vars vals bindings)))
>
> to `expand-body' in `psyntax.scm'. (A similar clause is added to
> `expand-top-sequence' and `syntax-type' is extended to recognize
> `define-alias' and return `define-alias-form' for the type.)
>
> With identifiers lexically bound in the same module, my change does what
> it is supposed to do. The following test passes:
>
> (pass-if "alias is free-identifier=?"
> (let ((x #t))
> (define-syntax foo
> (syntax-rules (x)
> ((foo x) #t)
> ((foo _) #f)))
> (let ()
> (define-alias y x)
> (foo y))))
>
> My code, however, doesn't work when the aliased identifier is global
> and/or comes from another module: The following test fails:
>
> (pass-if-equal "alias is free-identifier=? with globals"
> '(1 5)
> (let ()
> (define-alias comma unquote)
> `(1 (comma (+ 2 3)))))
>
> I see that my attempt to bind the identifier `y' to `x's label (if given
> `(define-alias y x)') is too naive. I have taken a look at `free-id=?' and
> `resolve-identifier' in `psyntax.scm', but the way modules are handled in
> `psyntax.scm' is still new to me. Thus I'm glad about any hints.
>
The problem seems to lie in the code of `free-id=?' in `psyntax.scm'.
`free-id=?' contains the following clause:
((symbol? ni)
;; `i' is not lexically bound. Assert that `j' is free,
;; and if so, compare their bindings, that they are either
;; bound to the same variable, or both unbound and have
;; the same name.
(and (eq? nj (id-sym-name j))
(let ((bi (id-module-binding i mi)))
(if bi
(eq? bi (id-module-binding j mj))
(and (not (id-module-binding j mj))
(eq? ni nj))))
(eq? (id-module-binding i mi) (id-module-binding j mj))))
`free-id=?' is called by the transformer of `quasiquote' to check whether
`comma' and `unquote' are `free-identifier=?'. If I understand the code of
`free-id=?' correctly, `ni' and `nj' become the labels of `comma' and
`unquote', respectively, which are both the same due to how I have tried to
implement `define-alias'. These labels are symbols because they are not
lexically bound but (imported) globals (from the module `(guile)').
The code from `free-id=?' cited above looks up the module bindings of
`comma' and `unquote' but not by their (symbol) labels, but by their
identifier names. This fails because there is no global identifier bound
with the name `comma'. (Independently, too things about the code look
strange to me. Firstly, the code seems to make the relation defined by
`free-id=?' non-symmetric: For the second identifier `j', it is checked
whether its symbol name is the same as its label. This does not happen for
the identifier `i'. Secondly, the last `eq?' comparison seems to be
superfluous.)
I have rewritten the above clause as follows:
((symbol? ni)
;; `i' is not lexically bound. Assert that `j' is free,
;; and if so, compare their bindings, that they are either
;; bound to the same variable, or both unbound and have
;; the same name.
(and (symbol? nj)
(let ((bi (id-module-binding ni mi)))
(if bi
(eq? bi (id-module-binding nj mj))
(and (not (id-module-binding nj mj))
(eq? ni nj)))))))
The main difference is that I use `ni' and `nj' (the symbol labels) to look
up the binding (I also have to check explicitly that the label of `j' also
makes `j' as not lexically bound.)
I think this implements the correct semantics of free-id=?. And, indeed,
the following test now passes:
(pass-if-equal "alias is free-identifier=? with globals"
'(1 5)
(let ()
(define-alias comma unquote)
`(1 (comma (+ 2 3)))))
Also this test now works correctly:
(pass-if "alias is free-identifier=? with unbound"
(let ()
(define-syntax foo
(syntax-rules (x z)
((foo z) #f)
((foo x) #t)
((foo _) #f)))
(let ()
(define-alias y x)
(foo y))))
The new semantics `free-id=?' are compatible with all existing tests in the
Guile test suite. If you want to experiment with my ideas, I have attached
a patch file.
-- Marc
[-- Attachment #1.2: Type: text/html, Size: 9680 bytes --]
[-- Attachment #2: define-alias.patch --]
[-- Type: text/x-patch, Size: 17896 bytes --]
diff --git a/.gitignore b/.gitignore
index dc8eedaf4..7d2d79daa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -168,3 +168,4 @@ INSTALL
/meta/build-env
/lib/limits.h
/lib/stdint.h
+/filesys-test-link.tmp
diff --git a/module/ice-9/psyntax.scm b/module/ice-9/psyntax.scm
index adc699713..41feb947c 100644
--- a/module/ice-9/psyntax.scm
+++ b/module/ice-9/psyntax.scm
@@ -954,13 +954,12 @@
;; and if so, compare their bindings, that they are either
;; bound to the same variable, or both unbound and have
;; the same name.
- (and (eq? nj (id-sym-name j))
- (let ((bi (id-module-binding i mi)))
+ (and (symbol? nj)
+ (let ((bi (id-module-binding ni mi)))
(if bi
- (eq? bi (id-module-binding j mj))
- (and (not (id-module-binding j mj))
- (eq? ni nj))))
- (eq? (id-module-binding i mi) (id-module-binding j mj))))
+ (eq? bi (id-module-binding nj mj))
+ (and (not (id-module-binding nj mj))
+ (eq? ni nj))))))
(else
;; Otherwise `i' is bound, so check that `j' is bound, and
;; bound to the same thing.
@@ -1129,6 +1128,11 @@
mod))
(lambda ()
(build-global-definition s var (expand e r w mod)))))))))
+ ((define-alias-form)
+ (let ((id (wrap value w mod))
+ (label (id-var-name e w mod)))
+ (extend-ribcage! ribcage id label)
+ '()))
((define-syntax-form define-syntax-parameter-form)
(let* ((id (wrap value w mod))
(label (gen-label))
@@ -1272,6 +1276,7 @@
;; call none any other call
;; begin-form none begin expression
;; define-form id variable definition
+ ;; define-alias-form id alias definition
;; define-syntax-form id syntax definition
;; define-syntax-parameter-form id syntax parameter definition
;; local-syntax-form rec? syntax definition
@@ -1359,6 +1364,11 @@
(wrap e w mod)
#'(if #f #f)
empty-wrap s mod))))
+ ((define-alias)
+ (syntax-case e ()
+ ((_ name val)
+ (and (id? #'name) (id? #'val))
+ (values 'define-alias-form #'name e #'val w s mod))))
((define-syntax)
(syntax-case e ()
((_ name val)
@@ -1443,7 +1453,8 @@
(if (memq 'eval when-list)
(expand-sequence #'(e1 e2 ...) r w s mod)
(expand-void))))))
- ((define-form define-syntax-form define-syntax-parameter-form)
+ ((define-form define-alias-form define-syntax-form
+ define-syntax-parameter-form)
(syntax-violation #f "definition in expression context, where definitions are not allowed,"
(source-wrap form w s mod)))
((syntax)
@@ -1600,6 +1611,12 @@
(cons id var-ids)
(cons var vars) (cons (cons er (wrap e w mod)) vals)
(cons (make-binding 'lexical var) bindings)))))
+ ((define-alias-form)
+ (let ((id (wrap value w mod))
+ (label (id-var-name e w mod)))
+ (extend-ribcage! ribcage id label)
+ (parse (cdr body) (cons id ids) labels var-ids vars vals
+ bindings)))
((define-syntax-form)
(let ((id (wrap value w mod))
(label (gen-label))
@@ -1727,8 +1744,8 @@
(call-with-values
(lambda () (resolve-identifier
(make-syntax '#{ $sc-ellipsis }#
- (syntax-wrap e)
- (syntax-module e))
+ (syntax-wrap e)
+ (syntax-module e))
empty-wrap r mod #f))
(lambda (type value mod)
(if (eq? type 'ellipsis)
@@ -2036,10 +2053,10 @@
(eval-local-transformer (expand x trans-r w mod) mod)))
#'(val ...)))))
(expand-body #'(e1 e2 ...)
- (source-wrap e w s mod)
- (extend-env names bindings r)
- w
- mod)))
+ (source-wrap e w s mod)
+ (extend-env names bindings r)
+ w
+ mod)))
(_ (syntax-violation 'syntax-parameterize "bad syntax"
(source-wrap e w s mod))))))
@@ -2290,8 +2307,8 @@
(let ((id (if (symbol? #'dots)
'#{ $sc-ellipsis }#
(make-syntax '#{ $sc-ellipsis }#
- (syntax-wrap #'dots)
- (syntax-module #'dots)))))
+ (syntax-wrap #'dots)
+ (syntax-module #'dots)))))
(let ((ids (list id))
(labels (list (gen-label)))
(bindings (list (make-binding 'ellipsis (source-wrap #'dots w s mod)))))
@@ -2503,6 +2520,8 @@
(global-extend 'define 'define '())
+ (global-extend 'define-alias 'define-alias '())
+
(global-extend 'define-syntax 'define-syntax '())
(global-extend 'define-syntax-parameter 'define-syntax-parameter '())
@@ -2519,12 +2538,12 @@
(syntax-case p* ()
((x . y)
(call-with-values
- (lambda () (cvt* #'y n ids))
- (lambda (y ids)
- (call-with-values
- (lambda () (cvt #'x n ids))
- (lambda (x ids)
- (values (cons x y) ids))))))
+ (lambda () (cvt* #'y n ids))
+ (lambda (y ids)
+ (call-with-values
+ (lambda () (cvt #'x n ids))
+ (lambda (x ids)
+ (values (cons x y) ids))))))
(_ (cvt p* n ids)))))
(define (v-reverse x)
@@ -2589,15 +2608,15 @@
'apply
(list (build-simple-lambda no-source (map syntax->datum ids) #f new-vars '()
(expand exp
- (extend-env
- labels
- (map (lambda (var level)
- (make-binding 'syntax `(,var . ,level)))
- new-vars
- (map cdr pvars))
- r)
- (make-binding-wrap ids labels empty-wrap)
- mod))
+ (extend-env
+ labels
+ (map (lambda (var level)
+ (make-binding 'syntax `(,var . ,level)))
+ new-vars
+ (map cdr pvars))
+ r)
+ (make-binding-wrap ids labels empty-wrap)
+ mod))
y))))))
(define gen-clause
@@ -2653,12 +2672,12 @@
no-source (list (syntax->datum #'pat)) #f (list var)
'()
(expand #'exp
- (extend-env labels
- (list (make-binding 'syntax `(,var . 0)))
- r)
- (make-binding-wrap #'(pat)
- labels empty-wrap)
- mod))
+ (extend-env labels
+ (list (make-binding 'syntax `(,var . 0)))
+ r)
+ (make-binding-wrap #'(pat)
+ labels empty-wrap)
+ mod))
(list x))))
(gen-clause x keys (cdr clauses) r
#'pat #t #'exp mod)))
@@ -2696,58 +2715,58 @@
;; expanded, and the expanded definitions are also residualized into
;; the object file if we are compiling a file.
(set! macroexpand
- (lambda* (x #:optional (m 'e) (esew '(eval)))
- (expand-top-sequence (list x) null-env top-wrap #f m esew
- (cons 'hygiene (module-name (current-module))))))
+ (lambda* (x #:optional (m 'e) (esew '(eval)))
+ (expand-top-sequence (list x) null-env top-wrap #f m esew
+ (cons 'hygiene (module-name (current-module))))))
(set! identifier?
- (lambda (x)
- (nonsymbol-id? x)))
+ (lambda (x)
+ (nonsymbol-id? x)))
(set! datum->syntax
- (lambda (id datum)
- (make-syntax datum (syntax-wrap id)
- (syntax-module id))))
+ (lambda (id datum)
+ (make-syntax datum (syntax-wrap id)
+ (syntax-module id))))
(set! syntax->datum
- ;; accepts any object, since syntax objects may consist partially
- ;; or entirely of unwrapped, nonsymbolic data
- (lambda (x)
- (strip x empty-wrap)))
+ ;; accepts any object, since syntax objects may consist partially
+ ;; or entirely of unwrapped, nonsymbolic data
+ (lambda (x)
+ (strip x empty-wrap)))
(set! syntax-source
- (lambda (x) (source-annotation x)))
+ (lambda (x) (source-annotation x)))
(set! generate-temporaries
- (lambda (ls)
- (arg-check list? ls 'generate-temporaries)
- (let ((mod (cons 'hygiene (module-name (current-module)))))
- (map (lambda (x)
- (wrap (module-gensym "t") top-wrap mod))
- ls))))
+ (lambda (ls)
+ (arg-check list? ls 'generate-temporaries)
+ (let ((mod (cons 'hygiene (module-name (current-module)))))
+ (map (lambda (x)
+ (wrap (module-gensym "t") top-wrap mod))
+ ls))))
(set! free-identifier=?
- (lambda (x y)
- (arg-check nonsymbol-id? x 'free-identifier=?)
- (arg-check nonsymbol-id? y 'free-identifier=?)
- (free-id=? x y)))
+ (lambda (x y)
+ (arg-check nonsymbol-id? x 'free-identifier=?)
+ (arg-check nonsymbol-id? y 'free-identifier=?)
+ (free-id=? x y)))
(set! bound-identifier=?
- (lambda (x y)
- (arg-check nonsymbol-id? x 'bound-identifier=?)
- (arg-check nonsymbol-id? y 'bound-identifier=?)
- (bound-id=? x y)))
+ (lambda (x y)
+ (arg-check nonsymbol-id? x 'bound-identifier=?)
+ (arg-check nonsymbol-id? y 'bound-identifier=?)
+ (bound-id=? x y)))
(set! syntax-violation
- (lambda* (who message form #:optional subform)
- (arg-check (lambda (x) (or (not x) (string? x) (symbol? x)))
- who 'syntax-violation)
- (arg-check string? message 'syntax-violation)
- (throw 'syntax-error who message
- (or (source-annotation subform)
- (source-annotation form))
- (strip form empty-wrap)
- (and subform (strip subform empty-wrap)))))
+ (lambda* (who message form #:optional subform)
+ (arg-check (lambda (x) (or (not x) (string? x) (symbol? x)))
+ who 'syntax-violation)
+ (arg-check string? message 'syntax-violation)
+ (throw 'syntax-error who message
+ (or (source-annotation subform)
+ (source-annotation form))
+ (strip form empty-wrap)
+ (and subform (strip subform empty-wrap)))))
(let ()
(define (%syntax-module id)
@@ -2788,8 +2807,8 @@
((ellipsis)
(values 'ellipsis
(make-syntax (syntax-expression value)
- (anti-mark (syntax-wrap value))
- (syntax-module value))))
+ (anti-mark (syntax-wrap value))
+ (syntax-module value))))
(else (values 'other #f))))))))
(define (syntax-locally-bound-identifiers id)
@@ -2913,8 +2932,8 @@
((null? p) (and (null? e) r))
((pair? p)
(and (pair? e) (match (car e) (car p) w
- (match (cdr e) (cdr p) w r mod)
- mod)))
+ (match (cdr e) (cdr p) w r mod)
+ mod)))
((eq? p 'each-any)
(let ((l (match-each-any e w mod))) (and l (cons l r))))
(else
@@ -2960,14 +2979,14 @@
(else (match* e p w r mod)))))
(set! $sc-dispatch
- (lambda (e p)
- (cond
- ((eq? p 'any) (list e))
- ((eq? p '_) '())
- ((syntax? e)
- (match* (syntax-expression e)
- p (syntax-wrap e) '() (syntax-module e)))
- (else (match* e p empty-wrap '() #f))))))))
+ (lambda (e p)
+ (cond
+ ((eq? p 'any) (list e))
+ ((eq? p '_) '())
+ ((syntax? e)
+ (match* (syntax-expression e)
+ p (syntax-wrap e) '() (syntax-module e)))
+ (else (match* e p empty-wrap '() #f))))))))
(define-syntax with-syntax
diff --git a/test-suite/tests/syntax.test b/test-suite/tests/syntax.test
index 883004a27..67df87b3d 100644
--- a/test-suite/tests/syntax.test
+++ b/test-suite/tests/syntax.test
@@ -1649,6 +1649,50 @@
(hash interpreted most-positive-fixnum)
(hash compiled most-positive-fixnum))))
+(with-test-prefix "aliases"
+ (pass-if "aliased variables are eq?"
+ (let ((x "var"))
+ (define-alias y x)
+ (eq? x y)))
+
+ (pass-if "can alias definition in the same body"
+ (let ((y #f))
+ (define x #t)
+ (define-alias y x)
+ y))
+
+ (pass-if "right hand side of alias-definition is not postponed"
+ (let ((x #t))
+ (define-alias y x)
+ (define x #f)
+ y))
+
+ (pass-if "alias is free-identifier=?"
+ (let ((x #t))
+ (define-syntax foo
+ (syntax-rules (x)
+ ((foo x) #t)
+ ((foo _) #f)))
+ (let ()
+ (define-alias y x)
+ (foo y))))
+
+ (pass-if "alias is free-identifier=? with unbound"
+ (let ()
+ (define-syntax foo
+ (syntax-rules (x z)
+ ((foo z) #f)
+ ((foo x) #t)
+ ((foo _) #f)))
+ (let ()
+ (define-alias y x)
+ (foo y))))
+
+ (pass-if-equal "alias is free-identifier=? with globals"
+ '(1 5)
+ (let ()
+ (define-alias comma unquote)
+ `(1 (comma (+ 2 3))))))
;;; Local Variables:
;;; eval: (put 'pass-if-syntax-error 'scheme-indent-function 1)
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2018-11-18 11:15 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-15 16:55 Aliasing an identifier Marc Nieper-Wißkirchen
2018-11-17 15:17 ` Marc Nieper-Wißkirchen
2018-11-18 11:15 ` Marc Nieper-Wißkirchen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).