From: vy
Subject: Opposite of ~^ FORMAT Directive
Date: 
Message-ID: <1177802827.659216.43020@l77g2000hsb.googlegroups.com>
Hi,

Is it possible to make FORMAT print a phrase just in the first element
of a ~{...~} list iteration. (Like opposite of ~^.)


Regards.

From: Kent M Pitman
Subject: Re: Opposite of ~^ FORMAT Directive
Date: 
Message-ID: <ufy6j6c49.fsf@nhplace.com>
vy <·············@gmail.com> writes:

> Is it possible to make FORMAT print a phrase just in the first element
> of a ~{...~} list iteration. (Like opposite of ~^.)

I think the reason there's not is that often one just reorganizes the
text slightly, pushing the first part out of the loop to the left. e.g.,

(defun foo (x) (format t "First ~{~A~^, then ~}." x))
=> FOO

(foo '(a b c d))
First A, then B, then C, then D.
=> NIL

If the case of (foo '()) is something you worry about, then use:

(defun foo (x) (format t "~:[None~;~:*First ~{~A~^, then ~}~]." x))
=> FOO

(foo '())
None.
=> NIL

If you insist on pushing things into the loop, about the only trick that
comes to mind, and it's really an ugly trick--but worth knowing, is to
use some sort of circular list thing, as in:

(defun circular-list (&rest args)
  (let ((x (copy-list args))) 
    (nconc x x)))
=> CIRCULAR-LIST

(setq *print-circle* t)
=> T

; test it out
(circular-list 'a 'b 'c)
=> #1=(A B C . #1#)

(defun foo (x)
  (format t "~:{~:[First~:;then~] ~A~:^, ~}." 
    (mapcar #'list ;this mapcar will stop as long as x is not circular!
            (cons nil (circular-list t))
            x)))
=> FOO

(foo  '(a b c d))
First A, then B, then C, then D.
=> NIL

Then again, I don't use every last feature of FORMAT, so maybe someone else
remembers another feature I'm forgetting.

But you know, you're not really _required_ to put everything in one FORMAT
string.  It is ok to use conventional loops, multiple calls to FORMAT, etc.
Sometimes, it's a lot more readable that way, too.
From: vy
Subject: Re: Opposite of ~^ FORMAT Directive
Date: 
Message-ID: <1177845567.117643.320860@u30g2000hsc.googlegroups.com>
Hi,

On Apr 29, 7:25 am, Kent M Pitman <······@nhplace.com> wrote:
> vy <·············@gmail.com> writes:
> > Is it possible to make FORMAT print a phrase just in the first element
> > of a ~{...~} list iteration. (Like opposite of ~^.)
> ...
> If the case of (foo '()) is something you worry about, then use:
>
> (defun foo (x) (format t "~:[None~;~:*First ~{~A~^, then ~}~]." x))
> => FOO
>
> (foo '())
> None.
> => NIL

Yep, this is what I was looking for. Thanks so much for your detailed
answer.


Regards.
From: Joerg Hoehle
Subject: Re: Opposite of ~^ FORMAT Directive
Date: 
Message-ID: <ufy6h3lyz.fsf@users.sourceforge.net>
Kent,

Kent M Pitman <······@nhplace.com> writes:
> comes to mind, and it's really an ugly trick--but worth knowing, is to
> use some sort of circular list thing, as in:
>     (mapcar #'list ;this mapcar will stop as long as x is not circular!
>             (cons nil (circular-list t))
>             x)))

Some people these recent years are extremely pedantic about strict
interpretation of the ANSI-CL (or rather the CLHS), possibly putting
more into its wording than the authors intended to.

One can derive from the entry on MAPCAR:
  MAPCAR function &rest lists => result list
  Exceptional situations:
  Should be prepared to signal an error of type type-error if any list
  is not a proper list.
that your code suggestion is not portable code.

However I've come across plenty of (historic?) Lisp code which depends
on this circular list trick wo work with MAPCAR (and other sequence or
list functions).  Probably no implementation will choose to signal an
error at the risk of seeing some software library fail (or plainly
because they won't perform an extra check for circular lists) -- or
now that I've pointed at it, they'll change the Lisp implementation
because historic code could be crap ;)

Yet it other areas, these same implementations appear
"plus royaliste que le roi".

E.g. (LENGTH '(2 3 . 4)) signals an error in many implementations,
whereas the MAPCAR trick works.  I would have been happy with LENGTH
counting the number of conses reachable from CDR, e.g. 2.

Do you think CL need a CIRCULAR-LIST-ARGUMENTS writeup similar to
DOTTED-LIST-ARGUMENTS?
http://www.lispworks.com/documentation/HyperSpec/Issues/iss138.htm

Regards,
	Jorg Hohle
Telekom/T-Systems Technology Center
From: Kent M Pitman
Subject: Re: Opposite of ~^ FORMAT Directive
Date: 
Message-ID: <u8xc9ls8q.fsf@nhplace.com>
Joerg Hoehle <······@users.sourceforge.net> writes:

> Kent,
> 
> Kent M Pitman <······@nhplace.com> writes:
> > comes to mind, and it's really an ugly trick--but worth knowing, is to
> > use some sort of circular list thing, as in:
> >     (mapcar #'list ;this mapcar will stop as long as x is not circular!
> >             (cons nil (circular-list t))
> >             x)))
> 
> Some people these recent years are extremely pedantic about strict
> interpretation of the ANSI-CL (or rather the CLHS), 

If you discover material discrepancies, pass them along.  We don't fix 
CLHS bugs on a day-to-day basis but we buffer them and try to fix them
periodically.  It is derived from the same TeX sources as ANSI CL used,
and (modulo errors in the TeX converter program I wrote, and a bit of
presentational creativity due to the rendering as HTML), it's supposed
to be pretty much the same.

> possibly putting
> more into its wording than the authors intended to.

Well, author intent is supposed to not be an issue at this point.  No
one can inspect and challenge author intent, certainly not in a way
that is subject to the same fairness/concensus requirements that the
creation process was.  When the process closed, all we were left with
was the words, and one person's interpretation is as good as mine.  

Rather than defend the text as obviously meaning what I said, since it
might have been meant to support my reading or it might not, it really
doesn't matter, it's easier from a debate point of view to just grant
an immediate win to anyone who claims the analysis you've laid out is
obviously correct and then to proceed to explain why this doesn't matter
to me.

All implementations deviate from the standard in minor regards, but I
take their statement of conformance to mean "they are prepared to
receive bug reports".  Not all vendors fix bug reports, but they bet
their entire credibility on the notion that their users will accept
their ruling on the aggregated credibility of their set of choices on
edge cases.  It affects their reputation and their business.

I think it behooves all of us to give implementations a fair amount of
freedom in small areas like this where there is no well-defined behavior
and they want to add an extension.  If someone is impeded in their work
by failure to detect something they need detected, I think most vendors
would work to create some form of custom control of the feature.  But 
absent a large shock to the community by putting the entire standard up 
for grabs (ANSI has no way to re-open a small set of issues, it can only
re-open the entire standard), this is what's needed for things to work.

So implementations play games with details of streams that push the edges
of the spec's requirements, and I think it's for the good.  They push the
edges of memory management as it relates to multi-tasking.  Some operations
have to be specially constrained in ways you could argue are in violation
of the spec in a multi-tasking environment, for example; but is anyone
rationally arguing they shouldn't?  The real questino is, do people shun
these implementations for those deviations or applaud their creativity.

Back to the case at hand, we wanted to say that mapcar shouldn't run
out of control if there was a circularity.  So indeed, I should be
prepared to have MAPCAR fail.  In porting, I'd want to test whether
MAPCAR in a given implementation did what the spec said, and I'd
respect an implementation for being pedantic.  But as a pragmatic
buyer, I'm prepared to respect them for deviating slightly, too.  I've
got better things to do than spend my time whining at them for this.

Labeling, to me, is everything.  What I _do_ like is for an implementation
to tell me a list of deviations.  But I don't mean that has to constrain
them to do a certain thing.  ANSI CL isn't patented, and we aren't controlling
use of the information in it.

I'd make the analogy to "no smoking" in restaurants.  I hate smoke.
But I have no problem with a restaurant having smoking... except if it
tries to pass itself off as having a "no smoking" area when I have to
either walk through smoke to get there or I can get smoke wafting at
me when I sit there.  My problem is not that people somewhere are
smoking.  My problem is that labeling is bad.  If someone wants to
just have a sign saying "We just smoke a lot here; enter at your own
risk", that's fine.  If someone wants a sign saying "We have a feeble
no smoking area that only sort of works" that's fine.  But what I want
to do is know at the time I enter what I'm getting into, before I have
invested time, before I have ordered things I owe moeny for, that this
is what I'm doing.

Same with the FDA, btw.  I think it's foolhardy for them to tell people
what drugs they can and cannot have, except maybe where those drugs, if
taken, pose a risk to others around the taker.  Largely, though, I think
all the FDA should be doing is labeling things "we tested this and it
works", "we're testing this and you can read the partial results here",
"we haven't tested this, who knows what it will do".  And then society 
should learn to read labels.

So as long as an implementation labels itself correctly, I'm all for it.

And the other way around, if I have code that needs an non-portable
feature, I like to note that.  I had forgotten we made this
requirement on the language, mostly just to stop out-of-control
programs, not to mean we hated circularity.  But given that we did
make this requirement, I think I should have said in my post that it
was a non-standard feature.  I still would have offered the trick,
because it is both pragmatically useful and intellectually
thought-provoking, but that was my bug in not labeling it.

If I had it to do again, I probably would have thought harder and
maybe suggested we say "should be prepared to signal an error of type
type-error if all the lists are circular."  and reduce the "any list"
issue to just if they are "dotted".  But I guess we didn't do that.
(Generally, I didn't choose technical content, btw; I just acted as
neutral scribe in writing down what we voted as a group.  Separately,
with another hat on, I advocated positions that were voted on, but I
had only one vote.  So I couldn't have just made a change of this kind
on my own initiative.)

> One can derive from the entry on MAPCAR:
>   MAPCAR function &rest lists => result list
>   Exceptional situations:
>   Should be prepared to signal an error of type type-error if any list
>   is not a proper list.
> that your code suggestion is not portable code.
> 
> However I've come across plenty of (historic?) Lisp code which depends
> on this circular list trick wo work with MAPCAR (and other sequence or
> list functions).  Probably no implementation will choose to signal an
> error at the risk of seeing some software library fail (or plainly
> because they won't perform an extra check for circular lists) -- or
> now that I've pointed at it, they'll change the Lisp implementation
> because historic code could be crap ;)

I think this is a good analysis.  Plus, I think the right
implementation will catch the case of runaway code.  Checking all
lists for circularity rather than just one would catch what anyone
cares about... 

Hmm.  The more I think of it, though, the more I think there's
probably even wiggle room for this to even be conforming, since the
algorithms for circular list detection don't spell out when are done
(before the mapping or interleaved) nor when the circularity is
detected.  (In the interleaved case, you can sometimes go an extra
time around the cycle before detection, and that can be long enough to
allow some implementations to successfully map over a circular list.
The whole notion of "should be prepared" is to not slow things down,
so I think one CANNOT argue that the test MUST be done before the
iterations begin... and then, short of auditing the code, I think it's
impossible to prove the implementation is not trying to conform unless
the mapcar simply never returns (which is, incidentally, also hard to
prove).  So maybe my remarks about "non coformance" don't even apply
here, and maybe there's a happy middle.  Even so, I'll leave this post
as written (I'm writing linearly) because my above remarks still apply
in other cases.

> Yet it other areas, these same implementations appear
> "plus royaliste que le roi".
> 
> E.g. (LENGTH '(2 3 . 4)) signals an error in many implementations,
> whereas the MAPCAR trick works.  I would have been happy with LENGTH
> counting the number of conses reachable from CDR, e.g. 2.
> 
> Do you think CL need a CIRCULAR-LIST-ARGUMENTS writeup similar to
> DOTTED-LIST-ARGUMENTS?
> http://www.lispworks.com/documentation/HyperSpec/Issues/iss138.htm

Well, those writeups were an artifact of the process. Write all you want
but it cannot change the language.

I regard a change to the language as I regard a second constitutional 
convention for the US.  It sounds good when you first hear it.  But when
you realize what it could turn into (worst case: a bunch of opportunists
trying to shanghai the thing to make it utterly different than what needed
fixing and convinced people to have it in the first place), you realize
that the stability of clumsy incremental change isn't so terrible.

If someone wanted to make a new language, they could always do so.  There
are many languages out there and new ones made all the time.  I see no
reason for ANSI CL to be destabilized, other than to capitalize on its
name and fame inappropriately...  

I'll risk one more political analogy: Look at what has recently
happened to the Republican party, a supposed party of fiscal
conservatism and of small, non-invasive goverment.  Why do you suppose
no one went and made a new "we like big government and lots of spying"
party?  Well, probably because "being Republican" sounded better, and
there were lots of members you could claim as your own.  I won't even
say that kind of thing doesn't work--it seems to have served the
Republicans well in the short term, though I have a feeling it will
ultimately be their undoing.  But for now, a lot of people seem to
call themselves loyal Republicans even when every last aspect of what
the Republicans used to stand for has been undermined.

Maybe that would work for ANSI CL, too.  Maybe we could turn it into 
something else and have a ready-made base of advocates.  But I doubt it.
Or I doubt it would long stand.

It is for this reason that I don't suggest writing writeups.  I think
learning from those writeups and writing a whole new language that is
coherent from the start is occasionally useful, and is an honorable
endeavor whether or not useful.

But a great many good things in the world are hard to define neatly,
and a great many bad things in the world come from the attempt to
define something overly neatly.  So I like to invest a bit of time in
understanding why CL can be and is useful in spite of its apparent
warts... and why other languages without those warts seem less useful.

I've contrasted Lisp and Scheme occasionally, for example, by noting
that Scheme is highly conservative in what they will admit to their
language.  They proceed by first understanding something, then adding
it to the language.  This assures the language is full of sound ideas.
This is a well-tested idea--some religions and governments use it all
the time, though they don't say it in so many words.  Rather than
freedom of choice, they tell you a particular set of rules they think
has worked for someone, and they tell you everyone should use that set
of rules because it's well studied and has known consequences.  But
Lisp, by contrast, establishes messy ideals that are hard to live up
to... a lot of the design, like the design of liberty and freedom,
comes not from the initial set of rules, but from the endeavor to
understand how those rules play out, and the construction of constructs
more akin to case law... our implementations often are like the federal
courts, sometimes respecting precedent in other jurisdictions, sometimes
not.  This gives users lots of choice and keeps things healthy.

You might think there should be a supreme court that smooths things over,
but the supreme court in this context would eliminate market choice, and
I think would not be good.  The US Supreme Court is continuously in a
battle on this very issue--trying to decide which issues must apply to
all states, and which issues must be allowed to vary by states so that
people have state-to-state choice.  It's not an easy issue, and since it's
not something where the outcome is well understood, I'm glad we're not
adopting it as an obvious answer.

I don't know if this answer helped, but I found it a very intriguing 
question and I thank you for raising it.  I'll be curious to hear others'
points of view on these issues.
From: Richard M Kreuter
Subject: Re: Opposite of ~^ FORMAT Directive
Date: 
Message-ID: <87d51nbxbp.fsf@tan-ru.localdomain>
vy <·············@gmail.com> writes:

> Hi,
>
> Is it possible to make FORMAT print a phrase just in the first element
> of a ~{...~} list iteration. (Like opposite of ~^.)

Assuming I'm parsing your question right,

CL-USER> (format t "~1{~A~}" '(foo bar baz))
-| FOO
=> NIL