Message ID | 87wofwa0wl.fsf@gmail.com |
---|---|
State | Accepted |
Headers | show |
Series | [bug#36875] doc: Document the use of `program-file' for mcron jobs. | expand |
Hello! Maxim Cournoyer <maxim.cournoyer@gmail.com> skribis: > From 0fffed46b4899bf0485926399d3971a4b5e94408 Mon Sep 17 00:00:00 2001 > From: Maxim Cournoyer <maxim.cournoyer@gmail.com> > Date: Thu, 1 Aug 2019 07:34:17 +0900 > Subject: [PATCH] doc: Document the use of `program-file' for mcron jobs. > > * doc/guix.texi (Scheduled Job Execution): Explain why using `program-file' > for an mcron job can be necessary. Add an example. [...] > +For more complex jobs defined in Scheme, it is safer to pass the job as a > +script to mcron; otherwise, macros defined or imported with @code{use-modules} > +wouldn't expand correctly, as Guile requires macros to be strictly defined or > +imported at the top level of a Guile module. This can be achieved using the > +@code{program-file} procedure from the @code{(guix gexp)} module, as shown in > +the example below. Macros are a very good example of the problem, but I wonder if it would be clearer to simply write something like: For more complex jobs defined in Scheme where you need control over the top level, for instance to introduce a @code{use-modules} form, you can move your code to a separate program using the @code{program-file} procedure of the @code{(guix gexp)} module (@pxref{G-Expressions}). The example below illustrates that. Anyway, your patch looks like a great improvement (and a funny example :-)) so IMO you should push one version or another! Thanks, Ludo’.
Hello Ludovic! Ludovic Courtès <ludo@gnu.org> writes: > Hello! > > Maxim Cournoyer <maxim.cournoyer@gmail.com> skribis: > >> From 0fffed46b4899bf0485926399d3971a4b5e94408 Mon Sep 17 00:00:00 2001 >> From: Maxim Cournoyer <maxim.cournoyer@gmail.com> >> Date: Thu, 1 Aug 2019 07:34:17 +0900 >> Subject: [PATCH] doc: Document the use of `program-file' for mcron jobs. >> >> * doc/guix.texi (Scheduled Job Execution): Explain why using `program-file' >> for an mcron job can be necessary. Add an example. > > [...] > >> +For more complex jobs defined in Scheme, it is safer to pass the job as a >> +script to mcron; otherwise, macros defined or imported with @code{use-modules} >> +wouldn't expand correctly, as Guile requires macros to be strictly defined or >> +imported at the top level of a Guile module. This can be achieved using the >> +@code{program-file} procedure from the @code{(guix gexp)} module, as shown in >> +the example below. > > Macros are a very good example of the problem, but I wonder if it would > be clearer to simply write something like: > > For more complex jobs defined in Scheme where you need control over > the top level, for instance to introduce a @code{use-modules} form, you > can move your code to a separate program using the @code{program-file} > procedure of the @code{(guix gexp)} module (@pxref{G-Expressions}). > The example below illustrates that. I like your version, which feels to me more elegant. But, from my experimentation, using (use-modules) in a nested form is fine for anything else than syntax (macros). Also, the Guile Reference only says that macros must be *defined* at the top level; it doesn't explicitly mention that importing macros is equivalent to defining macros, and are thus subjected to the same restrictions. So, I've amended it to mention the problem more precisely: --8<---------------cut here---------------start------------->8--- For more complex jobs defined in Scheme where you need control over the top level, for instance to introduce a @code{use-modules} form that defines syntax (macros), you can move your code to a separate program using the @code{program-file} procedure of the @code{(guix gexp)} module (@pxref{G-Expressions}). The example below illustrates that. --8<---------------cut here---------------end--------------->8--- > Anyway, your patch looks like a great improvement (and a funny example > :-)) so IMO you should push one version or another! This is now live as commit 1407ebeaa1. Thanks for feedback/review! :-) Maxim
Hi Maxim, Maxim Cournoyer <maxim.cournoyer@gmail.com> skribis: > Ludovic Courtès <ludo@gnu.org> writes: > >> Hello! >> >> Maxim Cournoyer <maxim.cournoyer@gmail.com> skribis: >> >>> From 0fffed46b4899bf0485926399d3971a4b5e94408 Mon Sep 17 00:00:00 2001 >>> From: Maxim Cournoyer <maxim.cournoyer@gmail.com> >>> Date: Thu, 1 Aug 2019 07:34:17 +0900 >>> Subject: [PATCH] doc: Document the use of `program-file' for mcron jobs. >>> >>> * doc/guix.texi (Scheduled Job Execution): Explain why using `program-file' >>> for an mcron job can be necessary. Add an example. >> >> [...] >> >>> +For more complex jobs defined in Scheme, it is safer to pass the job as a >>> +script to mcron; otherwise, macros defined or imported with @code{use-modules} >>> +wouldn't expand correctly, as Guile requires macros to be strictly defined or >>> +imported at the top level of a Guile module. This can be achieved using the >>> +@code{program-file} procedure from the @code{(guix gexp)} module, as shown in >>> +the example below. >> >> Macros are a very good example of the problem, but I wonder if it would >> be clearer to simply write something like: >> >> For more complex jobs defined in Scheme where you need control over >> the top level, for instance to introduce a @code{use-modules} form, you >> can move your code to a separate program using the @code{program-file} >> procedure of the @code{(guix gexp)} module (@pxref{G-Expressions}). >> The example below illustrates that. > > I like your version, which feels to me more elegant. But, from my > experimentation, using (use-modules) in a nested form is fine for > anything else than syntax (macros). That’s right, but I strongly recommend not relying on non-toplevel ‘use-modules’ because (1) it’s “ugly” because it introduces new bindings at run time, and (2) it’s not guaranteed to work in the future—in fact, the just-released Guile 2.9.4 introduces “declarative modules”, which is probably a first step in the direction of less run-time trickery with modules. > This is now live as commit 1407ebeaa1. Thanks for feedback/review! :-) Great, thank you! Ludo’.
Hello Ludovic, Ludovic Courtès <ludo@gnu.org> writes: > Hi Maxim, > > Maxim Cournoyer <maxim.cournoyer@gmail.com> skribis: > >> Ludovic Courtès <ludo@gnu.org> writes: >> >>> Hello! >>> >>> Maxim Cournoyer <maxim.cournoyer@gmail.com> skribis: >>> >>>> From 0fffed46b4899bf0485926399d3971a4b5e94408 Mon Sep 17 00:00:00 2001 >>>> From: Maxim Cournoyer <maxim.cournoyer@gmail.com> >>>> Date: Thu, 1 Aug 2019 07:34:17 +0900 >>>> Subject: [PATCH] doc: Document the use of `program-file' for mcron jobs. >>>> >>>> * doc/guix.texi (Scheduled Job Execution): Explain why using `program-file' >>>> for an mcron job can be necessary. Add an example. [...] >>> Macros are a very good example of the problem, but I wonder if it would >>> be clearer to simply write something like: >>> >>> For more complex jobs defined in Scheme where you need control over >>> the top level, for instance to introduce a @code{use-modules} form, you >>> can move your code to a separate program using the @code{program-file} >>> procedure of the @code{(guix gexp)} module (@pxref{G-Expressions}). >>> The example below illustrates that. >> >> I like your version, which feels to me more elegant. But, from my >> experimentation, using (use-modules) in a nested form is fine for >> anything else than syntax (macros). > > That’s right, but I strongly recommend not relying on non-toplevel > ‘use-modules’ because (1) it’s “ugly” because it introduces new bindings > at run time, and (2) it’s not guaranteed to work in the future—in fact, > the just-released Guile 2.9.4 introduces “declarative modules”, which is > probably a first step in the direction of less run-time trickery with > modules. Oh! That's good to know! Then using your proposed text as-is makes even more sense. Done in commit 4183105de0. Thank you! Maxim
From 0fffed46b4899bf0485926399d3971a4b5e94408 Mon Sep 17 00:00:00 2001 From: Maxim Cournoyer <maxim.cournoyer@gmail.com> Date: Thu, 1 Aug 2019 07:34:17 +0900 Subject: [PATCH] doc: Document the use of `program-file' for mcron jobs. * doc/guix.texi (Scheduled Job Execution): Explain why using `program-file' for an mcron job can be necessary. Add an example. --- doc/guix.texi | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/doc/guix.texi b/doc/guix.texi index e6047a4909..dd06efa9c2 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -12444,6 +12444,41 @@ gexps to introduce job definitions that are passed to mcron %base-services))) @end lisp +For more complex jobs defined in Scheme, it is safer to pass the job as a +script to mcron; otherwise, macros defined or imported with @code{use-modules} +wouldn't expand correctly, as Guile requires macros to be strictly defined or +imported at the top level of a Guile module. This can be achieved using the +@code{program-file} procedure from the @code{(guix gexp)} module, as shown in +the example below. + +@lisp +(define %battery-alert-job + ;; Beep when the battery percentage falls below %MIN-LEVEL. + #~(job + '(next-minute (range 0 60 1)) + #$(program-file + "battery-alert.scm" + (with-imported-modules (source-module-closure + '((guix build utils))) + #~(begin + (define %min-level 20) + (use-modules (guix build utils) + (ice-9 popen) + (ice-9 regex) + (ice-9 textual-ports) + (srfi srfi-2)) + (setenv "LC_ALL" "C") + (and-let* ((input-pipe (open-pipe* + OPEN_READ + #$(file-append acpi "/bin/acpi"))) + (output (get-string-all input-pipe)) + (m (string-match "Discharging, ([0-9]+)%" output)) + (level (string->number (match:substring m 1))) + ((< level %min-level))) + (format #t "warning: Battery level is low (~a%)~%" level) + (invoke #$(file-append beep "/bin/beep") "-r5"))))))) +@end lisp + @xref{Guile Syntax, mcron job specifications,, mcron, GNU@tie{}mcron}, for more information on mcron job specifications. Below is the reference of the mcron service. -- 2.21.0