Hi Christophe,

> I was trying to avoid the «? prompt» in case of an error.
> I know that this REPL is sometimes useful, but not for my use case.
> I eventually succeeded with (de *Err (bye)).

Note that this should normally not be necessary. In debug mode it is not
wise to exit immediately, as you may want to find the reason of the

And in production mode a PicoLisp application is normally started in the
background. In that case it exits automatically after logging the error
message(s). See "doc/ref.html#errors":

   If the standard input is not from a terminal, the interpreter

Also, you can 'catch' errors and handle them.

> During this journey, I noticed a few things.
> About *Err, the doc says in:
> http://www.software-lab.de/doc/refE.html#*Err
> «a `prg` body». I didn't notice the use of `de`, so I first tried
> silly things like:
> (setq *Err (bye))  # this one is funny

Yeah, because the second argument to 'setq' is evaluated, so you
actually call (bye) and exit the interpreter :)

> (setq *Err '(bye))
> (setq *Err "(bye)")
> But none worked. So I went to:
> http://www.software-lab.de/doc/refP.html#prog
> A beginner may think that the body of `prog` is not really a list.

Well, the explanation of the ref syntax in "doc/ref.html#fun" explicitly
says that it is a list:

   • prg - Prog-Body: A list of executable expressions (run)

> A beginner would rather think that the body of `run`
> (or rather its first parameter) is a list.

Hmm, not sure. 'run' takes a list of 'exe's (Lisp expressions).

> So I didn't know what to do from here, except going to the part of

A good idea is also to search through the sources. You find a real-world
example for the usage of '*Err' in "lib/app.l":

   # Exit on error
   (de *Err
      ~(as trail
         (for (L (trail T)  L)
            (if (pair (car L))
               (println (pop 'L))
               (space 3)
               (println (pop 'L) (pop 'L)) ) )
         (println '=======) )
      (prinl *Pid " ! " (stamp) " [" *Adr " " (host *Adr) "] " *Agent)
      (show This)
      (for "X" '(*Gate *Agent *Host *Port *PRG *Url *SesId *ConId *Tab *Gui 
*Btn *Get *ID)
         (println "X" (val "X")) )
      (for "X" (env)
         (unless (== (car "X") (cdr "X"))
            (println (car "X") (cdr "X")) ) )
      (rollback) )

This is in almost all my production code. It results in writing various
things to the log file, and then exits (see above).

> and noticed that the official way to set it is (de *Err (bye))

But this has not to be the case. Also sense makes to write

   (push '*Err '(doThis))

and then perhaps in some other place

   (push '*Err '(doThat))

This happens with several other globals in the system, like *Bye, *Fork,
*Run, *JS etc.

> I would have find this clearer: (setq *Err '((bye)))

Yes, that's also fine. I prefer 'de' because it gives a warning if
'*Err' already has a value.

> To me, the use of 'de here is convoluted. I eventually realised how
> it may work. My guess is that since (de a (x)) defines a function

No. 'de' is not exclusively for function definitions. Everything is just
a value, it depends on runtime later whether this value is meant to be a
function, a 'prg' body, or arbitrary data.

> I'd understand that these suggestions would not make their
> way to the official docs, but I know for sure that the prompt
> at the end of the example here is a ? and not a $:
> http://www.software-lab.de/doc/refE.html#*Err

Right! Thanks for the hint! The return value of 'de' is also wrong. It
is not the body, but the symbol '*Err'. I have fixed that.

♪♫ Alex
UNSUBSCRIBE: mailto:picolisp@software-lab.de?subject=Unsubscribe

Reply via email to