unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* Fwd: new function
       [not found] <CADEOadfF+rR=fW0fS-PkQkDN8EHFB1sJnkeePMJyc23m9shLgA@mail.gmail.com>
@ 2021-09-19  9:18 ` Damien Mattei
  2021-09-19 10:38   ` Maxime Devos
  0 siblings, 1 reply; 9+ messages in thread
From: Damien Mattei @ 2021-09-19  9:18 UTC (permalink / raw)
  To: guile-user; +Cc: Jean-Paul Roy

---------- Forwarded message ---------
From: Damien Mattei <damien.mattei@gmail.com>
Date: Sun, Sep 19, 2021 at 9:54 AM
Subject: new function
To: <guile-devel@gnu.org>


hello,
i'm developing an extension to Scheme
and i need a procedure or macro that define a variable only if it is not
bind and if it is just set! it.

I can not do it in Guile or any Scheme,and i'm desperately searching a way
to do that. I finally conclude that it can be done only by adding it in the
language.

Can someone include a such function in Guile next release?
i know guile have a predicate defined? to test binfing of a vairable but
writing a macro with it is not possible because define can be used in an
expression context.

Thank in advance for any help
Damien


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Fwd: new function
  2021-09-19  9:18 ` Fwd: new function Damien Mattei
@ 2021-09-19 10:38   ` Maxime Devos
  2021-09-19 14:45     ` Matt Wette
  0 siblings, 1 reply; 9+ messages in thread
From: Maxime Devos @ 2021-09-19 10:38 UTC (permalink / raw)
  To: Damien Mattei, guile-user; +Cc: Jean-Paul Roy

[-- Attachment #1: Type: text/plain, Size: 1826 bytes --]

Damien Mattei schreef op zo 19-09-2021 om 11:18 [+0200]:
> ---------- Forwarded message ---------
> From: Damien Mattei <damien.mattei@gmail.com>
> Date: Sun, Sep 19, 2021 at 9:54 AM
> Subject: new function
> To: <guile-devel@gnu.org>
> 
> 
> hello,
> i'm developing an extension to Scheme
> and i need a procedure or macro that define a variable only if it is not
> bind and if it is just set! it.

Could you give an example in which the hypothetical define-or-set! is used?
I wonder where such a thing would be useful.

> I can not do it in Guile or any Scheme,and i'm desperately searching a way
> to do that. I finally conclude that it can be done only by adding it in the
> language.
> 
> Can someone include a such function in Guile next release?
> i know guile have a predicate defined?

defined? only works on global variables, not on lexicals,
and depends on the (current-module), which is not necessarily
the module defined? is used in.

>  to test binfing of a vairable but
> writing a macro with it is not possible because define can be used in an
> expression context.

You can use 'syntax-local-binding'.

(use-modules (system syntax))
(define-syntax define-or-set!
  (lambda (s)
    (syntax-case s ()
      ((_ var value)
       (case (syntax-local-binding #'var)
         ((lexical displaced-lexical) #'(set! var value))
         ((global) #'(define var value))
         (else ???))))))

,expand (define-or-set! a 0) ; $_ = (define a 0)
,expand (let ((a 0)) (define-or-set! a 0) a) ; $_ = (let ((a 0)) (set! a 0) a)
(define-or-set! a 0)
,expand (define-or-set! a 0) ; $_ = (define a 0) (might or might not be acceptable for your use case
,expand (let () (define-or-set! a 0) (define-or-set! a 1) a) ; $_ = (let () (define a 0) (set! a 1))

Greetings,
Maxime.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 260 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Fwd: new function
  2021-09-19 10:38   ` Maxime Devos
@ 2021-09-19 14:45     ` Matt Wette
  2021-09-19 14:56       ` Maxime Devos
  2021-09-21 13:04       ` Damien Mattei
  0 siblings, 2 replies; 9+ messages in thread
From: Matt Wette @ 2021-09-19 14:45 UTC (permalink / raw)
  To: guile-user



On 9/19/21 3:38 AM, Maxime Devos wrote:
> Damien Mattei schreef op zo 19-09-2021 om 11:18 [+0200]:
>> ---------- Forwarded message ---------
>> From: Damien Mattei <damien.mattei@gmail.com>
>> Date: Sun, Sep 19, 2021 at 9:54 AM
>> Subject: new function
>> To: <guile-devel@gnu.org>
>>
>>
>> hello,
>> i'm developing an extension to Scheme
>> and i need a procedure or macro that define a variable only if it is not
>> bind and if it is just set! it.
> Could you give an example in which the hypothetical define-or-set! is used?
> I wonder where such a thing would be useful.
>
>> I can not do it in Guile or any Scheme,and i'm desperately searching a way
>> to do that. I finally conclude that it can be done only by adding it in the
>> language.
>>
>> Can someone include a such function in Guile next release?
>> i know guile have a predicate defined?
> defined? only works on global variables, not on lexicals,
> and depends on the (current-module), which is not necessarily
> the module defined? is used in.
>
>>   to test binfing of a vairable but
>> writing a macro with it is not possible because define can be used in an
>> expression context.
> You can use 'syntax-local-binding'.
>
> (use-modules (system syntax))
> (define-syntax define-or-set!
>    (lambda (s)
>      (syntax-case s ()
>        ((_ var value)
>         (case (syntax-local-binding #'var)
>           ((lexical displaced-lexical) #'(set! var value))
>           ((global) #'(define var value))
>           (else ???))))))
>
> ,expand (define-or-set! a 0) ; $_ = (define a 0)
> ,expand (let ((a 0)) (define-or-set! a 0) a) ; $_ = (let ((a 0)) (set! a 0) a)
> (define-or-set! a 0)
> ,expand (define-or-set! a 0) ; $_ = (define a 0) (might or might not be acceptable for your use case
> ,expand (let () (define-or-set! a 0) (define-or-set! a 1) a) ; $_ = (let () (define a 0) (set! a 1))
>
> Greetings,
> Maxime.

Does this work for you?

scheme@(guile-user)> (define a 1)
scheme@(guile-user)> (define a 2)
scheme@(guile-user)> a
$2 = 2
scheme@(guile-user)>








^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Fwd: new function
  2021-09-19 14:45     ` Matt Wette
@ 2021-09-19 14:56       ` Maxime Devos
  2021-09-21 13:04       ` Damien Mattei
  1 sibling, 0 replies; 9+ messages in thread
From: Maxime Devos @ 2021-09-19 14:56 UTC (permalink / raw)
  To: Matt Wette, guile-user, Damien Mattei

[-- Attachment #1: Type: text/plain, Size: 1834 bytes --]

Matt Wette schreef op zo 19-09-2021 om 07:45 [-0700]:
> On 9/19/21 3:38 AM, Maxime Devos wrote:
> > [...]
> > (use-modules (system syntax))
> > (define-syntax define-or-set!
> >    (lambda (s)
> >      (syntax-case s ()
> >        ((_ var value)
> >         (case (syntax-local-binding #'var)
> >           ((lexical displaced-lexical) #'(set! var value))
> >           ((global) #'(define var value))
> >           (else ???))))))
> > 
> > ,expand (define-or-set! a 0) ; $_ = (define a 0)
> > ,expand (let ((a 0)) (define-or-set! a 0) a) ; $_ = (let ((a 0)) (set! a 0) a)
> > (define-or-set! a 0)
> > ,expand (define-or-set! a 0) ; $_ = (define a 0) (might or might not be acceptable for your use case
> > ,expand (let () (define-or-set! a 0) (define-or-set! a 1) a) ; $_ = (let () (define a 0) (set! a 1))
> > 
> > Greetings,
> > Maxime.
> 
> Does this work for you?
> 
> scheme@(guile-user)> (define a 1)
> scheme@(guile-user)> (define a 2)
> scheme@(guile-user)> a
> $2 = 2
> scheme@(guile-user)>

If I use 'define', the following evaluates to zero:

(define a 0)
(let ()
  (define a 1)
  (values))
a

(the inner 'a' shadows the global 'a', thus the last a evaluates to 0 instead of 1)

However, Damien Mattei asked for a variant of 'define' that only defines a variable
if it is not yet bound (let's call this variant define-or-set!)

(define-or-set! a 0)
(let ()
  (define-or-set! a 1)
  (values))
a

As within the 'let' expression, 'a' is already bound (to the global variable), due to the
first (define-or-set! a 0), the inner 'define-or-set!' should set! 'a' instead of
defining a new variable 'a'.  As such, the code above should expand to:

(define a 0)
(let ()
  (set! a 1)
  (values))
a ; evaluates to 1.

Possibly Damien Mattei wants something else though ...

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 260 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Fwd: new function
  2021-09-19 14:45     ` Matt Wette
  2021-09-19 14:56       ` Maxime Devos
@ 2021-09-21 13:04       ` Damien Mattei
  2021-09-21 19:03         ` Maxime Devos
  1 sibling, 1 reply; 9+ messages in thread
From: Damien Mattei @ 2021-09-21 13:04 UTC (permalink / raw)
  To: Matt Wette; +Cc: guile-user

i have tested define-once
http://www.gnu.org/software/guile/docs/master/guile.html/Top-Level.html
(the defvar of Lisp)and idea are:
-unfortunately it is considered by scheme as a define,so there is some
context where it is not allowed in my code
-seems to work fine at toplevel (as mentioned in doc) but strange behavior
in a function, i did not understand really what happened but i got some
#unspecified value.

here are my test code:
cheme@(guile-user)> (define (foo2)
  (define-once  x 1)
  (if #t
      (let ()
        (define-once x 2)
        ;;(set! x 2)
        (display "x=")
        (display x)
        (newline))
      'never)
  (display x)
  (newline))
scheme@(guile-user)> x
;;; <unknown-location>: warning: possibly unbound variable `x'
ice-9/boot-9.scm:1669:16: In procedure raise-exception:
Unbound variable: x

Entering a new prompt.  Type `,bt' for a backtrace or `,q' to continue.
scheme@(guile-user) [1]> ,q
scheme@(guile-user)> (foo2)
x=2
1
scheme@(guile-user)> (foo2)
x=2
1
scheme@(guile-user)> x
;;; <unknown-location>: warning: possibly unbound variable `x'
ice-9/boot-9.scm:1669:16: In procedure raise-exception:
Unbound variable: x

Entering a new prompt.  Type `,bt' for a backtrace or `,q' to continue.
scheme@(guile-user) [1]> ,q
scheme@(guile-user)> (define x 3)
scheme@(guile-user)> (foo2)
x=#<unspecified>
#<unspecified>
scheme@(guile-user)> x
3

it does not seem to help me, perheaps if i can test the return of
#<unspecified> ....

Damien

On Sun, Sep 19, 2021 at 4:46 PM Matt Wette <matt.wette@gmail.com> wrote:

>
>
> On 9/19/21 3:38 AM, Maxime Devos wrote:
> > Damien Mattei schreef op zo 19-09-2021 om 11:18 [+0200]:
> >> ---------- Forwarded message ---------
> >> From: Damien Mattei <damien.mattei@gmail.com>
> >> Date: Sun, Sep 19, 2021 at 9:54 AM
> >> Subject: new function
> >> To: <guile-devel@gnu.org>
> >>
> >>
> >> hello,
> >> i'm developing an extension to Scheme
> >> and i need a procedure or macro that define a variable only if it is not
> >> bind and if it is just set! it.
> > Could you give an example in which the hypothetical define-or-set! is
> used?
> > I wonder where such a thing would be useful.
> >
> >> I can not do it in Guile or any Scheme,and i'm desperately searching a
> way
> >> to do that. I finally conclude that it can be done only by adding it in
> the
> >> language.
> >>
> >> Can someone include a such function in Guile next release?
> >> i know guile have a predicate defined?
> > defined? only works on global variables, not on lexicals,
> > and depends on the (current-module), which is not necessarily
> > the module defined? is used in.
> >
> >>   to test binfing of a vairable but
> >> writing a macro with it is not possible because define can be used in an
> >> expression context.
> > You can use 'syntax-local-binding'.
> >
> > (use-modules (system syntax))
> > (define-syntax define-or-set!
> >    (lambda (s)
> >      (syntax-case s ()
> >        ((_ var value)
> >         (case (syntax-local-binding #'var)
> >           ((lexical displaced-lexical) #'(set! var value))
> >           ((global) #'(define var value))
> >           (else ???))))))
> >
> > ,expand (define-or-set! a 0) ; $_ = (define a 0)
> > ,expand (let ((a 0)) (define-or-set! a 0) a) ; $_ = (let ((a 0)) (set! a
> 0) a)
> > (define-or-set! a 0)
> > ,expand (define-or-set! a 0) ; $_ = (define a 0) (might or might not be
> acceptable for your use case
> > ,expand (let () (define-or-set! a 0) (define-or-set! a 1) a) ; $_ = (let
> () (define a 0) (set! a 1))
> >
> > Greetings,
> > Maxime.
>
> Does this work for you?
>
> scheme@(guile-user)> (define a 1)
> scheme@(guile-user)> (define a 2)
> scheme@(guile-user)> a
> $2 = 2
> scheme@(guile-user)>
>
>
>
>
>
>
>


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Fwd: new function
  2021-09-21 13:04       ` Damien Mattei
@ 2021-09-21 19:03         ` Maxime Devos
  2021-09-22  7:52           ` Damien Mattei
  2021-09-22 19:12           ` Taylan Kammer
  0 siblings, 2 replies; 9+ messages in thread
From: Maxime Devos @ 2021-09-21 19:03 UTC (permalink / raw)
  To: Damien Mattei, Matt Wette; +Cc: guile-user

[-- Attachment #1: Type: text/plain, Size: 2163 bytes --]

Damien Mattei schreef op di 21-09-2021 om 15:04 [+0200]:
> i have tested define-once
> http://www.gnu.org/software/guile/docs/master/guile.html/Top-Level.html
> (the defvar of Lisp)and idea are:
> -unfortunately it is considered by scheme as a define,so there is some
> context where it is not allowed in my code
> -seems to work fine at toplevel (as mentioned in doc) but strange behavior
> in a function, i did not understand really what happened but i got some
> #unspecified value.
> 
> here are my test code:
> cheme@(guile-user)> (define (foo2)
>   (define-once  x 1)
>   (if #t
>       (let ()
>         (define-once x 2)
>         ;;(set! x 2)
>         (display "x=")
>         (display x)
>         (newline))
>       'never)
>   (display x)
>   (newline))

Possibly you want (added a set? argument for demonstration):

(define (foo2 set?)
  (define x) ; define an (undefined or unbound, not sure about terminology) variable
  (if set?
      (let ()
        (set! x 2) ; change the value of x
        (display "x=")
        (display x)
        (newline))
      'never)
  (display x)
  (newline))

That should be portable and avoids global state.

scheme@(guile-user)> x
;;; <stdin>:20:0: warning: possibly unbound variable `x'
ice-9/boot-9.scm:1685:16: In procedure raise-exception:
Unbound variable: x
scheme@(guile-user) [1]> ,q

scheme@(guile-user) [1]> (foo2 #f)
#<unspecified> ; I expected an error as would result from ...

;; ... this ...
scheme@(guile-user)> (variable-ref (make-undefined-variable))
ice-9/boot-9.scm:1685:16: In procedure raise-exception:
In procedure variable-ref: Unbound variable: #<variable 7f6de46cde80 value: #<undefined>>

Entering a new prompt.  Type `,bt' for a backtrace or `,q' to continue.
scheme@(guile-user) [2]> 

;; instead  of #<unpecified> but whatever ...

scheme@(guile-user) [1]> (foo2 #t)
x=2
2
scheme@(guile-user) [1]> (foo2 #t)
x=2
2


scheme@(guile-user) [1]> (define x 3)
scheme@(guile-user) [1]> (foo2 #t)
x=2 ; foo2 doesn't use the global variable 'x'
2

scheme@(guile-user) [1]> x
$1 = 3

Does this seem reasonable to you?

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 260 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Fwd: new function
  2021-09-21 19:03         ` Maxime Devos
@ 2021-09-22  7:52           ` Damien Mattei
  2021-09-22 18:03             ` Maxime Devos
  2021-09-22 19:12           ` Taylan Kammer
  1 sibling, 1 reply; 9+ messages in thread
From: Damien Mattei @ 2021-09-22  7:52 UTC (permalink / raw)
  To: Maxime Devos; +Cc: guile-user, Matt Wette

i do not understand well what you want to mean with those example.
For me  define-once does not seems to be a solution, it act as define too
much ,does not set! variable if already exist and can not use to set it
again because, as define it is forbidden twice in the same block for the
same variable:

scheme@(guile-user)> (define (foo3)
  (define-once  x 1)
  (if #t
      (let ()
        (define-once x 2)
        ;;(set! x 2)
        (display "x=")
        (display x)
        (newline)
        (define-once x 3)
        ;;(set! x 2)
        (display "x=")
        (display x)
        (newline)

        )
      'never)
  (display x)
  (newline))
While compiling expression:
Syntax error:
unknown file:51:6: invalid or duplicate identifier in definition in form
(let () (define-once x 2) (display "x=") (display x) (newline) (define-once
x 3) (display "x=") (display x) (newline))

i will try (use-modules (system syntax)) that yesterday seems to give
better results

On Tue, Sep 21, 2021 at 9:03 PM Maxime Devos <maximedevos@telenet.be> wrote:

> Damien Mattei schreef op di 21-09-2021 om 15:04 [+0200]:
> > i have tested define-once
> > http://www.gnu.org/software/guile/docs/master/guile.html/Top-Level.html
> > (the defvar of Lisp)and idea are:
> > -unfortunately it is considered by scheme as a define,so there is some
> > context where it is not allowed in my code
> > -seems to work fine at toplevel (as mentioned in doc) but strange
> behavior
> > in a function, i did not understand really what happened but i got some
> > #unspecified value.
> >
> > here are my test code:
> > cheme@(guile-user)> (define (foo2)
> >   (define-once  x 1)
> >   (if #t
> >       (let ()
> >         (define-once x 2)
> >         ;;(set! x 2)
> >         (display "x=")
> >         (display x)
> >         (newline))
> >       'never)
> >   (display x)
> >   (newline))
>
> Possibly you want (added a set? argument for demonstration):
>
> (define (foo2 set?)
>   (define x) ; define an (undefined or unbound, not sure about
> terminology) variable
>   (if set?
>       (let ()
>         (set! x 2) ; change the value of x
>         (display "x=")
>         (display x)
>         (newline))
>       'never)
>   (display x)
>   (newline))
>
> That should be portable and avoids global state.
>
> scheme@(guile-user)> x
> ;;; <stdin>:20:0: warning: possibly unbound variable `x'
> ice-9/boot-9.scm:1685:16: In procedure raise-exception:
> Unbound variable: x
> scheme@(guile-user) [1]> ,q
>
> scheme@(guile-user) [1]> (foo2 #f)
> #<unspecified> ; I expected an error as would result from ...
>
> ;; ... this ...
> scheme@(guile-user)> (variable-ref (make-undefined-variable))
> ice-9/boot-9.scm:1685:16: In procedure raise-exception:
> In procedure variable-ref: Unbound variable: #<variable 7f6de46cde80
> value: #<undefined>>
>
> Entering a new prompt.  Type `,bt' for a backtrace or `,q' to continue.
> scheme@(guile-user) [2]>
>
> ;; instead  of #<unpecified> but whatever ...
>
> scheme@(guile-user) [1]> (foo2 #t)
> x=2
> 2
> scheme@(guile-user) [1]> (foo2 #t)
> x=2
> 2
>
>
> scheme@(guile-user) [1]> (define x 3)
> scheme@(guile-user) [1]> (foo2 #t)
> x=2 ; foo2 doesn't use the global variable 'x'
> 2
>
> scheme@(guile-user) [1]> x
> $1 = 3
>
> Does this seem reasonable to you?
>


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Fwd: new function
  2021-09-22  7:52           ` Damien Mattei
@ 2021-09-22 18:03             ` Maxime Devos
  0 siblings, 0 replies; 9+ messages in thread
From: Maxime Devos @ 2021-09-22 18:03 UTC (permalink / raw)
  To: Damien Mattei; +Cc: guile-user, Matt Wette

[-- Attachment #1: Type: text/plain, Size: 1321 bytes --]

Damien Mattei schreef op wo 22-09-2021 om 09:52 [+0200]:
> i do not understand well what you want to mean with those example.
> For me  define-once does not seems to be a solution, it act as define too much 
> ,does not set! variable if already exist and can not use to set it again because,
> as define it is forbidden twice in the same block for the same variable:
> [...]

I was not suggesting using define-once.
Rather, I was demonstrating how to get Python-style scoping of variables local to
a function (procedure) in Scheme without defining new syntax, by using set! instead
of define, and adding a define in the beginning of the procedure for every variable.

Python:

def hello(language):
  if language == "english":
     message = "Hello world!"
  if language == "dutch":
     message = "Hallo wereld!"
  print(message)

hello("english") # output: Hello world!
hello("dutch") # output: Hallo wereld!

Equivalent (non-idomatic but portable) Scheme:

(define (hello language)
  (define message)
  (cond ((equal? language "english")
         (set! message "Hello world!"))
        ((equal? language "dutch")
         (set! message "Hallo wereld!")))
 
(display message)
  (newline))

(hello "english") ; "Hello world!"
(hello "dutch") ; "Hallo wereld!"

Greetings,
Maxime.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 260 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Fwd: new function
  2021-09-21 19:03         ` Maxime Devos
  2021-09-22  7:52           ` Damien Mattei
@ 2021-09-22 19:12           ` Taylan Kammer
  1 sibling, 0 replies; 9+ messages in thread
From: Taylan Kammer @ 2021-09-22 19:12 UTC (permalink / raw)
  To: Maxime Devos, Damien Mattei, Matt Wette; +Cc: guile-user

On 21.09.2021 21:03, Maxime Devos wrote:
> 
> (define (foo2 set?)
>   (define x) ; define an (undefined or unbound, not sure about terminology) variable
>   (if set?
>       (let ()
>         (set! x 2) ; change the value of x
>         (display "x=")
>         (display x)
>         (newline))
>       'never)
>   (display x)
>   (newline))
> 

I didn't know (define x) without a value was possible in Guile.  I guess
it's just a shorthand for (define x *unspecified*), judging by your result.

If I'm not mistaken, the only way in Scheme to get a "defined but not yet
bound" kind of situation is to use 'letrec'.  If you use the 'letrec*'
variant, it guarantees a straight order of evaluation, so the following is
supposed to definitely NOT work, due to y and z being defined-not-bound:

  (letrec* ((x (+ y z))
            (y (random 10))
            (z (random 10)))
    (display x)
    (newline))

However, in Guile, it seems to bind all the variables to #<unspecified>
anyway, resulting in a "wrong type argument" error (since we end up
passing #<unspecified> to '+') instead of saying that y and z are not
yet bound.

Long story short, there doesn't seem to be *any* way in Guile to have a
lexical variable that's defined but not bound.

-- 
Taylan



^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2021-09-22 19:12 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CADEOadfF+rR=fW0fS-PkQkDN8EHFB1sJnkeePMJyc23m9shLgA@mail.gmail.com>
2021-09-19  9:18 ` Fwd: new function Damien Mattei
2021-09-19 10:38   ` Maxime Devos
2021-09-19 14:45     ` Matt Wette
2021-09-19 14:56       ` Maxime Devos
2021-09-21 13:04       ` Damien Mattei
2021-09-21 19:03         ` Maxime Devos
2021-09-22  7:52           ` Damien Mattei
2021-09-22 18:03             ` Maxime Devos
2021-09-22 19:12           ` Taylan Kammer

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).