On 3/18/24 6:40 AM, Matt Wette wrote: > On 3/15/24 1:52 PM, Matt Wette wrote: >> >> As mentioned on another topic (start=up message) I had once hacked >> guile to have a >> info-port, with initial welcome message and compile messages going to >> (current-info-port). >> Adding a command arg to set that to a file or /dev/null would fix >> both issues. >> > The patch I sent out was not complete. i am making an effort to get > it working. > I'll let you all know when I have it. It looks like I have something working. Here is a link: https://github.com/mwette/guile-contrib/blob/main/patch/3.0.9/info-port.patch Matt
On 3/15/24 1:52 PM, Matt Wette wrote:
>
> As mentioned on another topic (start=up message) I had once hacked
> guile to have a
> info-port, with initial welcome message and compile messages going to
> (current-info-port).
> Adding a command arg to set that to a file or /dev/null would fix both
> issues.
>
The patch I sent out was not complete. i am making an effort to get it
working.
I'll let you all know when I have it.
Matt
On Fri, Mar 15, 2024, at 3:52 PM, Matt Wette wrote:
> As mentioned on another topic (start=up message) I had once hacked guile
> to have a info-port, with initial welcome message and compile messages
> going to (current-info-port). Adding a command arg to set that to a file or
> /dev/null would fix both issues.
>
> Matt
OP here. I was going to offer to try implementing a --quiet switch myself, but this idea seems better and I don't know how to do it.
For the moment I am satisfied running "guild compile test.scm" during deployment so this message doesn't appear in production, but I still feel that ideally there would be an option to suppress the message.
Kevin
[-- Attachment #1: Type: text/plain, Size: 572 bytes --] On Fri, Mar 15, 2024 at 01:52:10PM -0700, Matt Wette wrote: > On 3/15/24 1:47 PM, Marc Chantreux wrote: > > On Fri, Mar 15, 2024 at 08:00:09PM +0100, tomas@tuxteam.de wrote: > > > > I think most of Guile user actually want this feature for a long time. > > > > I can understand. > > > I agree. > > so do I. > > As mentioned on another topic (start=up message) I had once hacked guile to > have a > info-port, with initial welcome message and compile messages going to > (current-info-port). Thanks. To me, that makes a lot of sense, yes. Cheers -- t [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 195 bytes --]
On 3/15/24 1:52 PM, Matt Wette wrote:
> On 3/15/24 1:47 PM, Marc Chantreux wrote:
>> On Fri, Mar 15, 2024 at 08:00:09PM +0100, tomas@tuxteam.de wrote:
>>>> I think most of Guile user actually want this feature for a long time.
>>>> I can understand.
>>> I agree.
>> so do I.
>
> As mentioned on another topic (start=up message) I had once hacked
> guile to have a
> info-port, with initial welcome message and compile messages going to
> (current-info-port).
> Adding a command arg to set that to a file or /dev/null would fix both
> issues.
>
> Matt
>
>
I think is it.
--- libguile/ports.c-orig 2023-05-29 06:18:05.866508234 -0700
+++ libguile/ports.c 2023-05-29 09:00:54.592316332 -0700
@@ -432,6 +432,7 @@
static SCM cur_outport_fluid = SCM_BOOL_F;
static SCM cur_errport_fluid = SCM_BOOL_F;
static SCM cur_warnport_fluid = SCM_BOOL_F;
+static SCM cur_infoport_fluid = SCM_BOOL_F;
static SCM cur_loadport_fluid = SCM_BOOL_F;
SCM_DEFINE (scm_current_input_port, "current-input-port", 0, 0, 0,
@@ -488,6 +489,18 @@
}
#undef FUNC_NAME
+SCM_DEFINE (scm_current_info_port, "current-info-port", 0, 0, 0,
+ (void),
+ "Return the port to which diagnostic information should be sent.")
+#define FUNC_NAME s_scm_current_info_port
+{
+ if (scm_is_true (cur_infoport_fluid))
+ return scm_fluid_ref (cur_infoport_fluid);
+ else
+ return SCM_BOOL_F;
+}
+#undef FUNC_NAME
+
SCM_DEFINE (scm_current_load_port, "current-load-port", 0, 0, 0,
(),
"Return the current-load-port.\n"
@@ -545,6 +558,18 @@
}
#undef FUNC_NAME
+SCM
+scm_set_current_info_port (SCM port)
+#define FUNC_NAME "set-current-info-port"
+{
+ SCM oinfop = scm_fluid_ref (cur_infoport_fluid);
+ port = SCM_COERCE_OUTPORT (port);
+ SCM_VALIDATE_OPOUTPORT (1, port);
+ scm_fluid_set_x (cur_infoport_fluid, port);
+ return oinfop;
+}
+#undef FUNC_NAME
+
void
scm_dynwind_current_input_port (SCM port)
#define FUNC_NAME NULL
@@ -4155,6 +4180,7 @@
scm_c_define ("%current-output-port-fluid", cur_outport_fluid);
scm_c_define ("%current-error-port-fluid", cur_errport_fluid);
scm_c_define ("%current-warning-port-fluid", cur_warnport_fluid);
+ scm_c_define ("%current-info-port-fluid", cur_infoport_fluid);
}
void
@@ -4189,6 +4215,7 @@
cur_outport_fluid = scm_make_fluid ();
cur_errport_fluid = scm_make_fluid ();
cur_warnport_fluid = scm_make_fluid ();
+ cur_infoport_fluid = scm_make_fluid ();
cur_loadport_fluid = scm_make_fluid ();
default_port_encoding_var =
@@ -4227,4 +4254,8 @@
(scm_t_subr) scm_current_error_port);
scm_c_define_gsubr (s_scm_current_warning_port, 0, 0, 0,
(scm_t_subr) scm_current_warning_port);
+
+ /* Used by welcome and compiler routines. */
+ scm_c_define_gsubr (s_scm_current_info_port, 0, 0, 0,
+ (scm_t_subr) scm_current_info_port);
}
--- module/ice-9/command-line.scm-orig 2023-05-29 09:45:37.186157673 -0700
+++ module/ice-9/command-line.scm 2023-05-29 10:36:29.730463604 -0700
@@ -135,6 +135,7 @@
files.
--listen[=P] listen on a local port or a path for REPL clients;
if P is not given, the default is local port 37146
+ --info-file=PORT set output file for informative diagnostics
-q inhibit loading of user init file
--use-srfi=LS load SRFI modules for the SRFIs in LS,
which is a list of numbers like \"2,13,14\"
@@ -142,6 +143,7 @@
R6RS
--r7rs change initial Guile environment to better support
R7RS
+ -W don't print welcome message
-h, --help display this help and exit
-v, --version display version information and exit
\\ read arguments from following script lines"))
@@ -386,6 +388,14 @@
(parse args
(cons '((@@ (system repl server) spawn-server)) out)))
+ ((string=? arg "--info-file") ; set info port
+ (parse args
+ (cons `(set-current-info-port
+ ',(open-file
+ (substring arg (string-length "--info-port="))
+ "w"))
+ out)))
+
((string-prefix? "--listen=" arg) ; start a repl server
(parse
args
@@ -405,6 +415,12 @@
(error "unknown argument to --listen"))))
out)))
+ #|
+ ((string=? "-W" arg)
+ (parse args
+ (cons '(skip-welcome) out)))
+ |#
+
((or (string=? arg "-h") (string=? arg "--help"))
(shell-usage usage-name #f)
(exit 0))
--- module/ice-9/boot-9.scm-orig 2023-05-29 10:40:16.405710774 -0700
+++ module/ice-9/boot-9.scm 2023-05-29 09:26:41.743249629 -0700
@@ -190,6 +190,13 @@
(newline (current-warning-port))
(car (last-pair stuff)))
+(define (info . stuff)
+ (newline (current-info-port))
+ (display ";;; FYI " (current-info-port))
+ (display stuff (current-info-port))
+ (newline (current-info-port))
+ (car (last-pair stuff)))
+
\f
;;; {Features}
@@ -4328,15 +4335,15 @@
(load-thunk-from-file go-file-name)
(begin
(when gostat
- (format (current-warning-port)
+ (format (current-info-port)
";;; note: source file ~a\n;;; newer than compiled ~a\n"
name go-file-name))
(cond
(%load-should-auto-compile
(%warn-auto-compilation-enabled)
- (format (current-warning-port) ";;; compiling ~a\n" name)
+ (format (current-info-port) ";;; compiling ~a\n" name)
(let ((cfn (compile name)))
- (format (current-warning-port) ";;; compiled ~a\n" cfn)
+ (format (current-info-port) ";;; compiled ~a\n" cfn)
(load-thunk-from-file cfn)))
(else #f)))))
#:warning "WARNING: compilation of ~a failed:\n" name))
On 3/15/24 1:47 PM, Marc Chantreux wrote:
> On Fri, Mar 15, 2024 at 08:00:09PM +0100, tomas@tuxteam.de wrote:
>>> I think most of Guile user actually want this feature for a long time.
>>> I can understand.
>> I agree.
> so do I.
As mentioned on another topic (start=up message) I had once hacked guile
to have a
info-port, with initial welcome message and compile messages going to
(current-info-port).
Adding a command arg to set that to a file or /dev/null would fix both
issues.
Matt
On Fri, Mar 15, 2024 at 08:00:09PM +0100, tomas@tuxteam.de wrote:
> > I think most of Guile user actually want this feature for a long time.
> > I can understand.
> I agree.
so do I.
--
Marc Chantreux
Pôle CESAR (Calcul et services avancés à la recherche)
Université de Strasbourg
14 rue René Descartes,
BP 80010, 67084 STRASBOURG CEDEX
03.68.85.60.79
[-- Attachment #1: Type: text/plain, Size: 469 bytes --] On Fri, Mar 15, 2024 at 02:51:51PM -0400, Olivier Dion wrote: > On Fri, 15 Mar 2024, Keith Wright <kwright@keithdiane.us> wrote: > > Olivier Dion <olivier.dion@polymtl.ca> writes: [supress auto-compilation warnings] > >> Not possible unfortunately :-( > > > > Why would this be unfortunate? This seems like a feature (non-bug). > > I think most of Guile user actually want this feature for a long time. > I can understand. I agree. Cheers -- t [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 195 bytes --]
On Fri, 15 Mar 2024, Keith Wright <kwright@keithdiane.us> wrote: > Olivier Dion <olivier.dion@polymtl.ca> writes: > >>>> Like the warning says, you ought to either use the GUILE_AUTO_COMPILE >>>> environment variable or use the `--no-auto-compile' switch. >>>> Unfortunately, there is no `--quiet' or `--warning=/dev/null' option. >>> >>> I think the OP is fine with autocompilation (I even guess they expect >>> it, i.e. changing the source file and getting old behaviour would be >>> a surprise), they just want it to happen silently (as Tomas has hinted >>> at). >> >> Not possible unfortunately :-( > > Why would this be unfortunate? This seems like a feature (non-bug). I think most of Guile user actually want this feature for a long time. I can understand. > If it is autocompiling something you think is already compiled > then either your thought or the build/make/autocompile system is > buggy. It depends. You do not want to auto-compile script do you? You certainly do not want user to see this after installing your script. As for none-script files, I actually like the auto-compile warning. It tells me about changes in my project. -- Olivier Dion oldiob.ca
Olivier Dion <olivier.dion@polymtl.ca> writes:
>>> Like the warning says, you ought to either use the GUILE_AUTO_COMPILE
>>> environment variable or use the `--no-auto-compile' switch.
>>> Unfortunately, there is no `--quiet' or `--warning=/dev/null' option.
>>
>> I think the OP is fine with autocompilation (I even guess they expect
>> it, i.e. changing the source file and getting old behaviour would be
>> a surprise), they just want it to happen silently (as Tomas has hinted
>> at).
>
> Not possible unfortunately :-(
Why would this be unfortunate? This seems like a feature (non-bug).
If it is autocompiling something you think is already compiled
then either your thought or the build/make/autocompile system is buggy.
Don't kill the message, fix the error.
-- Keith
On Fri, 15 Mar 2024, <tomas@tuxteam.de> wrote:
> On Fri, Mar 15, 2024 at 01:31:43PM -0400, Olivier Dion wrote:
>> On Fri, 15 Mar 2024, ksoft@sent.com wrote:
>> > I am in the process of rewriting in Guile a script that I use
>> > regularly. Running Guile 3.0.9, when I execute a file containing
>
> [...]
>
>> Like the warning says, you ought to either use the GUILE_AUTO_COMPILE
>> environment variable or use the `--no-auto-compile' switch.
>> Unfortunately, there is no `--quiet' or `--warning=/dev/null' option.
>
> I think the OP is fine with autocompilation (I even guess they expect
> it, i.e. changing the source file and getting old behaviour would be
> a surprise), they just want it to happen silently (as Tomas has hinted
> at).
Not possible unfortunately :-(
--
Olivier Dion
oldiob.ca
[-- Attachment #1: Type: text/plain, Size: 710 bytes --] On Fri, Mar 15, 2024 at 01:31:43PM -0400, Olivier Dion wrote: > On Fri, 15 Mar 2024, ksoft@sent.com wrote: > > I am in the process of rewriting in Guile a script that I use > > regularly. Running Guile 3.0.9, when I execute a file containing [...] > Like the warning says, you ought to either use the GUILE_AUTO_COMPILE > environment variable or use the `--no-auto-compile' switch. > Unfortunately, there is no `--quiet' or `--warning=/dev/null' option. I think the OP is fine with autocompilation (I even guess they expect it, i.e. changing the source file and getting old behaviour would be a surprise), they just want it to happen silently (as Tomas has hinted at). Cheers -- tomás [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 195 bytes --]
On Fri, 15 Mar 2024, ksoft@sent.com wrote:
> I am in the process of rewriting in Guile a script that I use
> regularly. Running Guile 3.0.9, when I execute a file containing
>
> #!/usr/local/bin/guile -s
> !#
> (display "Hello, mailing list!")
> (newline)
>
> the following is printed to standard error:
>
> ;;; note: source file /Users/me/./test.scm
> ;;; newer than compiled /Users/me/.cache/guile/ccache/3.0-LE-8-4.6/Users/me/test.scm.go
> ;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0
> ;;; or pass the --no-auto-compile argument to disable.
> ;;; compiling /Users/me/./test.scm
> ;;; compiled
> /Users/me/.cache/guile/ccache/3.0-LE-8-4.6/Users/me/test.scm.go
Like the warning says, you ought to either use the GUILE_AUTO_COMPILE
environment variable or use the `--no-auto-compile' switch.
Unfortunately, there is no `--quiet' or `--warning=/dev/null' option.
What I typically do is to compile modules and not compile scripts
(program entrypoints). So in the end, I have the following prologue for
portable Guile script:
--8<---------------cut here---------------start------------->8---
#!/bin/sh
#-*-Scheme-*-
GUILE="$(command -v guile || command -v guile3.0)"
if [ -z "$GUILE" ]; then
echo "Missing guile executable."
exit 1
fi
exec $GUILE --no-auto-compile -e main -s "$0" "$@"
!#
--8<---------------cut here---------------end--------------->8---
Note the usage of `--no-auto-compile' which will prevent Guile from
auto-compiling file, while still loading already compiled modules.
[...]
--
Olivier Dion
oldiob.ca
[-- Attachment #1: Type: text/plain, Size: 1654 bytes --] Hello, On 2024-03-15 12:15:33 -0500, ksoft@sent.com wrote: > I am in the process of rewriting in Guile a script that I use regularly. Running Guile 3.0.9, when I execute a file containing > > #!/usr/local/bin/guile -s > !# > (display "Hello, mailing list!") > (newline) > > the following is printed to standard error: > > ;;; note: source file /Users/me/./test.scm > ;;; newer than compiled /Users/me/.cache/guile/ccache/3.0-LE-8-4.6/Users/me/test.scm.go > ;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0 > ;;; or pass the --no-auto-compile argument to disable. > ;;; compiling /Users/me/./test.scm > ;;; compiled /Users/me/.cache/guile/ccache/3.0-LE-8-4.6/Users/me/test.scm.go > > While not showstopping, it would be preferable if there were a way to suppress the message. You technically can disable the message by disabling the auto-compilation, which can be done using environment variable, or the flag, directly from the script file itself. However disabling it might not be always desired. > This has been mentioned here and in other venues previously [1][2][3], but the last mention was over 10 years ago and perusal of the Guile manual suggests nothing toward this end has been implemented yet. Would adding a --quiet switch cause breakage? I think adding a switch to suppress the message should be fine, I think something like --auto-compilation-quiet or something would work. I would actually want that as well, but never got to writing the patch. Have a nice day, Tomas Volf -- There are only two hard things in Computer Science: cache invalidation, naming things and off-by-one errors. [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --]
I am in the process of rewriting in Guile a script that I use regularly. Running Guile 3.0.9, when I execute a file containing #!/usr/local/bin/guile -s !# (display "Hello, mailing list!") (newline) the following is printed to standard error: ;;; note: source file /Users/me/./test.scm ;;; newer than compiled /Users/me/.cache/guile/ccache/3.0-LE-8-4.6/Users/me/test.scm.go ;;; note: auto-compilation is enabled, set GUILE_AUTO_COMPILE=0 ;;; or pass the --no-auto-compile argument to disable. ;;; compiling /Users/me/./test.scm ;;; compiled /Users/me/.cache/guile/ccache/3.0-LE-8-4.6/Users/me/test.scm.go While not showstopping, it would be preferable if there were a way to suppress the message. This has been mentioned here and in other venues previously [1][2][3], but the last mention was over 10 years ago and perusal of the Guile manual suggests nothing toward this end has been implemented yet. Would adding a --quiet switch cause breakage? Best, Kevin [1] https://lists.gnu.org/archive/html/guile-user/2011-03/msg00002.html [2] https://lists.gnu.org/archive/html/guile-devel/2011-03/msg00373.html [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=734009
Hello Jean! On 3/15/24 09:03, Jean Abou Samra wrote: >> My question is: Do the ... in the case >> >> ((test id _kt _kf) _kt) ... >> >> produce one case for each identifier in the list? > > Yes, they do. > > >> I am guessing that this is what they do. However, they are mentioned as literals in the inner syntax-rules, > > No, they aren't. The (id ...) form is expanded by the outer syntax-rules > form, as part of expanding the id-memv?? macro. They don't remain in the > expanded result. For example, if you call > > (id-memv?? foo (foo bar baz) kt kf) > > the expansion will look like > > (let-syntax ((test > (syntax-rules (foo bar baz) > ((test foo _kt _kf) _kf) > ((test bar _kt _kf) _kf) > ((test baz _kt _kf) _kf) > ((test otherwise _kt _kf) _kf)))) > (test foo kt kf)) Aha! Of course! The inner syntax-rules is nothing special from the perspective of the outer syntax-rules! Somehow I saw it as something special and "evaluated from the inside out" in my head instead of from the "outside in", as I should have been doing. That makes a lot more sense now. >> so I was thinking the expansion will simply put literally three dots there, >> instead of understanding the three dots to mean "for each of the ids". >> >> And also I still am unsure about whether the three dots work like this at all. > > They do. > > >> When one puts the ... after a compound expression, that contains the thing, that >> the ... were after in the matching -- in this case they were after id, and id is >> contained in the compound expression (test id _kt _kf) _kt) -- does that make >> the compound expression be generated for each thing matched? > > Yes, see: > > (syntax->datum > (with-syntax ((simple #'a) > ((compound ...) #'(b c d)) > (((nested-compound ...) ...) #'((e f g) (h i j)))) > #'(((simple compound nested-compound) ...) ...))) > > ⇒ (((a b e) (a c f) (a d g)) ((a b h) (a c i) (a d j))) That example is quite difficult to unpack for me, but I think I get it. Sort of. It is showing the reverse thing, not matching, but telling Guile what the match is. And then using that in an expression. >> But if this is the case, then I might be misunderstanding the Guile docs at >> https://www.gnu.org/software/guile/manual/html_node/Syntax-Rules.html: >> >> "Instances of a pattern variable in the template must be followed by an ellipsis." > Note that this is talking about the patterns, not the syntax forms. But it > is slightly misleading: also in patterns it is perfectly possible to do > something like > > (syntax->datum > (with-syntax ((((a b) ...) #'((1 2) (3 4) (5 6)))) > #'((a ...) . (b ...)))) > > ⇒ ((1 3 5) 2 4 6) OK, this is easier to understand. It tells Guile what values A and B will be and then uses A and B in another way. But still quite cool, that this is possible. Not sure where to use it yet. > Note the pattern > > ((a b) ...) > > An ellipsized pattern is recognized by the ellipsis, but it doesn't > need to follow a simple pattern variable, it can follow a nested > pattern. What do you mean by "follow a nested pattern"? > Best, > Jean As before, thanks for the revelations! Zelphir -- repositories:https://notabug.org/ZelphirKaltstahl
[-- Attachment #1: Type: text/plain, Size: 2398 bytes --] > My question is: Do the ... in the case > > ((test id _kt _kf) _kt) ... > > produce one case for each identifier in the list? Yes, they do. > I am guessing that this is what they do. However, they are mentioned as literals in the inner syntax-rules, No, they aren't. The (id ...) form is expanded by the outer syntax-rules form, as part of expanding the id-memv?? macro. They don't remain in the expanded result. For example, if you call (id-memv?? foo (foo bar baz) kt kf) the expansion will look like (let-syntax ((test (syntax-rules (foo bar baz) ((test foo _kt _kf) _kf) ((test bar _kt _kf) _kf) ((test baz _kt _kf) _kf) ((test otherwise _kt _kf) _kf)))) (test foo kt kf)) > so I was thinking the expansion will simply put literally three dots there, > instead of understanding the three dots to mean "for each of the ids". > > And also I still am unsure about whether the three dots work like this at all. They do. > When one puts the ... after a compound expression, that contains the thing, that > the ... were after in the matching -- in this case they were after id, and id is > contained in the compound expression (test id _kt _kf) _kt) -- does that make > the compound expression be generated for each thing matched? Yes, see: (syntax->datum (with-syntax ((simple #'a) ((compound ...) #'(b c d)) (((nested-compound ...) ...) #'((e f g) (h i j)))) #'(((simple compound nested-compound) ...) ...))) ⇒ (((a b e) (a c f) (a d g)) ((a b h) (a c i) (a d j))) > But if this is the case, then I might be misunderstanding the Guile docs at > https://www.gnu.org/software/guile/manual/html_node/Syntax-Rules.html: > > "Instances of a pattern variable in the template must be followed by an ellipsis." Note that this is talking about the patterns, not the syntax forms. But it is slightly misleading: also in patterns it is perfectly possible to do something like (syntax->datum (with-syntax ((((a b) ...) #'((1 2) (3 4) (5 6)))) #'((a ...) . (b ...)))) ⇒ ((1 3 5) 2 4 6) Note the pattern ((a b) ...) An ellipsized pattern is recognized by the ellipsis, but it doesn't need to follow a simple pattern variable, it can follow a nested pattern. Best, Jean [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 228 bytes --]
Hello Guile Users, I have another macro understanding question and I think I don't yet grasp all the usages of the ellipsis/tripple dot/... : Again it is a macro from https://okmij.org/ftp/Scheme/assert-syntax-rule.txt. This time the id-memv macro, which I think I mostly understand, but have questions about: ~~~~ ;; A macro-expand-time memv function for identifiers ;; id-memv?? FORM (ID ...) KT KF ;; FORM is an arbitrary form or datum, ID is an identifier. ;; The macro expands into KT if FORM is an identifier, which occurs ;; in the list of identifiers supplied by the second argument. ;; All the identifiers in that list must be unique. ;; Otherwise, id-memv?? expands to KF. ;; Two identifiers match if both refer to the same binding occurrence, or ;; (both are undefined and have the same spelling). (define-syntax id-memv?? (syntax-rules () ((id-memv?? form (id ...) kt kf) (let-syntax ((test ;; Putting the ID matched in the outer syntax-rules ;; form, where it is flexible to stand for any ;; identifier, into the literals list makes it so, ;; that whatever was matched in the outer ;; syntax-rules is now literally matched against in ;; the inner syntax-rules. (syntax-rules (id ...) ;; If indeed FORM is the same identifier as ID, ;; then the result is the continuation for the ;; true case. ((test id _kt _kf) _kt) ... ((test otherwise _kt _kf) _kf)))) ;; Pass the form to be checked to test. (test form kt kf))))) ~~~~ My question is: Do the ... in the case ((test id _kt _kf) _kt) ... produce one case for each identifier in the list? I am guessing that this is what they do. However, they are mentioned as literals in the inner syntax-rules, so I was thinking the expansion will simply put literally three dots there, instead of understanding the three dots to mean "for each of the ids". And also I still am unsure about whether the three dots work like this at all. When one puts the ... after a compound expression, that contains the thing, that the ... were after in the matching -- in this case they were after id, and id is contained in the compound expression (test id _kt _kf) _kt) -- does that make the compound expression be generated for each thing matched? For example: (id-memv?? c (a b c) #t #f) would internally expand into the cases: ((test a _kt _kf) _kt) _kt) ((test b _kt _kf) _kt) _kt) ((test c _kt _kf) _kt) _kt) ((test otherwise _kt _kf) _kf) ? But if this is the case, then I might be misunderstanding the Guile docs at https://www.gnu.org/software/guile/manual/html_node/Syntax-Rules.html: "Instances of a pattern variable in the template must be followed by an ellipsis." So maybe I am just trying to see things here. Best regards, Zelphir repositories:https://notabug.org/ZelphirKaltstahl
> Ah, and I though that syntax-rules was always written in term of
> syntax-case. I see. Thank you!
Yeah, it most most often is these days, but historically, syntax-rules was invented before syntax-case. IIRC, the choice to include syntax-case in R6RS was controversial because syntax-rules was expressed in terms of different low-level abstractions in some Scheme implementations ("explicit substitutions" or something like that).
On Thu, 14 Mar 2024, Jean Abou Samra <jean@abou-samra.fr> wrote:
>> Excuse my ignorance, by why is symbol?? not written using syntax-cases
>> and the `indentifier?' guard?
>
> a) Because it's intellectually interesting to see what the power of syntax-rules is :)
> b) Not all Scheme standards and implementations contain syntax-case.
Ah, and I though that syntax-rules was always written in term of
syntax-case. I see. Thank you!
--
Olivier Dion
oldiob.ca
> Excuse my ignorance, by why is symbol?? not written using syntax-cases
> and the `indentifier?' guard?
a) Because it's intellectually interesting to see what the power of syntax-rules is :)
b) Not all Scheme standards and implementations contain syntax-case.
Excuse my ignorance, by why is symbol?? not written using syntax-cases
and the `indentifier?' guard?
On Thu, 14 Mar 2024, Zelphir Kaltstahl <zelphirkaltstahl@posteo.de> wrote:
> Hello Guile Users!
>
> I am having trouble understanding how the `symbol??` macro from
> https://okmij.org/ftp/Scheme/assert-syntax-rule.txt works.
>
> Here is what I have so far:
>
> ~~~~start~~~~
> ;; (symbol?? FORM KT KF)
> ;; FORM is an arbitrary form or datum.
> ;; A symbol? predicate at the macro-expand time.
> ;; Expands in KT if FORM is a symbol (identifier), Otherwise, expands in KF.
> ;; KT: Continuation/Case in case of true.
> ;; KF: Continuation/Case in case of false.
> (define-syntax symbol??
> (syntax-rules ()
> ;; The check is done by first pattern matching against some other
> ;; forms, that are not a symbol.
> ((symbol?? (x . y) kt kf) kf) ; It's a pair, not a symbol
> ((symbol?? #(x ...) kt kf) kf) ; It's a vector, not a symbol
> ;; After those things are excluded, the thing might be a symbol.
> ((symbol?? maybe-symbol kt kf)
> (let-syntax ((test
> (syntax-rules ()
> ((test maybe-symbol t f) t)
> ((test x t f) f))))
> (test abracadabra kt kf)))))
> ~~~~~end~~~~~
>
> So I don't understand why `test` works or how it works to check, whether
> `maybe-symbol` is a symbol or not. And I don't understand how `abracadabra`
> helps with that, or why it helps, to pass something undefined.
>
> Can someone help me understand, what is going on there?
>
> Actually I am trying to understand the whole page, and I got there while looking
> for a good `assert` macro ... rabbit hole and all that.
>
> Best regards,
> Zelphir
>
> --
> repositories:https://notabug.org/ZelphirKaltstahl
--
Olivier Dion
oldiob.ca
On 3/14/24 02:01, Jean Abou Samra wrote: > Hi! > > The explanations are on > > https://okmij.org/ftp/Scheme/macros.html#macro-symbol-p > > Maybe this version will be easier to understand (we don't really > need continuation-passing style here): > > (define-syntax symbol?? > (syntax-rules () > ((symbol?? maybe-symbol) > (let-syntax > ((test > (syntax-rules () > ((test maybe-symbol) #t) > ((test _) #f)))) > (test abracadabra))))) > > (symbol?? foo) ⇒ #t > (symbol?? (a . b)) ⇒ #f > (symbol?? 5) ⇒ #f > (symbol?? "a") ⇒ #f > (symbol?? #(1 a)) ⇒ #f > > > Basically: the macro call > > (symbol?? <foobar>) > > expands to a macro definition of test as > > (syntax-rules () > ((test <foobar>) #t) > ((test _) #f)) > > and a call (test abracadabra). Now, observe that if <foobar> > is a symbol, then it's a catch-all pattern when inserted > in the syntax-rules definition of `test`, so it will match > abracadabra (because it matches anything). On the other hand, > if it's not a symbol, then it won't match abracadabra, by case > analysis: if it's a number it will only match that number; booleans, > strings and characters likewise; if it's a pair it can only match > pairs; if it's a vector it can only match vectors; etc. > > I'm not exactly sure why Oleg Kiselyov included special cases for a pair > and a vector, but my guess is that not all Scheme implementations > support vectors in syntax-rules patterns (and the pair check is > necessary because the car or cdr could contain a vector). The Scheme > standards certainly have their opinion on this, and I knew that > stuff by heart at some point (when I implemented a syntax-rules/syntax-case > expander for a university project), but I don't remember, and it's > too late for scouring the standards... > > Best, > Jean On 3/14/24 02:03, Maxime Devos wrote: > > (define-syntax symbol?? > > (syntax-rules () > > ;; The check is done by first pattern matching against some other > > ;; forms, that are not a symbol. > > ((symbol?? (x . y) kt kf) kf) ; It's a pair, not a symbol > > ((symbol?? #(x ...) kt kf) kf) ; It's a vector, not a symbol > > The first two cases don’t need any explanation I think. > > ;; After those things are excluded, the thing might be a symbol. > > ((symbol?? maybe-symbol kt kf) > > (let-syntax ((test > > (syntax-rules () > > ((test maybe-symbol t f) t) > > ((test x t f) f)))) > > (test abracadabra kt kf))))) > > If maybe-symbol is a symbol, then (test abracadabra kt kf) matches (test > maybe-symbol t f) (let t=kt, f=kf, maybe-symbol=abracadabra). > > If maybe-symbol is not a symbol, for example it is a string “hello” (please > ignore wrong quoting), then > > (test maybe-symbol t f) becomes (test “hello” t f). The string “hello” cannot > act as an identifier (because it is a string, not a symbol), so (test > abracadabra kt kf) does not match the first case (test maybe-symbol t f). Only > the second case (test x t f) remains, and (test abracadabra kt kf) matches > this (set x to abracadabra, t to kt, f to kf). > > I think the first two cases are superfluous, but perhaps there is a > performance advantage. > > (I’m wondering if this still works in the case (symbol? ...), because ... is > special in syntax-rules) > > Best regards, > > Maxime Devos. > Thank you both! Mind-blowing stuff. But I think I understand it now. How clever. Best regards, Zelphir -- repositories:https://notabug.org/ZelphirKaltstahl
(define-syntax symbol?? (syntax-rules () ;; The check is done by first pattern matching against some other ;; forms, that are not a symbol. ((symbol?? (x . y) kt kf) kf) ; It's a pair, not a symbol ((symbol?? #(x ...) kt kf) kf) ; It's a vector, not a symbol The first two cases don’t need any explanation I think. ;; After those things are excluded, the thing might be a symbol. ((symbol?? maybe-symbol kt kf) (let-syntax ((test (syntax-rules () ((test maybe-symbol t f) t) ((test x t f) f)))) (test abracadabra kt kf))))) If maybe-symbol is a symbol, then (test abracadabra kt kf) matches (test maybe-symbol t f) (let t=kt, f=kf, maybe-symbol=abracadabra). If maybe-symbol is not a symbol, for example it is a string “hello” (please ignore wrong quoting), then (test maybe-symbol t f) becomes (test “hello” t f). The string “hello” cannot act as an identifier (because it is a string, not a symbol), so (test abracadabra kt kf) does not match the first case (test maybe-symbol t f). Only the second case (test x t f) remains, and (test abracadabra kt kf) matches this (set x to abracadabra, t to kt, f to kf). I think the first two cases are superfluous, but perhaps there is a performance advantage. (I’m wondering if this still works in the case (symbol? ...), because ... is special in syntax-rules) Best regards, Maxime Devos.
[-- Attachment #1: Type: text/plain, Size: 1772 bytes --] Hi! The explanations are on https://okmij.org/ftp/Scheme/macros.html#macro-symbol-p Maybe this version will be easier to understand (we don't really need continuation-passing style here): (define-syntax symbol?? (syntax-rules () ((symbol?? maybe-symbol) (let-syntax ((test (syntax-rules () ((test maybe-symbol) #t) ((test _) #f)))) (test abracadabra))))) (symbol?? foo) ⇒ #t (symbol?? (a . b)) ⇒ #f (symbol?? 5) ⇒ #f (symbol?? "a") ⇒ #f (symbol?? #(1 a)) ⇒ #f Basically: the macro call (symbol?? <foobar>) expands to a macro definition of test as (syntax-rules () ((test <foobar>) #t) ((test _) #f)) and a call (test abracadabra). Now, observe that if <foobar> is a symbol, then it's a catch-all pattern when inserted in the syntax-rules definition of `test`, so it will match abracadabra (because it matches anything). On the other hand, if it's not a symbol, then it won't match abracadabra, by case analysis: if it's a number it will only match that number; booleans, strings and characters likewise; if it's a pair it can only match pairs; if it's a vector it can only match vectors; etc. I'm not exactly sure why Oleg Kiselyov included special cases for a pair and a vector, but my guess is that not all Scheme implementations support vectors in syntax-rules patterns (and the pair check is necessary because the car or cdr could contain a vector). The Scheme standards certainly have their opinion on this, and I knew that stuff by heart at some point (when I implemented a syntax-rules/syntax-case expander for a university project), but I don't remember, and it's too late for scouring the standards... Best, Jean [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 228 bytes --]