Re: Undefined in LISP

Liste des GroupesRevenir à cl lisp 
Sujet : Re: Undefined in LISP
De : k.j.w (at) *nospam* rfc1924mail.nop (Kevin J Witczak)
Groupes : comp.lang.lisp
Date : 22. Apr 2025, 03:48:59
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <87y0vsoqqs.fsf@rfc1924mail.nop>
References : 1 2 3 4 5
User-Agent : Gnus/5.13 (Gnus v5.13)
Daniel Cerqueira <dan.list@lispclub.com> writes:

Lawrence D'Oliveiro <ldo@nz.invalid> writes:
>
On Sat, 22 Mar 2025 12:07:14 +0000, Daniel Cerqueira wrote:
>
Lawrence D'Oliveiro <ldo@nz.invalid> writes:
 
On Fri, 21 Mar 2025 22:47:38 +0000, Daniel Cerqueira wrote:
>
I would like to know your thoughts, about what being undefined
actually is. Should an undefined expression be represented by a
symbol, or should an undefined expression be silent (without
returning a symbol)?
Should an attempt to evaluate such an expression even terminate?
 My opinion is that it should...
So undefined behaviour cannot be really undefined, it must return some
kind of value we are going to arbitrarily name as “undefined”?
>
Does every LISP S-expression need to have a value (need to be
evaluated)?  Is atributing a symbol to undefined behaviour needed?

In the context of the LISP 1.5 Programmer's Manual, "undefined" seems to
simply mean "has no value with respect to the semantics of the language
defined in the LISP 1.5 Programmer's Manual". As Kaz pointed out,
"undefined" occurs infrequently in the manual, but many of its usages
are strictly prescriptive or proscriptive: they state when function
calls and symbols are specified to have a return value or not, and many
of those usages appear in the language specification in Section I.

Things like `startread' which requires CURCHAR and CHARCOUNT to be
undefined under various conditions. `eq' yields always either *T* or
NIL, and must never be undefined, even if its arguments are bad. `cond'
must have an undefined value if no branch's predicate evaluates to *T*.

In Section I, 1.6, we get:

|1. In the pure theory of LISP.  all functions other than the five basic
|ones  need to  be  defined each  time  they  are to  be  used. This  is
|unworkable in  a practical  sense.  The LISP  programming system  has a
|larger  stock  of built-in  functions  known  to the  interpreter,  and
|provision for adding as many more as the programmer cares to define.

|2. The  basic functions. and cdr  were said to be  undefined for atomic
|arguments.  In  the system, they always  have a value, although  it may
|not always be meaningful.  Similarly, the basic predicate eq always has
|a  value. The  effects  of these  functions in  unusual  cases will  be
|understood  after  reading  the  chapter  on  list  structures  in  the
|computer.

Taken together with the above, what the relevant Section VII has to
indicate is that LISP expressions are semantically disjoint from the
computed internal structures the LISP programming system uses, and
that's the source of the ambiguity. LISP, the language, is not the same
as its machine implementation. LISP has some cases where its relevant
functions semantically mean nothing, in the same way that mathematical
functions can be locally undefined within their domain, like a function
f(x) := 1/x, for x = 0. `eq', in LISP 1.5, has the domain of atoms, and
so is undefined for non-atomic arguments, but is later explicitly
confirmed to actually just be one of *T* or NIL no matter if it is
passed bad arguments per se, presumably because this smooths over a
common source of programs halting and catching fire.

What this all means of course is that undefined basically stands in for
"implementation dependent". When the language formally has nothing to
say, the machine just keeps going. Programming languages don't extend
"all the way down". LISP (or Lisp (or Scheme (&c.))) the language is
made up partly of function definitions: like `car' and `cdr', whose
semantics define them for the domain of non-atomic arguments, but we're
explicitly told by the 1.5 PM that in the actual implementation they
always have a return value (even if it's not a value that means anything
where you'd be calling them), presumably also out of brute practicality.

Worth noting in the 1.5 PM is the "UNDEFINED SYMBOL" error emitted by
LAP that Kaz also pointed out. This error, we're told on page 75,
specifically indicates "assembly incomplete".  LISP, the programming
language, has no formal notion of assembly (or machine instructions) -
it's just a system for recursive function computation via a List
processing mechanism. But an actually machine-computable LISP must sit
upon such an implementation level. Alongside "UNDEFINED SYMBOL" we also
see LAP errors like "OUT OF BINARY PROGRAM SPACE". LISP also doesn't
have a semantics for memory; garbage collection is how we deal with the
emergence of this practicality on real hardware. "Undefined" funcall
values mean as much as return values on a call that blows up its stack.

LISP 1.5 is very old, there's sections in here about how the Overlord
manages tape ingestion. These are kept out of the language spec section
for good reason: they're implementational, and disjoint from the
language semantics too. We are responsible for ensuring Lisp code does
the right thing when exceptions occur, even when the language itself
specifically doesn't. More contemporary versions of Lisp have grown
condition handling systems specifically for this - to provide a place
within the language semantics to enable users to discretionally handle
various conditions, for when such behaviour properly resides within the
program's domain.

I'd say it's probably fruitless to try too hard to shoehorn "undefined"
into the semantics of the language, asking questions like when and where
it would be correct for Lisp to have a representation for states of
affairs which violate its semantics. Lisp also doesn't try to shoehorn
in a semantics of memory management (no malloc et al.) either. We just
want garbage collection so our code doesn't hang up and go out to lunch
when the unexpected happens.

Languages may introduce things like the Bottom type ⊥ because they
perform non-optional, non-trivial Type and Kind analysis as part of the
implementation of their type system. Rust does have a semantics of
memory management because one of its key design goals was to be like C
but not in the bad ways. Maybe Lisp, in the large sense, should or could
have use for these things (turnstile in Typed Racket comes to mind: a
metalanguage for Scheme-based type system computation at macroexpansion
time). But LISP, as specified by McCarthy et al. in the early days,
doesn't incorporate such things. Implementation dependent behaviour was
what you got.

--
;; Basically just a Boltzmann brain with extra steps.
;; -*- (rfc1924 "YiVsRYGrgTcVTuwaB^>SZ*Fa2X>2ZIXa") -*-

Date Sujet#  Auteur
21 Mar 25 * Undefined in LISP22Daniel Cerqueira
22 Mar 25 +- Re: Undefined in LISP1Jeff Barnett
22 Mar 25 +- Re: Undefined in LISP1Alan Bawden
22 Mar 25 +- Re: Undefined in LISP1Kaz Kylheku
22 Mar 25 +* Re: Undefined in LISP15Lawrence D'Oliveiro
22 Mar 25 i`* Re: Undefined in LISP14Daniel Cerqueira
22 Mar 25 i `* Re: Undefined in LISP13Lawrence D'Oliveiro
23 Mar 25 i  `* Re: Undefined in LISP12Daniel Cerqueira
23 Mar 25 i   +- Re: Undefined in LISP1Jeff Barnett
24 Mar 25 i   +* Re: Undefined in LISP9Lawrence D'Oliveiro
24 Mar 25 i   i+* Re: Undefined in LISP3Kaz Kylheku
24 Mar 25 i   ii+- Re: Undefined in LISP1Paul Rubin
24 Mar 25 i   ii`- txr [was Re: Undefined in LISP1Madhu
24 Mar 25 i   i`* Re: Undefined in LISP5Daniel Cerqueira
24 Mar 25 i   i `* Re: Undefined in LISP4Lawrence D'Oliveiro
27 Mar 25 i   i  `* Re: Undefined in LISP3Robert Girault
29 Mar 25 i   i   `* Re: Undefined in LISP2Daniel Cerqueira
29 Mar 25 i   i    `- Re: Undefined in LISP1Lawrence D'Oliveiro
22 Apr 25 i   `- Re: Undefined in LISP1Kevin J Witczak
22 Mar 25 `* Re: Undefined in LISP3Paul Rubin
23 Mar 25  `* Re: Undefined in LISP2Stefan Ram
24 Mar 25   `- Re: Undefined in LISP1Lawrence D'Oliveiro

Haut de la page

Les messages affichés proviennent d'usenet.

NewsPortal