> I'm not here "railing" against the Common Lisp package system. I > think it's clearly the right thing in a language with "heavy" > symbols--symbols that have plists and all that.
Or in a language with multiple programs that do symbolic processing on the same data and want to keep their own "markers" in the data.
> Now you argue that this has made the macro system in Scheme "very > complex", but I think that's looking at the wrong side of the > problem. Scheme macros, from the user's perspective, are as simple as > can be: they reliably Just Work.
Unless you want to do something where they Just Won't. And all this syntactic bloat being forced for a little theoretical "perfection". Not a language for me, for sure.
-- -> -/ - Rahul Jain - \- <- -> -\ http://linux.rice.edu/~rahul -=- mailto:rj...@techie.com /- <- -> -/ "Structure is nothing if it is all you got. Skeletons spook \- <- -> -\ people if [they] try to walk around on their own. I really /- <- -> -/ wonder why XML does not." -- Erik Naggum, comp.lang.lisp \- <- |--|--------|--------------|----|-------------|------|---------|-----|-| (c)1996-2002, All rights reserved. Disclaimer available upon request.
> > In article <87u1rixmm7....@photino.sid.rice.edu>, > > Rahul Jain <rj...@sid-1129.sid.rice.edu> wrote: > > > Bruce Hoult <br...@hoult.org> writes: > > > > In article <87vgbyz9jo....@photino.sid.rice.edu>, > > > > Rahul Jain <rj...@sid-1129.sid.rice.edu> wrote: > > > > > I think that if scheme is a lisp, then it would be a very strange > > > > > concept to call ML not a lisp.
> > > > Scheme and ML fail my "Can you easily transliterate textbook programs > > > > from one language into the other language?" test.
> > > So the syntax is what matters? Java is a C, then?
> > No, syntax does not matter. For example, Common Lisp and Dylan can > > usually be easily transliterated into each other, but the syntax is > > quite different.
> It all depends on what's "usual".
Of course. Unfortunately it's always going to be subjective.
> > > And what textbook are you talking about? I can't believe that there > > > are textbooks which don't use call/cc
> > As someone just pointed out, SICP doesn't mention call/cc. I hadn't > > realised that, but SICP is pretty much the clasic > > textbook-that-uses-scheme.
> So we should use a book that uses a language to teach general concepts > as the standard textbook for that language? I don't get the point of > this "textbook program" idea.
The idea is *precisely* that the book should have programs that do some general, useful, thing rather than programs intended to illustrate obscure and seldom-used corners of the language.
> > > > ML examples make frequent use of implicit currying.
> > > That's syntactic sugar, really.
> > True, and you can emulate it in Scheme using lambdas and/or an explicit > > "curry", but it's used heavily enough in ML to cause a lot of code > > expansion when translated to Scheme.
> Same with porting code that uses CLOS or conditions to Scheme.
I agree. CL and Scheme are probably the two Lisps with the greatest distance between them. CL code using CLOS and conditions is easy to port to Dylan.
> Or code that uses call/cc to Lisp.
^^^^^ Common Lisp
I already covered that. Most Scheme programs don't use call/cc heavily.
> > Perhaps a better example (which I mentioned yesterday but forgot today) > > is the heavy use of pattern matching in ML.
> That can be done without too much trouble with COND. As much trouble > as any other differences between the languages.
"Too much trouble" is subjective. I'd say it's too much trouble to just use cond. If you had a destructuring-cond then it might not be.
> > > > > > I'm a bit unclear about the "notation for functions in terms of > > > > > > conses" requirement, also. > > > > > [...] > > > > I don't see why that is important for languages that don't have "eval" > > > > or procedural macros, such as ML, Dylan, and (believe it or not) Scheme > > > > until recently. > > > Yes, exactly. :)
> > Well, if you think that "eval" is essential then list *it*, not the > > incidental "notation for functions in terms of conses".
> Perl has eval, too.
My point exactly. More than one c.l.ler has pointed out how close Perl 5 is getting to being a Lisp.
In article <3225183094172...@naggum.net>, Erik Naggum <e...@naggum.net> wrote:
> * Rahul Jain <rj...@sid-1129.sid.rice.edu> > | Hmm, yes. But it would have made more sense for them to make clear > | that they were on a trajectory away from Lisp.
> Precisely, positions can be close to eachother, but the direction of the > momentum or the heading to the destination may be quite different. What > is so annoying with "Scheme is a (dialect of) Lisp" when published > recently (as opposed to when it was written) is that they imply that Lisp > has moved in the same direction Scheme has, and that is patently _false_.
Lisp can't move in a direction. It just is. Platonic. Pure. Common Lisp can move in a direction.
> I cannot in Scheme construct the notion of passing > '(kent:person-1 rahul:person-1)
> Or if I do, then KENT:PERSON-1 is a symbol with a 13-letter name and the > functions that do the accessing have to first decode it to find a hidden > symbol PERSON-1 within it and also a function or table that corresponds > to Kent's NAME operation/resource.
I think you're making too much of this.
You can always pass something like this: (list kent 'person-1 rahul 'person-1) where kent and rahul are hash tables, assoc lists, closures or something.
Or you could define some global lookup table for 'kent and 'rahul, and just pass '((kent person-1) (rahul person-1)). I don't see any major design flaw here.
Do you really think packages and property lists are prereqs for a symbolic processing language?
-- <brlewis@[(if (brl-related? message) ; Bruce R. Lewis "users.sourceforge.net" ; http://brl.sourceforge.net/ "alum.mit.edu")]>
Bruce Hoult <br...@hoult.org> writes: > Lisp can't move in a direction. It just is. Platonic. Pure. Common > Lisp can move in a direction.
Hmm, maybe you should take a linguistics class, they explain why symbols don't have one static meaning. Languages change.
-- -> -/ - Rahul Jain - \- <- -> -\ http://linux.rice.edu/~rahul -=- mailto:rj...@techie.com /- <- -> -/ "Structure is nothing if it is all you got. Skeletons spook \- <- -> -\ people if [they] try to walk around on their own. I really /- <- -> -/ wonder why XML does not." -- Erik Naggum, comp.lang.lisp \- <- |--|--------|--------------|----|-------------|------|---------|-----|-| (c)1996-2002, All rights reserved. Disclaimer available upon request.
Bruce Hoult <br...@hoult.org> writes: > In article <877koexin3....@photino.sid.rice.edu>, > Rahul Jain <rj...@sid-1129.sid.rice.edu> wrote: > > Bruce Hoult <br...@hoult.org> writes: > > > No, syntax does not matter. For example, Common Lisp and Dylan can > > > usually be easily transliterated into each other, but the syntax is > > > quite different. > > It all depends on what's "usual". > Of course. Unfortunately it's always going to be subjective.
Or rather, a concept that should be defined in terms of community instead of some arbitrary transient critera.
> The idea is *precisely* that the book should have programs that do some > general, useful, thing rather than programs intended to illustrate > obscure and seldom-used corners of the language.
call/cc is a general, useful things. throw/catch is a common technique, and scheme programmers need to use call/cc to do that.
> > > Perhaps a better example (which I mentioned yesterday but forgot today) > > > is the heavy use of pattern matching in ML. > > That can be done without too much trouble with COND. As much trouble > > as any other differences between the languages. > "Too much trouble" is subjective. I'd say it's too much trouble to just > use cond. If you had a destructuring-cond then it might not be.
Right, just a simple macro. Or maybe it's not so simple in scheme? I can't imagine why.
> > Perl has eval, too. > My point exactly. More than one c.l.ler has pointed out how close Perl > 5 is getting to being a Lisp.
Except that it doesn't have any of the features that I find defining in Lisp. (code (and data) represented as cons-trees of symbols in packages, most importantly.)
-- -> -/ - Rahul Jain - \- <- -> -\ http://linux.rice.edu/~rahul -=- mailto:rj...@techie.com /- <- -> -/ "Structure is nothing if it is all you got. Skeletons spook \- <- -> -\ people if [they] try to walk around on their own. I really /- <- -> -/ wonder why XML does not." -- Erik Naggum, comp.lang.lisp \- <- |--|--------|--------------|----|-------------|------|---------|-----|-| (c)1996-2002, All rights reserved. Disclaimer available upon request.
> Kent M Pitman wrote: > > If you think CL is missing some higher order operation that it should have, > > other than the known issues over tail calling and call/cc, I'd be curious > > to know. If these two items are what you mean by higher order, I am > > perhaps missing your point somehow.
> Yes, you are. I was talking about the fact that the defining > feature of Lisp2, separate environments for values and for > functions, creates a bias against higher-order thinking.
Whoa! Slow down, Will. It's obvious from Kent's post that you need to define higher-order here. It looks like you're talking about higher-order functions: functions that manipulate functions that manipulate functions.
Functions that manipulate other data types are first-order functions. Functions that manipulate first-order functions are second-order functions. Am I using your terminology?
Absent definition, "higher order thinking" just sounds like "superior thinking," making your post even more inflammatory.
> In Lisp2, functions are usually bound in a different environment from > other values, so Lisp2 programmers do not think of functions simply as > values. Thus, for example, you can find examples of Common Lisp > programmers who do not see the need for hygienic macros, claiming that > function names cannot be shadowed. Are they unaware of FLET and > LABELS? Probably not. Probably they're just aware that FLET and > LABELS are so seldom used as not to cause a problem for macro writers. > Why aren't FLET and LABELS used? There are many reasons, but one is > the cultural bias against higher-order thinking that results from a > Lisp2.
I think you're making too much of what you see in this Usenet discussion. Yes, Lisp1 makes using higher-order functions more convenient. However, someone who knows how to use higher-order functions will use them in any language, most assuredly in a language that includes lambda. If you want to argue that a Lisp1 is better for people learning about higher-order functions, go for it. But don't paint "Lisp2 programmers" with one brush.
> Many of the people who are attracted to Lisp in the first place > don't like to clutter their programs with all these injections > and coercions from one type to another. They're annoying and > unnecessary.
Let the language with no idioms that anyone views as "clutter" cast the first stone.
> If you're a higher-order thinker, you'd be happier > with a Lisp1 if all else were equal.
> It wouldn't be, of course.
Right, so even higher-order thinkers may have valid reasons for choosing CL, even if it means having to type #' a lot.
-- <brlewis@[(if (brl-related? message) ; Bruce R. Lewis "users.sourceforge.net" ; http://brl.sourceforge.net/ "alum.mit.edu")]>
>>>>> On 15 Mar 2002 13:38:02 GMT, Dorai Sitaram ("Dorai") writes:
Dorai> In article <3C91BE29.8872F...@cfmu.eurocontrol.be>, Dorai> Ian Wild <ian.w...@eurocontrol.int> wrote: >> Dorai Sitaram wrote: >>> >>> I'm sorry I didn't understand that. Is an "embedded >>> Lisp" something that has an s-exp syntax but doesn't >>> have read, prin1, etc? Does this Lisp system have >>> ports (in the sense of doors) to the outside >>> world at all, and how does it accept a Lisp program to >>> run? >> >> Err....I feed my program to the compiler and it generates >> the bytes that get burned into ROMs that make the doorbell >> play the opening sequence of "All You Need is Love". I >> can write my program in a choice of languages, assembler, >> C, and PL/M spring to mind, but you're suggesting I can >> /never/ use Lisp unless I also fit a screen and keyboard >> to the doorbell. (Plus, I'd guess, a disc drive to >> give "load" somewhere to look.)
Dorai> I would say you have a Lisp _program_.
No, he's saying his robot doorbell has a Lisp runtime system that is capable of running Lisp programs downloaded into it.
The same thing is true in C: there is a C runtime system in the robot or credit-card terminal, and it probably does not include printf.
> Kent M Pitman wrote: > > If you think CL is missing some higher order operation that it should have, > > other than the known issues over tail calling and call/cc, I'd be curious > > to know. If these two items are what you mean by higher order, I am > > perhaps missing your point somehow.
> Yes, you are.
Hmm. (Reading what you've written, I'm still not so sure I'm missing something. I certainly accept that you think I am. My personal take is that I perceive the same fact set differenlty than you. But it's really of no consequence as long as we can understand each other well enough to debate, and I certainly find your presentation of the perceived problem lucid enough to continue...)
> I was talking about the fact that the defining > feature of Lisp2, separate environments for values and for > functions, creates a bias against higher-order thinking.
This is a nice succinct example of where we take a different view on the same data. I perceive that you think writing #'foo is somehow a negativity because you don't what to write it. I think what you don't see is that I don't have any negative take on the writing of #'foo and so I am not negatively biased away from using it.
To cast things into provocative terms, I might say "what creates a bias against higher-order thinking in CL is the people lined up with picket signs outside the School of CL Programming's doorsteps saying "#' is ugly". I don't think it's a necessary truth, but I think if you chant it enough, you might make some headway. And certainly you will make people feel like they are offending someone by doing it. But in the end, all that means is you will cause people not to do higher order programming since that _is_ the syntax we do it in. You will not cause a change in the language this way. Indeed, if you want to encourage higher order programming, you need to get Nike to sponsort a set of signs for your picketers that say "Just call it" and that ignore the syntax.
> In Lisp2, functions are usually bound in a different environment > from other values, so Lisp2 programmers do not think of > functions simply as values.
This is surely isn't true of me. I do. That's what I find so incredible about this discussion. I look at #'car and think of it as just another function. One I file in a special "hot file" of quickly available functions so that it will be available EVEN IF there is a local lexical binding shadowing it. I regard it as diminishing the importance of the function named by #'car if you allow it to be shadowed! That says, "it might not be important to get to this function in this context" and that strikes me as extraordinariliy bizarre!
> Thus, for example, you can find > examples of Common Lisp programmers who do not see the need > for hygienic macros, claiming that function names cannot be > shadowed.
Function names cannot be _unpreventably_ shadowed. Both CL and Scheme allow the writing of buggy code, of course.
I realized after my post on "data hygiene" that the issue is that Scheme provides two-argument EVAL but CL needs only 1-argument EVAL because the "meaning" (read: the appropriate binding environment) of symbols to EVAL is obvious just from the symbols. Moreover, in CL you can construct mixed-use expressions that are tricky to compose in Scheme without layering extra levels of expression. Consider: (eval '(cl:car (foo:bar alpha:*beta*))). Now in Scheme you would have to first receive the environment in which FOO and *BETA* were meaningful in order to do (lambda (foo-environment alpha-environment) (eval `(car ',(',(eval 'bar foo-environment) ',(eval '*beta* alpha-environment))) (scheme-report-environment 5))) or else you have to receive the actual values of those symbols from someone who has done you the service of looking those things up (lambda (bar *beta*) (eval `(car ,(',bar ',*beta*)) (scheme-report-environment 5))) or (lambda (bar *beta*) (eval `(car ,(bar *beta*)) (scheme-report-environment 5))) [the second is more concise, but kind of does EVAL the favor of doing part of its job for it beforehand].
> Are they unaware of FLET and LABELS?
To understand this situation, you must work by cases:
First, I consider minimal competence of a programmer to include the requirement that the programmer is not only aware of FLET and LABELS but is aware of his own code and the consequences of his own code.
FLET and LABELS can certainly shadow names, _however_
(a) if a programmer shadows his own names, I must conclude he intends to and I take this as the same kind of gesture as I would in scheme if one issued a "please capture" request to a hygienic macro system
(b) if a programmer shadows another's names, they are declaring themselves implementor of that other programmer's code. This is bad style, IMO, and in general should never be done in well-styled code. (It is, however, sometimes done and sometimes even defensibly in an attempt to patch broken code.)
Probably not.
> Probably they're just aware that FLET and LABELS are so seldom > used as not to cause a problem for macro writers.
No, I use them all the time. But I don't run into trouble because I (a) never shadow my own names and (b) I never bind the names of another package. Doing (a) assures I do not break my own macros and (b) assures I don't break others' macros. So macros just work.
> Why aren't FLET and LABELS used?
Because a lot of the time we don't need them. I use them any time I don't have a simpler way to do something. I use them a _lot_ in macrology, which you'd think would get me into trouble if macro hygiene were not present, but my code works quite reliably because there _is_ hygiene. It is just partially enforced at the data level, something Scheme does not have in its weakened notion of symbols.
> There are many reasons, but one is the > cultural bias against higher-order thinking that results from > a Lisp2.
I just don't agree.
> In Scheme, by contrast, LET, LETREC, and local definitions are > quite often used to define local functions. There are many > reasons for this, too, but one is that local functions are > convenient in higher-order programs, and Scheme, being a Lisp1, > has attracted people who like to write higher-order programs.
I don't disagree with this analysis of Scheme, though I think Scheme has done a disservice to others elsewhere by teaching its benefits as a contrast to the way others do things, rather than acknowledging other legitimate systems where higher order function are available. People come out of Lisp courses thinking it is a lemma that we don't have higher order functions that work, and so do not stop to examine that perhaps this is false.
You're certainly right that people who teach higher order functions tend to come from a Scheme background, but this is not a technical issue, it's an issue of historical preference ... er, "compatibility with the past", that thing we're sometimes reviled for, but just not Lisp's past. Someone else's past. And, as you can see, there is value to this. Because it attracts a certain kind of person. I just wish you didn't keep all the knowledge of higher order functions bottled up in the Scheme community by making it socially unacceptable for people with that knowledge to socialize with people from other communities without becoming hostile and evangelistic. (Not you personally, necessarily, though I think your personal rhetoric does sometimes have this effect, even though I know it's not your intent. But I mean "you" collectively, meaning the "Scheme establishment".)
I would liken this problem to the problem of producing equal rights among the races or the genders. The problem between races or genders arises in the first place becausee people like things in black and white (if you'll pardon the unintended pun, by which I really only mean "binary"). They want the good guys to be recognizable quickly from the bad guys, and what could be easier than looking at skin color or gender? So forgetting who caused the first order effect, the fact is that when the move for equality happened, the oppressors were of one race and the oppressed were of another, or the oppressors were of one gender and the oppressed of another. So, heh, it was easy to tell again who the bad guys were and who the good guys were. And the campaign for equality was mounted.. But wonder of wonders, the problem wasn't solved overnight and now here's the mess: people are still sometimes oppressed and people are sometimes not. And _neither_ the oppressed nor the oppressors are any longer recognizable simply by their "look". At that point, we've seen that society gets into a mess because some people start to realize that their allies come in both kinds but others really preferred the battle lines to be easily drawn and continue to behave as if the other gender or race were the enemy because it's easier, in effect repeating the underlying sin against which they are fighting: identifying a problem on the basis of a superficial earmark rather than on the basis of who is really causing what.
Now, one solution to this is for CL folks to claim that Scheme is a Lisp and to claim we all are of the same "race" or "gender" because we have the same look. But that's a simplistic solution because if you _really_ want to do outreach, and not simply rail against Bad Guys and Good Guys who can be recognized on sight by some earmark that has nothing to do with what you were complaining about, then at some point you have to stop labeling people by how they look and you have to start to say that what they do matters.
I think that what we do is more complex than it looks at first glance, and I'm really just tired of being railed at for being automatically wrong by people not taking a deep look at it. (Whether that's you or not depends on what's in your
> > > In article <3225161536947...@naggum.net>, Erik Naggum > <e...@naggum.net> wrote:
> > The single namespace, the lack of first-class symbols, exacerbated > > by the lack of packages, and the need for make-shift solutions to what > > should not have been problems, are all among the things that will > > continue to create problems.
> I think I really don't understand what he means by "first class symbols." > The phrase "first-class function" usually means that functions can be > passed as arugments and returned as values. Scheme symbols have those > properties as well. So one of us is obviously missing something, and I'm > pretty sure it's me.
While I hesitate to put words in Erik's mouth, I think that Erik is referring to the fact that the symbols in Scheme have very little to do with the symbolic identifiers in the code.
In Common Lisp, when you bind a special variable, or when you define a function, there is a both a distinguished name (the symbol) and a distinguished location (the function or value cell) where the value is *required* to be stored, and these are available at top level. So if you wrote a function `foo', the compiler will arrange for that function to be in the function cell of the symbol `foo'.
To contrast this with Scheme, the compiler arranges it so that the identifier `foo' will recover the current value of foo, but this has nothing to do with the symbol `foo'. Having the symbol `foo' won't (in general) let you modify the value or function associated with that name.
What this means is that the process of `linking' in Common Lisp is required to maintain its data keyed by symbols. This gives one an API to the link info which is very handy for debugging, introspection, and other advanced functionality.
Note that most Scheme implementations provide some functionality along these lines, but there is no defined standard.
> ... But Kent's right that another thing suddenly pops up:
> "I cannot later 'relate', at the symbol level, your person-1 with my > person-1, without doing a global renaming."
> Sure, this is certainly true. In Common Lisp, the two person-1's are > relateble, in that each program has easy access to the other. (And > the package system helps make that access even easier, and well > controlled.)
> Here the difference is going to just be one of style. It's actually > program hygene now, and making that access as easy as Kent would like > would be *breaking* a hygene barrier.
But this means that doing the thing you can do so easily in CL with (make-instance 'frob 'a 3 'b 4 'fred:a 7) is basically impossible to do in Scheme with symbols. You _must_ use non-symbols for the keyword markers. And as soon as you do this, you're not a "symbol processing language", IMO.
> I'm not here "railing" against the Common Lisp package system. I > think it's clearly the right thing in a language with "heavy" > symbols--symbols that have plists and all that.
But the Scheme symbol system is basically no more powerful than the Lisp KEYWORD package, and there are known limits to what that can do for you.
The term 'keyword' is even used sometimes in place of 'symbol' in Scheme bookmaking, underscoring the fact.
> Now you argue that this has made the macro system in Scheme "very > complex", but I think that's looking at the wrong side of the > problem. Scheme macros, from the user's perspective, are as simple as > can be: they reliably Just Work.
For those macros you can write at all. What about CL's LOOP? Can you write that in Scheme's macro system? Does the failure to be able to write a certain syntactic extension count as 'just working'?
> Everytime I worry (oh, will this > shadow something wrongs) and I bother figuring it out, I realize, > "nope, the rules nicely make sure the Right Thing will happen".
I never lose sleep over this particular problem. I lose more sleep over the loss of general-purpose symbol analysis and manipulation under full control of a Turing machine, which is what Scheme does. If it did give you this full control, things would not "just work", I claim. Unless you had something else looking out for you--like our conventions for data hygiene.
> The complexity is in the *implementation*, to preserve that quite > simple appearance to the user.
Provided you only want to do a subset of the things with your macro system that CL people routinely do. (Dylan, with its hygienic system, has the same limitations.) I'm not saying there's not a lot you can do. But a general purpose turing-machine-like equivalence has yet to be drawn that I've seen.
g...@jpl.nasa.gov (Erann Gat) writes: > No, I think I really am confused :-) Here's the unelided sentence:
> * Erik: > > The single namespace, the lack of first-class symbols, exacerbated > > by the lack of packages, and the need for make-shift solutions to what > > should not have been problems, are all among the things that will > > continue to create problems.
> I think I really don't understand what he means by "first class symbols." > The phrase "first-class function" usually means that functions can be > passed as arugments and returned as values. Scheme symbols have those > properties as well. So one of us is obviously missing something, and I'm > pretty sure it's me.
For many years, up until R5RS, the syntax was not (as with CL) about s-expressions. It was really about open parens and whitespace and stuff. There was no EVAL and it was possible to compile Scheme without calling READ. In this sense, the language was not defined on "symbols" but on some etherial syntax that looked like the syntax for symbols. Symbols and lists existed as data but had no relation to the names and other syntax things used in the language definition.
A patch was recently applied to the spec that said you can optionally call READ and can interpret these rules to be about structure instead of about syntax. But that wasn't how it was for a long time.
> > First-class symbols in > > specifying language semantics; certainly it has the datatype and I don't > > think he was denying that.
> Could you explain what you mean by that? I understand that CL semantics > are specified in terms of symbols. What I don't understand is why this is > considered so important. Is this really about special variables?
No.
> Because > if it is then it seems to me that you can easily emulate special variables > in Scheme using dynamic bind. (I'm not saying this as Scheme propoganda. > I'm saying this as an indication of where my understanding is at to help > people frame a response.)
> > As to your point, though, Erann, the addition of first-class symbosl in the > > language semantics is a very recent addition. A patch because many of us > > have complained about this for so long. Traditionally, Scheme has not had > > this. Nor has it had EVAL.
> R4RS had symbols so they go back at least to 1991. I can't find an online > copy of RNRS for N<4 so I don't know if they go back any further than > that.
It's not about the having or not having of a symbol datatype. It's about names in the language not being symbols because nothing in the language said that consed structure was even in play when applying language semantics, however similar data may have been to such consed structure.
Centuries ago, Nostradamus foresaw when Kent M Pitman <pit...@world.std.com> would write:
> ces...@qnci.net (William D Clinger) writes: > No, I wouldn't. I've used Scheme several times for work and > sometimes for play and have been around it all my adult life. I am > never happy with it because I just don't like the Lisp1 notation. I > find it needlessly cramping simply to have the binding of a variable > preclude my access to the same-named function. I find that easily > as offensive and cumbersom and putoffish as I believe you find > FUNCALL.
It's certainly a disputable matter whether or not it's a truly _fundamental_ problem that it's bad that, in Scheme, you can't do
I don't think it's vastly unfair to compare this to the PL/1 sort of thing of:
IF IF = 5 THEN LET LET = 7 ENDIF
[That might not quite be legitimate PL/1; hopefully the namespace "collisions" are obvious enough :-).]
In contrast, it's kind of irritating that Common Lisp prevents me from writing:
(defun c2f (t) "Convert Celcius temperature to Fahrenheit" (+ 32 (* 9/5 t)))
It is kind of nice to be able to use LIST as a variable name in CL, but that strikes me as being about as important as the fact that new macro schemes for Scheme keep making it pretty easy to redefine IF. (I haven't much call for redefining IF, as the existing one works _perfectly well_. That's one of the irritations of Alternative Macro Systems; they almost always focus on reimplementing something that already works well...) -- (concatenate 'string "aa454" "@freenet.carleton.ca") http://www3.sympatico.ca/cbbrowne/linux.html You will pay for your sins. If you have already paid, please disregard this message.
d...@goldshoe.gte.com (Dorai Sitaram) writes: > and while I did mention "load" which I think is file-specific > even in CL
LOAD can take a stream as argument.
-- Lieven Marchand <m...@wyrd.be> She says, "Honey, you're a Bastard of great proportion." He says, "Darling, I plead guilty to that sin." Cowboy Junkies -- A few simple words
> Hygenic macros solve a problem that CL does not have. (They solve a > problem introduced by Lisp1-ness. Heh.) I see no need for these > whatsoever.
* Bruce Lewis | You never need to use gensym when writing CL macros?
Please realize the difference between a requirement and a choice.
| Non-hygienic macros are definitely useful, but this bashing of hygienic | macros doesn't seem right.
It would not have been right in comp.lang.scheme. You are not in comp.lang.scheme. Over here, the obsessived-compulsive drive for "hygiene" is basically the object of some ridicule. People who scrub (like doctors) before they eat, after they have been in touch with potentially disease-carrying materials (bonus points for overstating the potential), and, say, before touching anything valuable, like a book or a keyboard, may find like-minded people who consider this proper behavior, but they should also prepare themselves to have their views rejected by other people in sometimes hostile and sometimes derogatory ways.
If you want some of the worst design decisions in Scheme to be protected from ridicule, choose comp.lang.scheme. If you consider the derogatory implication of calling Scheme macros "hygienic" (which is just as snotty as we expect from the Scheme community), some ridicule back at a language that needs them because it dirties _itself_ should be par for the course. It is not Common Lisp that dirties itself and "lacks hygiene", it is what Scheme would do. However, it is fairly obvious that the choice of the word "hygiene" is intended to communicate a superiority and instead of calling Common Lisp macros just "macros", they become "non-hygienic". What the hell is _that_? Scheme freaks who hijack the premise for a discussion like that are bad people in my book. Duane Rettig made a similar point about "proper tail recusion", which I chuckled when reading, because I had been taken in by the "improper" tail recursion that would be found in every other language. Scheme is chock full of snotty terminology like that and it is, frankly, really, really annoying.
I have read some of the most ludicrous nonsense about Common Lisp macros in comp.lang.scheme, where the common perception seemed to be that Common Lisp dirties itself _exactly_ the same way Scheme does, and it seems that Scheme freaks generally tend to think Common Lisp is nothing more than a variant of Scheme, that all the choices made by Scheme are also made by Common Lisp, except the ones that Common Lisp "missed" and that Common Lisp therefore sucks. However, this is the problem with Scheme freaks when they wander outside their little playpen -- they do not _know_ that their terminology is Scheme-specific, they do not _know_ that they have made a huge number of design decisions that are different from other members of the Lisp family, and yet they have the _gall_ to parade their arrogant ignorance outside their chosen forum, huffing and puffing like some mighty little dragon. _This_ is what has caused me to regard Scheme as an inferior language with inferior people in its community for so long, since no sane person would have to engage in such tactics to feel good about themselves and what they do. "Look, I'm hygienic and you're not, and I'm proper and you're not" is not particularly mature rhetoric, but it _is_ a pretty good marketing strategy for something that is in need of such rhetoric. But then the Scheme freaks want to pretend that what they do is _technical_ and _not_ political. That is when the sheer dishonesty becomes a little too much to bear for non-fans of Scheme.
/// -- In a fight against something, the fight has value, victory has none. In a fight for something, the fight is a loss, victory merely relief.
Bruce Lewis <brls...@yahoo.com> writes: > You can always pass something like this: > (list kent 'person-1 rahul 'person-1) > where kent and rahul are hash tables, assoc lists, closures or > something.
So instead of having proper namespaces for symbols in the first place, we should pass around the namespace as an extra arg for everything that MIGHT require a symbol argument?
-- -> -/ - Rahul Jain - \- <- -> -\ http://linux.rice.edu/~rahul -=- mailto:rj...@techie.com /- <- -> -/ "Structure is nothing if it is all you got. Skeletons spook \- <- -> -\ people if [they] try to walk around on their own. I really /- <- -> -/ wonder why XML does not." -- Erik Naggum, comp.lang.lisp \- <- |--|--------|--------------|----|-------------|------|---------|-----|-| (c)1996-2002, All rights reserved. Disclaimer available upon request.
* Erann Gat | I think I really don't understand what he means by "first class symbols." | The phrase "first-class function" usually means that functions can be | passed as arugments and returned as values. Scheme symbols have those | properties as well. So one of us is obviously missing something, and I'm | pretty sure it's me.
But what can you do with a symbol in Scheme? Can you read and write its value? At least you can call a (first-class) function that has been pased to you. Can you call a symbol in Scheme if its global value is a function? If symbols are _only_ interned constant strings, I do not see the value of calling them "symbols" in the Lisp sense of the word. This is one of the cost of flirting too much with the Algol family.
/// -- In a fight against something, the fight has value, victory has none. In a fight for something, the fight is a loss, victory merely relief.
In article <sfw1yel34u6....@shell01.TheWorld.com>, Kent M Pitman <pit...@world.std.com> wrote:
> > Now you argue that this has made the macro system in Scheme "very > > complex", but I think that's looking at the wrong side of the > > problem. Scheme macros, from the user's perspective, are as simple as > > can be: they reliably Just Work.
> For those macros you can write at all. What about CL's LOOP? Can you > write that in Scheme's macro system? Does the failure to be able to write > a certain syntactic extension count as 'just working'?
> [...]
> Provided you only want to do a subset of the things with your macro system > that CL people routinely do. (Dylan, with its hygienic system, has the > same limitations.)
When I read the first para above I wasn't sure whether you intended to lump Dylan with Scheme. I'm not up on the latest Scheme macro systems, but at least in Dylan the macro system is powerful enough to implement LOOP. Not only that, but it's part of the standard library.
> I'm not saying there's not a lot you can do. But a general purpose > turing-machine-like equivalence has yet to be drawn that I've seen.
Dylan macros are Turing-equivalent, although I think you'd be nuts to do anything that made use of that fact.
To my mind, macros are for providing nice syntax for things that you find you want to do frequently but that would be tedious to type or ugly to read. Making simple examples of tail recursion look like iteration does in other languages, for example. Or hiding ugliness such as the way you can use anonymous clases to implement anonymous functions in Java -- which I think you said earlier today would be reasonably acceptable if you could hide it in a macro.
In article <sfwn0x9eccg....@shell01.TheWorld.com>, Kent M Pitman
<pit...@world.std.com> wrote: > For many years, up until R5RS, the syntax was not (as with CL) about > s-expressions. It was really about open parens and whitespace and stuff. > There was no EVAL and it was possible to compile Scheme without calling > READ. In this sense, the language was not defined on "symbols" but on > some etherial syntax that looked like the syntax for symbols. Symbols > and lists existed as data but had no relation to the names and other > syntax things used in the language definition.
OK. But I still don't see why this should be such a big deal. Common Lisp syntax always denotes data, and has rules for interpreting certain kinds of data as code. Scheme has one syntax for programs, and another syntax for data, and the syntax for programs just happens to be a subset of the syntax for data. The difference to me seems purely rhetorical. At the end of the day I can call READ to translate character sequences into data, and LOAD to translate those same character sequences into code. (In fact, I can write EVAL in R4RS Scheme in terms of PRINT and LOAD.) And the whole issue, which never seemed to me (even ten years ago) like an issue to begin with, is now rendered doubly moot by the addition of EVAL to Scheme.
In other words, what is it you want to do that the "lack of first class symbols" (whatever that means) prevents you from doing?
> > Is this really about special variables?
> No.
...
> It's not about the having or not having of a symbol datatype. It's > about names in the language not being symbols because nothing in the > language said that consed structure was even in play when applying > language semantics, however similar data may have been to such consed > structure.
So I still don't see why this should be important except rhetorically. Why does it matter if the interpretation of "((lambda (x) (foo x)) (zot))" is given in terms of symbols or not as long as the net result is the same in both cases?
The only *real* difference I can think of is that in CL one can do something like (symbol-value (intern (read))), in other words, computing the dynamically bound value of a symbol whose identity is not known at compile time. (If you know the value of the symbol at compile time then (symbol-value 'X) is just X.) Before R5RS this did not have a straightforward Scheme equivalent. (Now it's just (eval (string->symbol (read)) (interaction-environment)).) That's why I asked if this was "really about special variables." Since the answer to that is no I think I'm still missing something.
In article <3225221516192...@naggum.net>, Erik Naggum <e...@naggum.net> wrote: > * Erann Gat > | I think I really don't understand what he means by "first class symbols." > | The phrase "first-class function" usually means that functions can be > | passed as arugments and returned as values. Scheme symbols have those > | properties as well. So one of us is obviously missing something, and I'm > | pretty sure it's me.
> But what can you do with a symbol in Scheme? Can you read and write its > value?
Yes:
(symbol-value x) == (eval x (interaction-environment)) (set x v) == (eval `(set! ,x value) (interaction-environment))
> Can you call a symbol in Scheme if its global value is a function?
Yes:
((eval f (interaction-environment)) arg1 arg2 ...)
or
(define (function f) (eval f (interaction-environment))) ((function f) ...)
Note that in the most common case where the identity of f is known at compile time this becomes simply (f arg1 arg2 ...).
You can even do:
(define (funcall f . args) (cond ((symbol? f) (apply (eval f (interaction-environment)) args)) ((procedure? f) (apply f args)) ((vector? f) (apply vector-ref f args)) ;-) ((and (cons? f) (eq (car f) 'lambda)) ...) ... (else ... ) ; error - f is not callable
> If symbols are _only_ interned constant strings, I do not see > the value of calling them "symbols" in the Lisp sense of the word.
So this is what I am struggling to understand. I have always thought that interned-constant-string is the "essence of symbolness". Whether symbols are mapped to values by having those values be "part of" the symbol as in CL, or through a separate environment object as in Scheme, seems to me at least on a practical level to be a relatively minor detail.
What do you see as the value (in the economic sense) of a symbol in the Lisp sense of the word? What can you do with a Lisp symbol that you can't do with a Scheme symbol? The only thing I can think of, even in pre-R5RS scheme, is computing the dynamic binding of a symbol whose identity is not known until run time.
Bruce Lewis <brls...@yahoo.com> writes: > Kent M Pitman <pit...@world.std.com> writes:
> > I cannot in Scheme construct the notion of passing > > '(kent:person-1 rahul:person-1)
> > Or if I do, then KENT:PERSON-1 is a symbol with a 13-letter name and the > > functions that do the accessing have to first decode it to find a hidden > > symbol PERSON-1 within it and also a function or table that corresponds > > to Kent's NAME operation/resource.
> I think you're making too much of this.
> You can always pass something like this: > (list kent 'person-1 rahul 'person-1) > where kent and rahul are hash tables, assoc lists, closures or > something.
But then I'm not using symbols as my basic guide word. In MAKE-INSTANCE, for example, the convention is
Now it either _is_ or _is not_ "good enough" to have keys be symbols. In CL it _is_ "good enough" because even a class made from two classes made by different people who both want a SIZE keyword (e.g., it's both a physical-object with width 19 (inches) and a screen-object with width 1024 (pixels) can be accomodated if they choose initargs of 'physob:width 19 'drawing-area:width 1024 and moreover this can be done in a way such that within each of those packages it isn't cumbersome because they just use 'width 19 in the scope of their own little domains where they are not mixed together. But to do (defclass the-big-picture (physob:monitor drawing-area:screen) ...) would be a disaster if you're using symbols as the markers. Yes, you could say the whole make-instance protocol needs to be (make-instance thing '(drawing-area screen) 19 '(drawing-area width) 1024) but in addition to just plain looking bad, you have slowed things down by requiring an equal comparison instead of an eq comparison, and have introduced the need to error check that I didn't do '(drawing-area screen ham-sandwich).
What Scheme does is not what you suggest but rather to define some
(define-key width) to expand to (define width (make-key 'width)) so that you do: (make-instance monitor width 19) in the physob 'module' or (make-instance drawing-area width 1024) in the drawing-area 'module' since you'll have done separate define-key operations in both of those modules and you won't be colliding. This means if you want to mix these things you have to do (define drawing-area-width (value-from-environment 'width drawing-area-environment)) (define physob-width (value-from-environment 'width physob-environment)) and then you do (make-instance the-big-picture monitor-width 19 drawing-area-width 1024) but the important thing to understand when you are all done with all this hair is that you are not using symbols to guide you, but you have substituted objects that are non-symbols to use as guides because symbols (as defined in Scheme) don't compare well with EQ (a shared INTERN makes it too easy for them to clash) and other objects do (because other objects are not interned). So Scheme has made 'intern' a hindrance in certain cases, not a help.
> Or you could define some global lookup table for 'kent and 'rahul, and > just pass '((kent person-1) (rahul person-1)). I don't see any major > design flaw here.
Forgive me if I'm already using s-expression for some other purpose than what you've devised and if this causes me _substantial_ difficulty.
The whole point of symbols is to attach meaning to, but by interning all symbols in the same package, that is, by not having a package system, you've robbed me of that.
> Do you really think packages and property lists are prereqs for a > symbolic processing language?
That's not how I would have expressed the problem, but if push comes to shove... yes.
The problem is that what you're saying is that an atom, to use it in the original sense of the word, "an atomic unit of meaning", is really not atomic.
Java has symbols in the sense that Scheme does. It calls them canonical strings. I want more of symbols than that. Java is not a symbol processing language.
* William D Clinger | Yes, you are. I was talking about the fact that the defining feature of | Lisp2, separate environments for values and for functions, creates a bias | against higher-order thinking.
No, it does not. This is completely bogus reasoning. And if it is your gripe with funcall, which seems to be a standard problem for Scheme freaks, even though they have _apply_ just as Common Lisp does, I have posted a macro called "with-functions" that effectively removes the funcall from sight and declares the variables as functions. This should shift the bias back in the favor of "higher-order thinking". That macro took me seven minutes to write, debug, and test (,', always confuses me). The distance between a Common Lisp and "higher-order thinking" is thus seven minutes of my time, and a google search and cut-and-paste for you. Please quit griping about this non-existing problem.
| In Lisp2, functions are usually bound in a different environment from | other values, so Lisp2 programmers do not think of functions simply as | values.
This sounds totally bogus. It certainly does not follow from the premise.
| Thus, for example, you can find examples of Common Lisp programmers who | do not see the need for hygienic macros, claiming that function names | cannot be shadowed.
You can find examples of absolutely anything, and if you include jails and mental hospitals, even more, so this must be the weakest of all possible ways to express a criticism.
It probably surprises you to learn that symbols in the common-lisp package cannot be defined or bound in a conforming program, so it is actually _true_ that "function names cannot be shadowed" (which is a very strange way of saying it. but I can sort of reverse-engineer the proper meaning from it). At least a macro can expect the standard environment to apply, and I believe macros should do just that, and if they require additional environments, they should use symbols in a package over which the macro author has control.
Because of packages and the restrictions on using symbols in the common-lisp package, there is no need to ensure that you have the right definition of any symbol in the common-lisp package with a function definition. This, if you bind a variable "list" in Scheme, you have clobbered the standard function "list" for the body of the form that binds it, but if you try to name a local function "list" in Common Lisp, you already have an error in your program, one that a compiler should be reporting to you.
| Are they unaware of FLET and LABELS? Probably not. Probably they're | just aware that FLET and LABELS are so seldom used as not to cause a | problem for macro writers.
Are you unaware of the restrictions on symbols in the Common Lisp package? If you are, please see ANSI X3.226-1994 11.1.2.1.2.
| Why aren't FLET and LABELS used? There are many reasons, but one is the | cultural bias against higher-order thinking that results from a Lisp2.
Nonense. It does not result from a Lisp-2 at all. That is just a stupid argument that Scheme freaks like to offer, and it is so goddamn _stale_.
| If you still don't get it, consider what it is like to simulate higher | order functions using function objects in Java. To call a function | object f, you use a special syntax such as f.call(_) instead of writing | f(_). The .call can be viewed as a kind of cast that coerces from the | value domain to the function domain. Common Lisp's FUNCALL can be viewed | as a similar coercion.
HELLO!? I PUBLISHED A MACRO THAT REMOVED FUNCALL FROM VIEW SO THAT YOU FUCKING OBNOXIOUS SCHEME FREAKS NO LONGER HAVE ANYTHING TO WHINE ABOUT! YOU MORONS HAVE SPENT *YEARS* WHINING ABOUT THIS, YET IT TOOK ME NO MORE THAN SEVEN MINUTES TO GET RID OF IT AND CONFLATE THE NAMESPACES FOR A SPECIFIC LIST OF VARIABLE NAMES. What does this show, _other_ than that Scheme freaks are _much_ more interested knocking and denigrating Common Lisp than doing anything useful and constructive?
If you still do not get it, figure out that Common Lisp has the power and capacity to change its syntax so it can accomodate such perversely anal- retentive needs as removing an operator from sight (even though you _still_ need apply).
| Many of the people who are attracted to Lisp in the first place don't | like to clutter their programs with all these injections and coercions | from one type to another.
If they had anything approaching a usable intelligence, they would figure out how to write the macro I wrote, and I did not even have a problem with funcall to begin with, I was just so goddamn tired of the useless, incompetent whining from people who were so clueless they could not even write a little macro to get what they wanted.
| They're annoying and unnecessary.
No, this is a conclusion about Common Lisp drawn from Scheme premises. Common Lisp is not a dialect of Scheme. This is _precisely_ what this is all about. You Scheme freaks are so full of yourself that you cannot even see that other people are _able_ to make other design choices than you have. You think everything other people do is _wrong_, do you not? Some of you guys sure act like you have a one-bit right/wrong flag, and of course you do nothing wrong, so therefore what other people do must be _wrong_, since it is not what you do, and what you do is _right_.
Common Lisp programmers do not regard this the same way you do. _If_ they do, they write something like the macro I wrote. There _is_ no problem to a Common Lisp programmer -- a beginner would ask if it could be fixed and an experienced Common Lisp programmer would just do it. It is _only_ a problem to Scheme freaks who have a grudge against Common Lisp and want to confirm their delusions of superiority to themselves.
| If you're a first- or second-order thinker, then you probably won't agree | with this, and you'll be happy with a Lisp2. If you're a higher-order | thinker, you'd be happier with a Lisp1 if all else were equal.
Lisp-1 and Lisp-2 have nothing whatsoever to do with this issue. Even funcall is a non-issue. What matters is probably what Kent Pitman has been hinting at: People who want a one-bit universe where purity and elegance and such follow very simple rules are much more attracted to functional programming languages _and_ Lisp-1. You have the causality all wrong, here, and this is quite obvious: People are not _naturally_ "higher-order thinkers", but there is much evidence to support a view that some people have a hard time dealing with "horizontal complexity" and much prefer "vertical complexity" on very small initial space. These two types are fairly incompatible. A vertical complexity guy will look at a horizontal complexity guy and think he is not superskilled in anything and therefore untrustworthy and useless (many academics fall into this trap), whereas a horizontal complexity guy who meets a vertical complexity will be stunned how little he knows about the world about some corner of which he has this astonishing amount of knowledge.
Now, the most interesting thing happens is when they meet one of their own type: A vertical complexity guy will trust another and defer authority to him automatically in his "area", thinking (1) that he, too, has spent a lifetime in some incredibly small area, and (2) that you cannot go wrong if you study something long enough, especially not if some accredited university has granted him a degree. However, those who master horizontal complexity much more easily, generally display an amazing amount of insight and knowledge in many areas, draw analogies from all kinds of areas, and they can communicate with others who master horizontal complexity with ease and can understand, not trust, those who have more knowledge in one area than another, because their knowledge is integrated into a system intended to mirror the world they experience. The vertical complexity guys have built their "system" from axioms and theorems that others have provided, before they may be able to provide their own deep insight into something that requires extremely specialized skills to appreciate.
I suspect that functional programming (and Scheme) appeals to those who find that they master vertical complexity more easily and dynamic programming (and Common Lisp) appeals to those who find that they master horizontal complexity more easily. However, this is _NOT_ (repeat: NOT) a one-bit flag in your personality. But, *sigh*, what's the use? One-bit people are going to respond as if it is, as I have I created but two pigeonholes and want to stuff all of mankind into one of them, anyway.
/// -- In a fight against something, the fight has value, victory has none. In a fight for something, the fight is a loss, victory merely relief.
Christopher Browne <cbbro...@acm.org> writes: > In contrast, it's kind of irritating that Common Lisp prevents me from > writing:
> (defun c2f (t) > "Convert Celcius temperature to Fahrenheit" > (+ 32 (* 9/5 t)))
No, it doesn't. You can just do
(defpackage temperature (:use "CL") (:shadow "T"))
(in-package "TEMPERATURE")
(defconstant true 'cl:t)
and you're all set.
Exactly because CL has packages, it's easy to redefine even reserved words.
> It is kind of nice to be able to use LIST as a variable name in CL, > but that strikes me as being about as important as the fact that new > macro schemes for Scheme keep making it pretty easy to redefine IF. > (I haven't much call for redefining IF, as the existing one works > _perfectly well_. That's one of the irritations of Alternative Macro > Systems; they almost always focus on reimplementing something that > already works well...)
I have a lot of call for both LIST as a function and LIST as a variable. I don't like making the decision about what every detail of the body of a function will look like when I've barely typed "(defun foo (list".
* Thomas Bushnell, BSG | But then that means that CL macros are not hygenic, because FLET captures | bindings in exactly the ways that are the point behind hygenic macros. | | Erik said if you separate function and variable namespaces, then you | don't need hygenic macros.
No, I said quite a bit more than that. Separating function and variable values is a necessary condition, not a sufficient condition to not need hygienic macros. Please return to the textbooks of whatever introductory course at your university or high school deals with argumentation and logic and LOOK UP THE DIFFERENCE BETWEEN NECESSARY AND SUFFICIENT, because you have truly not understood this and repeatedly make the mistake of conflating them.
I recommend a book I came across by accident 12 years ago: The Art of Reasoning by David Kelley. I have the first hardcover edition from 1988, but I see there is a third edition out in paperback:
There are probably lots and lots of books about thinking, but most of them seem to start with the assumption that you cannot think and thus have to learn it. This book starts with assumption that you can think, you only need to train yourself and stay away from the mistakes. Thinking is an acquired skill, but most people have somehow gotten by. There is some value to not ignoring that fact. However, many academics seem to have lost the ability to think clearly somewhere on the way to become extremely specialized in some arbitrarily complex field and they have certainly been rewarded with a highly characterized version of real thinking skills that is more about not feeling than about thinking.
| That's true only because | | 1) Global definitions are almost always functions. | 2) Global data definitions have special names, by convention , and | people never shadow those. | 3) People don't make local bindings in the function namespace. | | It's right that Lisp2 doesn't force you to follow those rules, but if you | don't follow them, then you can't claim that CL macros are hygenic.
Excuse me for knowing the Common Lisp language so well that I tend to forget that there are people out there with a strong desire _not_ to learn it before they shoot their mouths off. Now is a good tiem for you to wonder what it means that I also talked about packages and try to figure out what a Common Lisp programmer must know in order to use his language. In particular, a Common Lisp programmer has either read and understood 11.1.2.1.2 in the standard, or he has an implementation of Common Lisp (or a teacher) that enforces it. In either case, he learns that he can trust that if he sees a function call to common-lisp:car, he _knows_ what it will do, with absolute certainty -- no need to check the lexical environment, no need to afraid someone clobbered it, no need to scrub off the non-hygienic crap that Scheme accretes because it has no package concept _and_ no distinction between functional and variable values so all the good variables names are taken.
The reason Scheme needs hygienic macros is the same as the reason Scheme programmers do not call their arguments "list", but "lst". We do not have _that_ problem in Common Lisp, either. In short, Common Lisp is already a clean language, it does not need hygiene to clean up after its design decisions.
/// -- In a fight against something, the fight has value, victory has none. In a fight for something, the fight is a loss, victory merely relief.