summaryrefslogtreecommitdiff
path: root/doc/ref/scheme-scripts.texi
blob: 221c8ba205999c1db9e71f65859980dc6d34dfa8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
@c -*-texinfo-*-
@c This is part of the GNU Guile Reference Manual.
@c Copyright (C)  1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2010, 2011
@c   Free Software Foundation, Inc.
@c See the file guile.texi for copying conditions.

@node Guile Scripting
@section Guile Scripting

Like AWK, Perl, or any shell, Guile can interpret script files.  A Guile
script is simply a file of Scheme code with some extra information at
the beginning which tells the operating system how to invoke Guile, and
then tells Guile how to handle the Scheme code.

@menu
* The Top of a Script File::    How to start a Guile script.
* The Meta Switch::             Passing complex argument lists to Guile
                                from shell scripts.
* Command Line Handling::       Accessing the command line from a script.
* Scripting Examples::
@end menu


@node The Top of a Script File
@subsection The Top of a Script File

The first line of a Guile script must tell the operating system to use
Guile to evaluate the script, and then tell Guile how to go about doing
that.  Here is the simplest case:

@itemize @bullet

@item
The first two characters of the file must be @samp{#!}.

The operating system interprets this to mean that the rest of the line
is the name of an executable that can interpret the script.  Guile,
however, interprets these characters as the beginning of a multi-line
comment, terminated by the characters @samp{!#} on a line by themselves.
(This is an extension to the syntax described in R5RS, added to support
shell scripts.)

@item
Immediately after those two characters must come the full pathname to
the Guile interpreter.  On most systems, this would be
@samp{/usr/local/bin/guile}.

@item
Then must come a space, followed by a command-line argument to pass to
Guile; this should be @samp{-s}.  This switch tells Guile to run a
script, instead of soliciting the user for input from the terminal.
There are more elaborate things one can do here; see @ref{The Meta
Switch}.

@item
Follow this with a newline.

@item
The second line of the script should contain only the characters
@samp{!#} --- just like the top of the file, but reversed.  The
operating system never reads this far, but Guile treats this as the end
of the comment begun on the first line by the @samp{#!} characters.

@item
If this source code file is not ASCII or ISO-8859-1 encoded, a coding
declaration such as @code{coding: utf-8} should appear in a comment
somewhere in the first five lines of the file: see @ref{Character
Encoding of Source Files}.

@item
The rest of the file should be a Scheme program.

@end itemize

Guile reads the program, evaluating expressions in the order that they
appear.  Upon reaching the end of the file, Guile exits.

@node The Meta Switch
@subsection The Meta Switch

Guile's command-line switches allow the programmer to describe
reasonably complicated actions in scripts.  Unfortunately, the POSIX
script invocation mechanism only allows one argument to appear on the
@samp{#!} line after the path to the Guile executable, and imposes
arbitrary limits on that argument's length.  Suppose you wrote a script
starting like this:
@example
#!/usr/local/bin/guile -e main -s
!#
(define (main args)
  (map (lambda (arg) (display arg) (display " "))
       (cdr args))
  (newline))
@end example
The intended meaning is clear: load the file, and then call @code{main}
on the command-line arguments.  However, the system will treat
everything after the Guile path as a single argument --- the string
@code{"-e main -s"} --- which is not what we want.

As a workaround, the meta switch @code{\} allows the Guile programmer to
specify an arbitrary number of options without patching the kernel.  If
the first argument to Guile is @code{\}, Guile will open the script file
whose name follows the @code{\}, parse arguments starting from the
file's second line (according to rules described below), and substitute
them for the @code{\} switch.

Working in concert with the meta switch, Guile treats the characters
@samp{#!} as the beginning of a comment which extends through the next
line containing only the characters @samp{!#}.  This sort of comment may
appear anywhere in a Guile program, but it is most useful at the top of
a file, meshing magically with the POSIX script invocation mechanism.

Thus, consider a script named @file{/u/jimb/ekko} which starts like this:
@example
#!/usr/local/bin/guile \
-e main -s
!#
(define (main args)
        (map (lambda (arg) (display arg) (display " "))
             (cdr args))
        (newline))
@end example

Suppose a user invokes this script as follows:
@example
$ /u/jimb/ekko a b c
@end example

Here's what happens:
@itemize @bullet

@item
the operating system recognizes the @samp{#!} token at the top of the
file, and rewrites the command line to:
@example
/usr/local/bin/guile \ /u/jimb/ekko a b c
@end example
This is the usual behavior, prescribed by POSIX.

@item
When Guile sees the first two arguments, @code{\ /u/jimb/ekko}, it opens
@file{/u/jimb/ekko}, parses the three arguments @code{-e}, @code{main},
and @code{-s} from it, and substitutes them for the @code{\} switch.
Thus, Guile's command line now reads:
@example
/usr/local/bin/guile -e main -s /u/jimb/ekko a b c
@end example

@item
Guile then processes these switches: it loads @file{/u/jimb/ekko} as a
file of Scheme code (treating the first three lines as a comment), and
then performs the application @code{(main "/u/jimb/ekko" "a" "b" "c")}.

@end itemize


When Guile sees the meta switch @code{\}, it parses command-line
argument from the script file according to the following rules:
@itemize @bullet

@item
Each space character terminates an argument.  This means that two
spaces in a row introduce an argument @code{""}.

@item
The tab character is not permitted (unless you quote it with the
backslash character, as described below), to avoid confusion.

@item
The newline character terminates the sequence of arguments, and will
also terminate a final non-empty argument.  (However, a newline
following a space will not introduce a final empty-string argument;
it only terminates the argument list.)

@item
The backslash character is the escape character.  It escapes backslash,
space, tab, and newline.  The ANSI C escape sequences like @code{\n} and
@code{\t} are also supported.  These produce argument constituents; the
two-character combination @code{\n} doesn't act like a terminating
newline.  The escape sequence @code{\@var{NNN}} for exactly three octal
digits reads as the character whose ASCII code is @var{NNN}.  As above,
characters produced this way are argument constituents.  Backslash
followed by other characters is not allowed.

@end itemize


@node Command Line Handling
@subsection Command Line Handling

@c This section was written and contributed by Martin Grabmueller.

The ability to accept and handle command line arguments is very
important when writing Guile scripts to solve particular problems, such
as extracting information from text files or interfacing with existing
command line applications.  This chapter describes how Guile makes
command line arguments available to a Guile script, and the utilities
that Guile provides to help with the processing of command line
arguments.

When a Guile script is invoked, Guile makes the command line arguments
accessible via the procedure @code{command-line}, which returns the
arguments as a list of strings.

For example, if the script

@example
#! /usr/local/bin/guile -s
!#
(write (command-line))
(newline)
@end example

@noindent
is saved in a file @file{cmdline-test.scm} and invoked using the command
line @code{./cmdline-test.scm bar.txt -o foo -frumple grob}, the output
is

@example
("./cmdline-test.scm" "bar.txt" "-o" "foo" "-frumple" "grob")
@end example

If the script invocation includes a @code{-e} option, specifying a
procedure to call after loading the script, Guile will call that
procedure with @code{(command-line)} as its argument.  So a script that
uses @code{-e} doesn't need to refer explicitly to @code{command-line}
in its code.  For example, the script above would have identical
behaviour if it was written instead like this:

@example
#! /usr/local/bin/guile \
-e main -s
!#
(define (main args)
  (write args)
  (newline))
@end example

(Note the use of the meta switch @code{\} so that the script invocation
can include more than one Guile option: @xref{The Meta Switch}.)

These scripts use the @code{#!} POSIX convention so that they can be
executed using their own file names directly, as in the example command
line @code{./cmdline-test.scm bar.txt -o foo -frumple grob}.  But they
can also be executed by typing out the implied Guile command line in
full, as in:

@example
$ guile -s ./cmdline-test.scm bar.txt -o foo -frumple grob
@end example

@noindent
or

@example
$ guile -e main -s ./cmdline-test2.scm bar.txt -o foo -frumple grob
@end example

Even when a script is invoked using this longer form, the arguments that
the script receives are the same as if it had been invoked using the
short form.  Guile ensures that the @code{(command-line)} or @code{-e}
arguments are independent of how the script is invoked, by stripping off
the arguments that Guile itself processes.

A script is free to parse and handle its command line arguments in any
way that it chooses.  Where the set of possible options and arguments is
complex, however, it can get tricky to extract all the options, check
the validity of given arguments, and so on.  This task can be greatly
simplified by taking advantage of the module @code{(ice-9 getopt-long)},
which is distributed with Guile, @xref{getopt-long}.


@node Scripting Examples
@subsection Scripting Examples

To start with, here are some examples of invoking Guile directly:

@table @code

@item guile -- a b c
Run Guile interactively; @code{(command-line)} will return @*
@code{("/usr/local/bin/guile" "a" "b" "c")}.

@item guile -s /u/jimb/ex2 a b c
Load the file @file{/u/jimb/ex2}; @code{(command-line)} will return @*
@code{("/u/jimb/ex2" "a" "b" "c")}.

@item guile -c '(write %load-path) (newline)'
Write the value of the variable @code{%load-path}, print a newline,
and exit.

@item guile -e main -s /u/jimb/ex4 foo
Load the file @file{/u/jimb/ex4}, and then call the function
@code{main}, passing it the list @code{("/u/jimb/ex4" "foo")}.

@item guile -e '(ex4)' -s /u/jimb/ex4.scm foo
Load the file @file{/u/jimb/ex4.scm}, and then call the function
@code{main} from the module '(ex4)', passing it the list
@code{("/u/jimb/ex4" "foo")}.

@item guile -l first -ds -l last -s script
Load the files @file{first}, @file{script}, and @file{last}, in that
order.  The @code{-ds} switch says when to process the @code{-s}
switch.  For a more motivated example, see the scripts below.

@end table


Here is a very simple Guile script:
@example
#!/usr/local/bin/guile -s
!#
(display "Hello, world!")
(newline)
@end example
The first line marks the file as a Guile script.  When the user invokes
it, the system runs @file{/usr/local/bin/guile} to interpret the script,
passing @code{-s}, the script's filename, and any arguments given to the
script as command-line arguments.  When Guile sees @code{-s
@var{script}}, it loads @var{script}.  Thus, running this program
produces the output:
@example
Hello, world!
@end example

Here is a script which prints the factorial of its argument:
@example
#!/usr/local/bin/guile -s
!#
(define (fact n)
  (if (zero? n) 1
    (* n (fact (- n 1)))))

(display (fact (string->number (cadr (command-line)))))
(newline)
@end example
In action:
@example
$ ./fact 5
120
$
@end example

However, suppose we want to use the definition of @code{fact} in this
file from another script.  We can't simply @code{load} the script file,
and then use @code{fact}'s definition, because the script will try to
compute and display a factorial when we load it.  To avoid this problem,
we might write the script this way:

@example
#!/usr/local/bin/guile \
-e main -s
!#
(define (fact n)
  (if (zero? n) 1
    (* n (fact (- n 1)))))

(define (main args)
  (display (fact (string->number (cadr args))))
  (newline))
@end example
This version packages the actions the script should perform in a
function, @code{main}.  This allows us to load the file purely for its
definitions, without any extraneous computation taking place.  Then we
used the meta switch @code{\} and the entry point switch @code{-e} to
tell Guile to call @code{main} after loading the script.
@example
$ ./fact 50
30414093201713378043612608166064768844377641568960512000000000000
@end example

Suppose that we now want to write a script which computes the
@code{choose} function: given a set of @var{m} distinct objects,
@code{(choose @var{n} @var{m})} is the number of distinct subsets
containing @var{n} objects each.  It's easy to write @code{choose} given
@code{fact}, so we might write the script this way:

@example
#!/usr/local/bin/guile \
-l fact -e main -s
!#
(define (choose n m)
  (/ (fact m) (* (fact (- m n)) (fact n))))

(define (main args)
  (let ((n (string->number (cadr args)))
        (m (string->number (caddr args))))
    (display (choose n m))
    (newline)))
@end example

The command-line arguments here tell Guile to first load the file
@file{fact}, and then run the script, with @code{main} as the entry
point.  In other words, the @code{choose} script can use definitions
made in the @code{fact} script.  Here are some sample runs:
@example
$ ./choose 0 4
1
$ ./choose 1 4
4
$ ./choose 2 4
6
$ ./choose 3 4
4
$ ./choose 4 4
1
$ ./choose 50 100
100891344545564193334812497256
@end example

To call a specific procedure from a given module, we can use the special
form @code{(@@ (@var{module}) @var{procedure})}:

@example
#!/usr/local/bin/guile \
-l fact -e (@@ (fac) main) -s
!#
(define-module (fac)
  #:export (main))

(define (choose n m)
  (/ (fact m) (* (fact (- m n)) (fact n))))

(define (main args)
  (let ((n (string->number (cadr args)))
        (m (string->number (caddr args))))
    (display (choose n m))
    (newline)))
@end example

We can use @code{@@@@} to invoke non-exported procedures.  For exported
procedures, we can simplify this call with the shorthand
@code{(@var{module})}:

@example
#!/usr/local/bin/guile \
-l fact -e (fac) -s
!#
(define-module (fac)
  #:export (main))

(define (choose n m)
  (/ (fact m) (* (fact (- m n)) (fact n))))

(define (main args)
  (let ((n (string->number (cadr args)))
        (m (string->number (caddr args))))
    (display (choose n m))
    (newline)))
@end example

For maximum portability, we can instead use the shell to execute
@command{guile} with specified command line arguments.  Here we need to
take care to quote the command arguments correctly:

@example
#!/usr/bin/env sh
exec guile -l fact -e '(@@ (fac) main)' -s "$0" "$@@"
!#
(define-module (fac)
  #:export (main))

(define (choose n m)
  (/ (fact m) (* (fact (- m n)) (fact n))))

(define (main args)
  (let ((n (string->number (cadr args)))
        (m (string->number (caddr args))))
    (display (choose n m))
    (newline)))
@end example

Finally, seasoned scripters are probably missing a mention of
subprocesses.  In Bash, for example, most shell scripts run other
programs like @code{sed} or the like to do the actual work.

In Guile it's often possible get everything done within Guile itself, so
do give that a try first.  But if you just need to run a program and
wait for it to finish, use @code{system*}.  If you need to run a
sub-program and capture its output, or give it input, use
@code{open-pipe}.  @xref{Processes}, and @xref{Pipes}, for more
information.


@c Local Variables:
@c TeX-master: "guile.texi"
@c End: