Re: multiple read-time conditionals, puzzlement

phoebe Goldman <[email protected]> Mon, 13 Mar 2023 17:30:49 -0400
Newsgroups gmane.lisp.openmcl.devel
Message-ID <[email protected]>
2.4.8.17 Sharpsign Plus, http://www.lispworks.com/documentation/HyperSpec/Body/02_dhq.htm , says:

> #+ operates by first reading the feature expression and then skipping over the form if the feature expression fails. While reading the test, the current package is the KEYWORD package. Skipping over the form is accomplished by binding *read-suppress* to true and then calling read.


This means that a series of #+ or #- read-conditionals will result in recursive calls to READ with a stack of T bindings on *READ-SUPPRESS*. Note that neither reader macro ever binds *READ-SUPPRESS* to NIL, only either introduces a binding of T or uses the existing value.

Assume that *READ-SUPPRESS* is globally NIL. Consider reading:

#+foo #+foo a b

If :FOO is in *FEATURES*, the reader will:

1. Read the first #+FOO, evaluate its feature expression to true, and call READ recursively with no new *READ-SUPPRESS* binding.
  2. Read the second #+FOO, evaluate its feature expression to true, and call READ recursively with no new *READ-SUPPRESS* binding.
    3. Read A with the root *READ-SUPPRESS* binding of NIL, and return the symbol A.
4. Your initial call to READ has now returned, but there's more input. Call READ again to get another object.
5. Read B the root *READ-SUPPRESS* binding of NIL, and return the symbol B.

If :FOO is not in *FEATURES*, the reader will:

1. Read the first #+FOO, evaluate its feature expression to false, and call READ recursively with *READ-SUPPRESS* bound to T.
  2. Within that binding, read the second #+FOO, evaluate its feature expression to true, and call READ recursively with an additional layer of *READ-SUPPRESS* = T binding.
    3. Within both bindings, read A with *READ-SUPPRESS* true, and return nothing.
  4. Within the outer binding, read A with *READ-SUPPRESS* true, and return nothing.
5. Your initial call to READ has now returned, and you didn't get anything.

When you're dealing with multiple distinct feature expressions which are not uniformly all true or false, the behavior gets more complicated, but it's always defined by the spec as recursive calls to READ with a stack of *READ-SUPPRESS* bindings. I haven't looked carefully at the cases that spawned this discussion to see if CCL's behavior is compliant, but I don't believe there's any ambiguity in the spec.

Cheers,
phoebe

> On Mar 13, 2023, at 5:06 PM, Tim McNerney <[email protected]> wrote:
> 
> Would someone mind quoting “chapter and verse”?
> 
> Somehow, even those of us with decades of Common Lisp experience, all trying to follow the drama of the X3J13 committee, a bunch of us “missed the memo” about this convenient, allegedly legal, but “buyer beware” syntax.
> 
> Yes, I absolutely hate
>      #+foo :keyword #+foo argument too.
> 
> --Tim
> 
>> On Mar 13, 2023, at 14:00, Robert Goldman <[email protected]> wrote:
>> 
>>  On 13 Mar 2023, at 12:42, Ron Garret wrote:
>> Oh, forgot to add...
>> On Mar 13, 2023, at 10:20 AM, Arthur Cater <[email protected]> wrote:
>> It never previously occurred to me that read time conditionals could be nested.
>> Just because you can do something doesn't mean you should.
>> rg
>> I was surprised myself to see
>> #+foo #+foo
>> 
>> used to make two s-expressions (in)visible in the presence (absence) of the :foo feature. But it's clearly dictated by the spec, and is often handy when, for example one might want to have something conditionally in a property list
>> (list :prop1 12
>> #+foo #+foo
>> :foo 'bar)
>> 
>> In my opinion, that's clearer than
>> (list :prop1 12
>> #+foo :foo #+foo 'bar)
>> 
>> which obscures reading this as a property list and obscures the fact that the two elements of the list are going to be swapped in or out based on a single feature.
>> (append (list :prop 12) #+foo (list :foo 'bar) )
>> 
>> is not an alternative particularly pleasing to me, but YMMV. It's certainly very busy.
signature.asc (application/pgp-signature, 833 B)
-----BEGIN PGP SIGNATURE-----

iQIzBAEBCAAdFiEEP9mPiwXGYysiV7A93lWlZ3CUZK4FAmQPlgkACgkQ3lWlZ3CU
ZK7Hiw/8Dw0oNq/MAOf5wHKal0+Q2o42nQMTUKmjM956tmgJlt1AhOgiQCGFmmNL
naAUePHQMzUpEZ8gl4UMFUNnJNdP8+Z5R1+3uTYZ79lhvlUHLGxMAPD1a/HlT413
26M4IerH7vRxB0WBHBBfF8ldCnSS1y5N8adq8yY47m8NusKQgg/5wiWDNlWv37v/
AB2NsrQGO5xyJ0vzQRRTWDaB5itxo4EnItc9fgdAxtc59U7lsjCya1XKwhwtiwZJ
mdMSc6Rf0CHI1gZ4gdqGj8nEFlCCtTIHVMeJLvbbANXFdkC9fzH9RFMToENUcuFV
OxLyIj5P6+xpR6z/6UqOVAsYSkqFhbHCGsFVwytgvBWAQMuWjst/9c+XNWDtWqaz
pX/uIpJMFW8xamNB/HEoT5J96FtF0yPI38RUVNbtBKNdz8O3mUe90bbBrZoOroVV
2L8rHnuME4Eg2a4e3c1nGFIDrxsjvkRnLBqsrUsDGehR9OUwbmLsoutA/a0xKELI
l3x9tOL3DZDFu+8ZdKYs/ZJIHpJrF2lDkvXL5Mehirzg23mGQXMLuprcKPZM67z3
c/ffCGHtsEUZ0qCc+fOOKWxUJjESfmJFBsrulLhXb9KQNw1RCVa8Ndiu1zuLVHYH
HWhOc/89tRAi4SHsn+m97RuwvxLdPMVstR9jnsOmsgTalCzC/rQ=
=TSpb
-----END PGP SIGNATURE-----