scheme shell
Date: Thu, 12 Jun 2003 20:09:00 +0000 (UTC)
From: clements at ccs neu edu (John B. Clements)
Message-ID: <bcamks$1rc$1 at camelot ccs neu edu>
Organization: Northeastern University, College of Computer Science
Subject: Re: idiomatic use of &&

In article <bcam8i$1n5$1 at camelot ccs neu edu>,
John B. Clements <clements at ccs neu edu> wrote:
>In article <bcace9$rk8$1 at camelot ccs neu edu>,
>John B. Clements <clements at ccs neu edu> wrote:
>>I'm trying to write a shell script using &&, and I run into
>>the following issue: Let's say I have a sequence of commands,
>>strung together with &&, and I want to set the cwd for some of
>>them.  Easy enough, I just stick a (begin (with-cwd ...)) into
>>the &&.  But now, suppose I have more than one process that
>>gets run inside the with-cwd.  I want the entire sequence of
>>commands to have the && behavior; that is, if any one of them
>>fails, the whole thing halts.
>>If I use a nested &&, I don't by default get this behavior:
>>> (&& (begin (&& (rm nonexistentfile) (echo aaaa))) (echo bbbb))
>>rm: nonexistentfile: No such file or directory
>>That makes sense to me, given the stated semantics of &&.
>>How do I change it so that any error halts the whole string?
>>Here's my solution, but it seems like there must be a more
>>idiomatic way of doing this:
>>> (define (propagate-error x) (if x #t (error 'sub-error)))
>>> (&& (begin (propagate-error (&& (rm nonexistentfile)
>>                                  (echo aaaa))))
>>      (echo bbb))
>>rm: nonexistentfile: No such file or directory
>>Error: sub-error
>GRRR!  So it turns out that this code behaves differently
>in the REPL than it does in a script.  In a script, the
>error gets swallowed in a different place. So my
>'propagate-error' solution works in the REPL, but not
>in a script.
>Reading the docs more carefully, I see that the (begin ...) 'pf'
>form is rather ominously documented as a 'fork'.  So perhaps
>I need a different mechanism for sequencing a mixture of
>process forms and scheme expressions.
>Isn't this a pretty common operation?

AHA! since it's forked off, I need to kill it with (exit 1),
not with an error.

Okay, this is a bit ugly, but it works.

Thanks (Mike) for your comments (on the other branch),