<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">2.4.8.17 Sharpsign Plus, <a href="http://www.lispworks.com/documentation/HyperSpec/Body/02_dhq.htm">http://www.lispworks.com/documentation/HyperSpec/Body/02_dhq.htm</a> , says:<div><br></div><div><blockquote type="cite">#+ 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.</blockquote></div><div><br></div><div>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.</div><div><br></div><div>Assume that *READ-SUPPRESS* is globally NIL. Consider reading:</div><div><br></div><div>#+foo #+foo a b</div><div><br></div><div>If :FOO is in *FEATURES*, the reader will:</div><div><br></div><div>1. Read the first #+FOO, evaluate its feature expression to true, and call READ recursively with no new *READ-SUPPRESS* binding.</div><div>  2. Read the second #+FOO, evaluate its feature expression to true, and call READ recursively with no new *READ-SUPPRESS* binding.</div><div>    3. Read A with the root *READ-SUPPRESS* binding of NIL, and return the symbol A.</div><div>4. Your initial call to READ has now returned, but there's more input. Call READ again to get another object.</div><div>5. Read B the root *READ-SUPPRESS* binding of NIL, and return the symbol B.</div><div><br></div><div>If :FOO is not in *FEATURES*, the reader will:</div><div><br></div><div>1. Read the first #+FOO, evaluate its feature expression to false, and call READ recursively with *READ-SUPPRESS* bound to T.</div><div>  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.</div><div>    3. Within both bindings, read A with *READ-SUPPRESS* true, and return nothing.</div><div>  4. Within the outer binding, read A with *READ-SUPPRESS* true, and return nothing.</div><div>5. Your initial call to READ has now returned, and you didn't get anything.</div><div><br></div><div>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.</div><div><br></div><div>Cheers,</div><div>phoebe</div><div><span id="x-apple-selection:end"></span><span><br><blockquote type="cite">On Mar 13, 2023, at 5:06 PM, Tim McNerney <mc@media.mit.edu> wrote:<br><br class="Apple-interchange-newline">Would someone mind quoting “chapter and verse”? <br><br>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. <br><br>Yes, I absolutely hate <br>     #+foo :keyword #+foo argument too. <br><br>--Tim<br><br><blockquote type="cite">On Mar 13, 2023, at 14:00, Robert Goldman <rpgoldman@sift.info> wrote:<br><br></blockquote><blockquote type="cite">




On 13 Mar 2023, at 12:42, Ron Garret wrote:<br>
Oh, forgot to add...<br>
On Mar 13, 2023, at 10:20 AM, Arthur Cater <arthur.cater@ucd.ie> wrote:<br>It never previously occurred to me that read time conditionals could be nested.<br>
Just because you can do something doesn't mean you should.<br>rg<br>

I was surprised myself to see<br>
#+foo #+foo<br><br>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<br>
(list :prop1 12<br>      #+foo #+foo<br>      :foo 'bar)<br><br>In my opinion, that's clearer than<br>
(list :prop1 12<br>      #+foo :foo #+foo 'bar)<br><br>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.<br>
(append (list :prop 12) #+foo (list :foo 'bar) )<br><br>is not an alternative particularly pleasing to me, but YMMV.  It's certainly very busy.<br>






</blockquote></blockquote></span><br><div></div></div></body></html>