Excellent things that helped: CL macros.
Horrible things that get in the way: CL characters,
and lack of builtin modular operators.
The problem is that CL purports to be a high-level language, but actually
provides gratuitously incompatible and subtly unusable access to what is
ought to be low-level constructs. The world has standardized on low-level
byte streams as the universal medium for communication of data, including
text. Yet, CL strings are based on a pseudo-high-level characters that are
not portably interoperable with worldly text, much less efficiently. That
there can be direct support for >8 bit characters and for character
attributes is great, but, particularly when efficient portable text-processing
is meant, the only way is using (unsigned-byte 8), and suddenly, all
builtin support for any text-processing at all vanish.
ACL6's SIMPLE-STREAMs are a definite step in the right direction,
and I hope other vendors will adopt similar interfaces.
CommonLISPers often diss Scheme for being such a small language, which forces
development of incompatible implementation-specific extensions for any
interesting work. Well, we have to face the fact that in today's world,
CL is also a small language by this criterion. Much much smaller than
C, SML, OCAML, Haskell, Mercury, Oz, Perl, Python, or whatever.
[ François-René ÐVB Rideau | Reflection&Cybernethics | http://fare.tunes.org ]
[ TUNES project for a Free Reflective Computing System | http://tunes.org ]
Racism consists in attributing to genetics what is due to memetics. -- Faré
I found macros to be helpful, but I didn't run into any particular
trouble with CL characters. I used (read-sequence) into a
simple-array and it seemed to work out well enough. Profiling
suggested the vast majority of time was spent in the md5 code.
Bit-twiddling may well be slow in Lisp, but there is the other side of
the question. In a recent project, I would have gladly accepted an
order of magnitude decrease in performance to get Lisp's rational and
bignum support instead of slaving my way around the inadequacy of C's
32 bit ints and double floats. I suspect the algorithm would be
pretty much as fast or faster in Lisp than in C on the given hardware.
It would certainly have been simpler.
Gregm
Several implementations are available for those who ask, some as fast as
those written in C, and about as low-level as C versions, too.
| Horrible things that get in the way: CL characters, and lack of builtin
| modular operators.
Huh? You probably mean that you open a file with element-type character
and since you get what you asked for, but not what you wanted, you blame
the language instead of your own incompetence at expressing your wishes.
If you really want to read a file of 8-bit bytes, specify it, and you get
exactly what you want.
| The problem is that CL purports to be a high-level language, but actually
| provides gratuitously incompatible and subtly unusable access to what is
| ought to be low-level constructs.
Huh? This sounds like a disgruntled programmer more than a language
problem. Perhaps we would be able to judge for ourselves if you posted
the actual _code_ you wrote to arrive at these weird conclusions?
| The world has standardized on low-level byte streams as the universal
| medium for communication of data, including text.
Which is a mistake, since they run into an enormous amount of trouble
with supporting more than one character encoding. The Unix model is one
of those "simpler than possible" models that do not actually work when
pushed too hard. That some operations require punning on the lowest
level of representation and that this is not only possible, but easy in
C, is not necessarily a good thing. Such representational issues should
be explicit. Even C++ has discovered the truth in this, these days.
What has stopped you from using "low-level byte streams" in _your_ code?
| Yet, CL strings are based on a pseudo-high-level characters that are not
| portably interoperable with worldly text, much less efficiently.
Whatever that means. I think you are simply seriously confused and would
have come a lot further if you had asked for help or read _all_ the fine
documentation before you became so frustrated, but that seems to be
incompatible with the tunes to which some people's egos play.
| That there can be direct support for >8 bit characters and for character
| attributes is great, but, particularly when efficient portable
| text-processing is meant, the only way is using (unsigned-byte 8), and
| suddenly, all builtin support for any text-processing at all vanish.
The myopia suffered by people who think 8 bits is sufficient is probably
never going to be discovered as long as they stare at their data from a
distance of only 1 inch. Just because you think you need a byte for a
particular operation does not mean that you do, nor that anything else
should conform to this particular requirement.
Look, you are not doing text processing when you process bytes. It works
in some environments and under some assumptions, but if you are dealing
with text, you deal with characters, not their coding, and if you deal
with bytes, you are not dealing with characters. It is that simple.
Since the C mindset is so insidious and unconscious with those who suffer
frm it, including some long-time (not Common) Lisp programmers,
| CommonLISPers often diss Scheme for being such a small language, which
| forces development of incompatible implementation-specific extensions for
| any interesting work. Well, we have to face the fact that in today's
| world, CL is also a small language by this criterion. Much much smaller
| than C, SML, OCAML, Haskell, Mercury, Oz, Perl, Python, or whatever.
What does this mean? Your conclusions seem to be drawn from a lot of bad
experiernce, but there is no way to determine whether that is due to your
incompetence or to whatever it is you conclude it must have been, blaming
the language for your problems. Just post the evidence: The code and let
people help you figure out what the real problem is.
///
--
Norway is now run by a priest from the fundamentalist Christian People's
Party, the fifth largest party representing one eighth of the electorate.
--
Carrying a Swiss Army pocket knife in Oslo, Norway, is a criminal offense.
> The problem is that CL purports to be a high-level language, but actually
> provides gratuitously incompatible and subtly unusable access to what is
> ought to be low-level constructs. The world has standardized on low-level
> byte streams as the universal medium for communication of data, including
> text. Yet, CL strings are based on a pseudo-high-level characters that are
> not portably interoperable with worldly text, much less efficiently. That
> there can be direct support for >8 bit characters and for character
> attributes is great, but, particularly when efficient portable text-processing
> is meant, the only way is using (unsigned-byte 8), and suddenly, all
> builtin support for any text-processing at all vanish.
> ACL6's SIMPLE-STREAMs are a definite step in the right direction,
> and I hope other vendors will adopt similar interfaces.
You've done the work on md5 and I haven't so this is guess work, but
my first thought where the problem would lie is that a lot of these
algorithms assume efficient 32 bit operations, which in CL will
cons. Given sufficient declarations the character->(unsigned-byte 8)
conversions with char-code should be negligable.
--
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
MD5 seems to be designed with hardware implementations in mind. This is
not a bad idea, but it tends to make software implementations weirder.
I have written an MD5 function in Allegro CL, using several low-level
features (which are still at a higher level than C) and decided to split
the 32-bit numbers in two 16-bit parts. Emacs has done the same thing,
but in a slightly different way. I wanted to add support for a bitwise
rotate function that would end up using such instructions if available,
but it is probably easier to write MD5 in assembly on each platform than
to optimize it better. In the application I used this, MD5 hashes were a
serious bottleneck, so it had to be better than using FFI to a C function.
After having worked with the MD5 functions on and off for a month or so,
I came to conclude that it _should_ be written in assembly, and started
to do that, but it turned out to be extremely time-consuming work. The
Intel processors are shy too many registers, so all the fun in trying to
make it superfast was replaced by increasing frustration over the design
of those processors. Still, initial estimates indicated that a hand-
tuned assembly version would be about twice as fast as the code that gcc
produced for the naive implementation found in the RFC, so it would be
worth it at significant cost.
I also think the new streams design from Franz Inc makes for a good way
to deal with the 64-byte buffers. It is wrong to try to work with MD5 at
the character level, and the typical use of MD5 is to ensure that some
data stream is intact. If the application that consumes the stream can
do both MD5 hashing and its real work at the same time, and can roll back
the work if the MD5 hash turns out bad, much will be saved compared to
making two passes, since we must assume that the MD5 hash is usually good.
> | Horrible things that get in the way: CL characters, and lack of builtin
> | modular operators.
> Huh? You probably mean that you open a file with element-type character
> and since you get what you asked for, but not what you wanted, you blame
> the language instead of your own incompetence at expressing your wishes.
No, I blame the language for not allowing me to express my wishes.
I can, certainly, open files in octet mode - mind you, that's precisely
what I do. But then, I'm not interoperable with all the body of
character-based text, SEXP or (shudder) XML processing. It is certainly
possible to build translation layers from one to the other, but it's clumsy,
inefficient, not portable, and underspecified.
Certainly, each implementation specifies (more or less precisely)
what happens when you use code-char and such, but then, you have
the same kind of incompatible extension hell as in Scheme. Once again,
reading their specification, I happen to like the recent things done
by Franz (SIMPLE-STREAM), but it's unhappily not directly applicable to me.
For performance, lack of supported modular integer operators
is also a big problem.
> Perhaps we would be able to judge for ourselves if you posted
> the actual _code_ you wrote to arrive at these weird conclusions?
I consider it bad practice to post large code files on USENET. I posted
the URL to that code, which ought to be enough for anyone interested.
I repeat it here (and add a second one), in case you missed it:
ftp://Samaris.tunes.org/pub/lang/cl/fare/md5.lisp
http://tunes.org/cgi-bin/cvsweb/fare/fare/lisp/md5.lisp
[I made very minor cleanups and enhancements since yesterday;
those who downloaded, beware that two of the transient revisions
that I committed a few hours ago (1.3 and 1.4) had buggy typos - sorry;
latest released (1.5) is ok]
> | The world has standardized on low-level byte streams as the universal
> | medium for communication of data, including text.
> Which is a mistake, since they run into an enormous amount of trouble
> with supporting more than one character encoding.
It is not a mistake - it is the natural thing to do in a world of
proprietary black-box devices and software.
> The Unix model is one of those "simpler than possible" models that
> do not actually work when pushed too hard.
I agree, but this is beside the point. I hate UNIX about as one can
(does the UNIX haters mailing-list still exist?) - and I use it daily.
> What has stopped you from using "low-level byte streams" in _your_ code?
I did it. But it's not portably interoperable with the character-based
SEXP code that I have. Using MD5 to portably support code version tagging,
etc., becomes "interesting". By no means impossible. Just a PITA.
> Look, you are not doing text processing when you process bytes.
No I'm not. And sometimes, I want to do only one. Sometimes, I want to do
only the other. Sometimes, I am happy with the character processing done
by my implementation (though it's not portable). Sometimes, I need precise
control on the processing that happens (e.g. because I'm precisely
transcoding stuff from one protocol to another). And sometimes, I want to
do both byte-processing and text-processing at once on the same stream
(at once: switching from one to the other, or even doing both character
processing AND md5sum'ing on the same chunk).
In the latter cases, any implicit character processing done by the
implementation is an abstraction inversion, to me.
> if you are dealing
> with text, you deal with characters, not their coding,
Not even. I could be dealing with words, with sentences, with layout
elements. In such contexts, characters are too low-level and not what I like.
Yet I don't resent of CL not standardizing on high-level protocols -- it's
things that can easily be implemented on top of them. However, wrongly
standardizing on low-level things while adding restrictions to them is
an abstraction inversion and it's wrong - it's the language getting in the
way rather than helping.
One reason C has success is because it has little abstraction inversions
(it does, with the implicit call stack and unavailability of user-defined
safe-points with respect to temporary variable allocation).
Open single-implementation languages (ocaml, perl, python, etc.) can also
be fixed with respect to any abstraction inversion that may creep - and
indeed you'll find that they have little that gets in the way.
> | CommonLISPers often diss Scheme for being such a small language, which
> | forces development of incompatible implementation-specific extensions for
> | any interesting work. Well, we have to face the fact that in today's
> | world, CL is also a small language by this criterion. Much much smaller
> | than C, SML, OCAML, Haskell, Mercury, Oz, Perl, Python, or whatever.
> What does this mean?
I'm sorry I don't speak norvegian (yet). It means precisely what it says.
Despite the superiority of LISP on some matters (macros, dynamism, object
system), it is an inferior language on many other matters (static safety,
efficiency, modularity, concurrency/distribution, resource control,
modular numbers, interface to the real-world, openness, etc.).
If you pick a particular implementation and consider it your world,
you may gain back some of it - but then you'll see that you're no better
than Scheme, and that the weight of the LISP standard is something that
drags you back rather than helps you forth. [This reminds me of the
situation of FORTH, too.]
[ François-René ÐVB Rideau | Reflection&Cybernethics | http://fare.tunes.org ]
[ TUNES project for a Free Reflective Computing System | http://tunes.org ]
If you could ask a unique question to a computer during a Turing test,
what would you ask?
-- Douglas Hofstader, Metamagical Themas
The character issue is much worse: it's a *semantic* problem.
It might not be in the speed bottleneck of this particular code
(still, a typical character-based application doing MD5 in *portable*
Common LISP would have a least 4 or 5 layers of buffers, just in the
LISP side -- which does slow things down). But it's a major PITA to
code around this nasty abstraction inversion.
[ François-René ÐVB Rideau | Reflection&Cybernethics | http://fare.tunes.org ]
[ TUNES project for a Free Reflective Computing System | http://tunes.org ]
Motto for a society of free individuals: LIBERTY + RESPONSABILITY = PROPERTY
This newsgroup, for instance.
| If someone was willing to publish code for others to use, he'd already
| have done it. Or at least announced it on a webpage.
That has actually been done. I will certainly not blame you for not
finding things on the Net, however. That is why asking those wetware
search engines called "humans" is still a very good idea.
| So far, the only advertised Common LISP implementation of MD5 is Franz'
| ACL6's - which doesn't quite fulfill my needs, and is embedded in their
| application rather than available as portable common lisp.
It is not an implementation in Common Lisp, but written in C as a
low-level system function. There seem to be serious performance
improvements in the upcoming 6.1 release.
| The ACL version is about twice slower than C.
Well, that much is fairly odd, considering that it is written in C. I
only noticed that it consed like mad because it used C space for a copy
of every string, and that C space was neither freed nor garbage collected.
| No, I blame the language for not allowing me to express my wishes.
I can sympathize with this. I frequently blame the planet earth for
exhibiting more gravitation than I wish it had, and I wish magic worked,
too, because I certainly do not want to do so much _work_ all the time.
The wishes of good engineers are subjugated to the reality in which they
need their wishes to come true. The wishes of really bad engineers are
completely disconnected from any reality. I think yours are of the
latter kind.
| I can, certainly, open files in octet mode - mind you, that's precisely
| what I do. But then, I'm not interoperable with all the body of
| character-based text, SEXP or (shudder) XML processing.
You really need to clue in that MD5 does not operate on characters. That
some languages have no idea what a character is, but treat it like a
small integer is really not something you can blame either MD5 or Common
Lisp for. If you really need a stream to exhibit characters while you do
MD5 processing on its underlying byte stream, you can do that by creating
a new stream class that reads from those 64-byte buffers that you read
from the input source and give to MD5. It is really not that hard if you
want to _work_ with the language and avoid "wishing" for things that are
incompatible with the language you use.
| It is certainly possible to build translation layers from one to the
| other, but it's clumsy, inefficient, not portable, and underspecified.
MD5 is specified to work on blocks of 64 bytes. How you get from what
you have to 64-byte blocks is really a question of quality of programmer
and implementation. I still think you are simply massively incompentent.
| Certainly, each implementation specifies (more or less precisely) what
| happens when you use code-char and such, but then, you have the same kind
| of incompatible extension hell as in Scheme.
Wrong.
| Once again, reading their specification, I happen to like the recent
| things done by Franz (SIMPLE-STREAM), but it's unhappily not directly
| applicable to me.
Well, what makes it impossible for you to take their good ideas and
implement them on your own?
| For performance, lack of supported modular integer operators is also a
| big problem.
I actually agree with this in general, but for MD5, just break the 32-bit
integers in half and operate on 16-bit values, instead. I assure you
that no significant performance loss is caused by this, and the algorithm
does not increase in complexity because of it. This is a fairly simple
engineering tradeoff that good engineers will do to get the work done and
bad engineers will refuse to do because they wish they did not have to.
| I consider it bad practice to post large code files on USENET.
Well, if your MD5 function is a large code file, then you have even more
problems.
| I posted the URL to that code, which ought to be enough for anyone
| interested.
There is no way to ascertain that what is pointed to by a URL will remain
the same after it has been criticized. We have seen how some massively
dishonest _frauds_ on this newsgroup have altered the text of published
URLs (even without updating the version) in order to make their critics
look bad. Post the code and it will be very hard to "update" it.
| I repeat it here (and add a second one), in case you missed it:
| ftp://Samaris.tunes.org/pub/lang/cl/fare/md5.lisp
| http://tunes.org/cgi-bin/cvsweb/fare/fare/lisp/md5.lisp
I find it rather odd that you cannot destill your problems down to a few
simple cases. Everybody can look elsewhere for the full context, but it
_should_ be possible to show people your problems with an appropriate
excerpt. A good bug report contains a destilled example. A bad bug
report contains a million lines of rotten code with a single line "this
code is perfect, but your compiler does not conform to my wishes".
| > | The world has standardized on low-level byte streams as the universal
| > | medium for communication of data, including text.
| > Which is a mistake, since they run into an enormous amount of trouble
| > with supporting more than one character encoding.
| It is not a mistake - it is the natural thing to do in a world of
| proprietary black-box devices and software.
Huh? You have a special knack for non sequiturs. TEXT IS NOT BYTES.
You _really_ need to understand this. Failing that, you will run into
all sorts of problems, and there will be no end to your complaints, as I
suspect you have already noticed.
| I did it. But it's not portably interoperable with the character-based
| SEXP code that I have.
Really? Tell you what, when I wrote my MD5 functions for Allegro CL 5.0,
I stuffed it between the I/O system and the reader, and I reset and grab
the md5 hashes while reading characters from the stream. If I can do
this in Allegro CL, so can you in CMUCL. If you naively implement the
fairly stupid C model used for MD5, sending blocks of 64 "bytes" down to
a new function, instead of grabbing the input buffers of the stream, and
run into problems that you do not look into seriously in order to find a
better way, you are simply incompentent at what you do and should not
blame anyone else, _especially_ not the language.
| Using MD5 to portably support code version tagging, etc., becomes
| "interesting". By no means impossible. Just a PITA.
I have no idea what you are trying to talk about.
| No I'm not. And sometimes, I want to do only one. Sometimes, I want to
| do only the other. Sometimes, I am happy with the character processing
| done by my implementation (though it's not portable). Sometimes, I need
| precise control on the processing that happens (e.g. because I'm
| precisely transcoding stuff from one protocol to another). And
| sometimes, I want to do both byte-processing and text-processing at once
| on the same stream (at once: switching from one to the other, or even
| doing both character processing AND md5sum'ing on the same chunk).
I honestly fail to see the problem. In my view, it takes a fairly dense
programmer to fail to deal with these things intelligently. If you need
both byte stream and character stream, as you would do in HTTP, there are
two ways of doing that: so-called "bivalent" streams, from which you can
read both bytes and characters, but which introduces serious problems in
maintaining state information about non-trivial character codings, or
some means to switch the type of the stream between byte and character,
which communicates to the lower levels what you intend to do from now on.
If you need precise control, ask for it. Your system does _not_ do a lot
of weird magic that you have no control over. Just trust me on this, OK?
Go read the fine documentation and discover for yourself that you _can_
trust the implementation.
| In the latter cases, any implicit character processing done by the
| implementation is an abstraction inversion, to me.
Yes, to you, because you have _already_ inverted the model. You do _not_
convert from bytes to characters to bytes in order to do MD5 hashing on
the bytes -- the danger of losing the original byte values is too high no
matter how you do things. You have to get at the bytes where they are
actually found, just after they have been read, and just before they are
written. Anything else is pretty damn stupid.
| > if you are dealing with text, you deal with characters, not their
| > coding,
| Not even. I could be dealing with words, with sentences, with layout
| elements. In such contexts, characters are too low-level and not what I
| like.
I am sure you think this is relevant to something. Could you try to make
it a bit more clear what it is might be relevant to? No, never mind.
| Yet I don't resent of CL not standardizing on high-level protocols --
| it's things that can easily be implemented on top of them. However,
| wrongly standardizing on low-level things while adding restrictions to
| them is an abstraction inversion and it's wrong - it's the language
| getting in the way rather than helping.
Have you at all considered that _you_ might be wrong in any of this? If
not, I would actually like to hear your arguments for why your way of
seeing things is correct. I am getting tired of your non sequiturs and
the randomness of your "conclusions".
| I'm sorry I don't speak norvegian (yet). It means precisely what it says.
Oh, geez, you really _are_ a typically French retard. Well, thank you
for proving that my guess that your whining is due to your incredible
incompetence and the arrogance that only rabid ignorants who have no
desire to listen to anyone other than the voices in their head. You
really made it clear that you lack the ability to express yourself in
English, but when you resort to the kind of low-level idiocy you do, all
hope is lost that you will ever recover enough of your thinking ability
to get back on track.
Of _course_ Common Lisp does not match your wishes, Francois-Rene Rideau.
If it did, it would be a really stupidly designed language. I am happy
you were not around when things _were_ designed.
Incompetence on your scale should be punishable by law.
If you think you had some valid concerns about the language, back up and
do a better job of presenting them, unoccluded by your stupidity and
incompetence and your "wishes". I am quite sure you will find people
sympathetic to a number of language design issues when it comes to coding
stuff like MD5, but a good engineer knows when to use languages that are
better for some particular tasks than others. Bad engineers should just
be encouraged to become better at what they do, or to switch careers to
one in which they _could_ become good at what they do.
> The character issue is much worse: it's a *semantic* problem.
> It might not be in the speed bottleneck of this particular code
> (still, a typical character-based application doing MD5 in *portable*
> Common LISP would have a least 4 or 5 layers of buffers, just in the
> LISP side -- which does slow things down). But it's a major PITA to
> code around this nasty abstraction inversion.
md5 is defined on a stream of octets. You should calculate it at that
level. That later on that stream of octets is converted into something
with meaning at a higher level, such as characters in a certain
encoding, is neither relevant nor an abstraction inversion.
Francois-Rene> Lieven Marchand <m...@wyrd.be> writes:
>> You've done the work on md5 and I haven't so this is guess work,
>> but my first thought where the problem would lie is that a lot of these
>> algorithms assume efficient 32 bit operations, which in CL will cons.
Francois-Rene> Indeed, the *performance* problem is lack of efficient modular integer
Francois-Rene> operations, with all the consing, unconsing, size-checking, etc.,
Francois-Rene> that goes with it.
Well, you can get rid of the consing size-checking, etc., by doing, as
Erik says, 16-bit chunks.
Or lie to the compiler so that your function
(defsubst ub32-add/2 (x y)
"Return 32-bit modular sum of 32-bit integers X and Y."
(declare (type ub32 x y))
(enforce-ub32 (+ x y)))
becomes something like
(defun ub32-add/2 (x y)
(declare (type ub32 x y))
(the ub32 (+ x y)))
With the right speed and safety, this will probably be converted to a
single 32-bit add instruction, which is what you wanted.
For 16-bit chunks, something like the following might work (barely
untested):
(defun ub32-add/2 (x y)
(declare (type (unsigned-byte 32) x y) (optimize speed (safety 0)))
(let* ((lo-x (logand x #xffff))
(hi-x (logand (ash x -16) #xffff))
(lo-y (logand y #xffff))
(hi-y (logand (ash y -16) #xffff))
(lo-sum (+ lo-x lo-y))
(hi-sum (+ hi-x hi-y)))
(declare (type (unsigned-byte 17) lo-sum hi-sum))
(when (> lo-sum #xffff)
(setf lo-sum (logand lo-sum #xffff))
(incf hi-sum 1))
(logior (ash (logand hi-sum #xffff) 16)
lo-sum)))
This shouldn't cons except for the result and probably runs faster
than what you have because it doesn't have to call out to a generic +
routine.
Ray
That said, the remark I made "I was looking for a Common LISP implementation
of MD5, but found none" just was context, not a reproach to you or to anyone.
You seem to be looking for things to argue over.
> It is not an implementation in Common Lisp, but written in C as a
> low-level system function.
I was imprecise in my phrasing. I meant "implementation available to
Common LISP programmers". This was indeed not enough to satisfy my standards
(and even less so considering that this implementation is not available to
me but for testing purposes). I suppose I could have also written a FFI to C
for CMUCL or CLISP, but I didn't feel like doing both of it, and wanted
my code to run on both, as well as on Genera, ThinLisp, etc. In other words,
I purported to support the (maybe illusive) idea that there is a usable
portable Common LISP language.
[Skipped ad-hominem attacks]
> You really need to clue in that MD5 does not operate on characters.
Who said it did? (actually, the ACL6 interface does, but that's why
I extended it to work on octets arrays, too). Still, it operates on
streams that I also have to interpret as characters, in a different
context (notably so as to use, e.g. WRITE, FORMAT, and all those text
processing libraries). CL forces me to do double buffering (actually,
treble, or more), which sucks because of coding nightmares even more
than for the slowness.
> That some languages have no idea what a character is, but treat it like a
> small integer is really not something you can blame either MD5 or Common
> Lisp for.
I actually don't blame languages that treat characters as small integers.
They provide limited functionality indeed, but at least, they provide
some functionality you can portably build upon.
I do blame CL for providing an implementation-dependent notion of character
that is both too low-level to portably do any interesting thing with it,
and too high-level to allow for portable interaction with standard low-level
protocols.
> creating a new stream class that reads from those 64-byte buffers
> that you read from the input source and give to MD5.
Sure. That's why I was talking about double, treble, whatever, buffering,
which is overhead in programming time as well as in running time and space,
and qualifying that as "clumsy, inefficient, not portable, and
underspecified".
> | Once again, reading their specification, I happen to like the recent
> | things done by Franz (SIMPLE-STREAM), but it's unhappily not directly
> | applicable to me.
>
> Well, what makes it impossible for you to take their good ideas and
> implement them on your own?
>
Sure I can. (Well, someone else seems to be doing that for CMUCL).
However, so it would be no more portable CL, and so that it remains
"ported CL", I'd have to do it on each of the implementations I use
(although most of it could hopefully be done in portable CL).
> but for MD5, just break the 32-bit integers in half and operate on 16-bit
> values, instead.
Yes, I have thought about this. However, I began with 32-bit because it
was more natural, and hoped CMUCL could do well with it. It could do better.
I was happy enough with the implementation so as to decide to publish it
before to optimize it, if I ever do it (but then instead of writing ugly
implementation-specific LISP - some of my friends call that "bugware" -
I'd rather write efficient assembly and FFI code, and/or develop
a special-purpose subLISP compiler that would do that for me).
> I assure you that no significant performance loss is caused by this,
Thanks for the tip.
> and the algorithm does not increase in complexity because of it.
Sure, but the discussion matters only if we're already into constant factors.
> | I consider it bad practice to post large code files on USENET.
> Well, if your MD5 function is a large code file, then you have even more
> problems.
It is small by for a code file (700 lines, including lots of comments),
but I consider it large and noisy by USENET post standards.
> There is no way to ascertain that what is pointed to by a URL will remain
> the same after it has been criticized. We have seen how some massively
> dishonest _frauds_ on this newsgroup have altered the text of published
> URLs (even without updating the version) in order to make their critics
> look bad. Post the code and it will be very hard to "update" it.
>
Wow, you seem have really low expectations about people, at least on USENET.
Well, if this is the kind of things you fear, I have no shame posting the
MD5 of my current CVS release 1.8:
dd512185e07d1aeeab11454568eb14e9 md5.lisp
Unless I can break MD5, or modify bits on every USENET archive, there is no
way I can now retract my code. The file I had when I originally posted was not
yet on CVS, and I didn't keep a copy (one of the tens of people who downloaded
might have it), but apart from a few type declarations, added documentation
and reordering of definitions, it is essentially the same as the current one.
Notice that now that the code is on CVS, you can browse old versions at any
moment - so even in a year, you can check that the MD5 is the one I said.
http://tunes.org/cgi-bin/cvsweb/fare/fare/lisp/md5.lisp
> I find it rather odd that you cannot destill your problems down to a few
> simple cases.
Here's my problem #1 in a simple case: (ub32-add x y z)
Here's my problem #2 in a simple case: (char-code c)
Sometimes, the few paragraphs of explanation is as simple as it can get.
> A good bug report contains a destilled example.
Words are a good vector for distilled ideas.
> A bad bug report contains a million lines of rotten code [...]
Which is another reason why I chose not to post my code on USENET.
> with a single line "this code is perfect,
> but your compiler does not conform to my wishes".
My code is not perfect, and part of the reason it isn't
is that the language has deficiencies.
> | > | The world has standardized on low-level byte streams as the universal
> | > | medium for communication of data, including text.
> | > Which is a mistake, since they run into an enormous amount of trouble
> | > with supporting more than one character encoding.
> | It is not a mistake - it is the natural thing to do in a world of
> | proprietary black-box devices and software.
>
> Huh? You have a special knack for non sequiturs. TEXT IS NOT BYTES.
You have a knack for straw man arguments.
Of course, text is not bytes. The point is, it is easy to agree on bytes,
and impossible to agree on text. Since "binary-compatible" proprietary
software and hardware cannot be mended after-the-fact to account for
a moving low-level extensional representation for the high-level intentional
agreement on what text is, proprietary vendors can but standardize on
low-level protocols. So once again, of course, text is not bytes.
But any world-standard protocol for communicating text will be based on bytes.
> Really? Tell you what, when I wrote my MD5 functions for Allegro CL 5.0,
> I stuffed it between the I/O system and the reader, and I reset and grab
> the md5 hashes while reading characters from the stream. If I can do
> this in Allegro CL, so can you in CMUCL.
Sure I can. But I don't want to do it for CMUCL, SBCL, CLISP, Genera, ACL,
ThinLisp, and every other implementation. In other words, if I pick one
implementation and stick to it, I'd be fine - but then, so would I picking
a Scheme implementation, OCAML, or a system
> If you need precise control, ask for it. Your system does _not_ do a lot
> of weird magic that you have no control over. Just trust me on this, OK?
Sure. But each system does its own non-weird magic, in an incompatible way.
That's called non-portability. I'm not criticizing ACL, CMUCL, CLISP, Genera,
or anything - each does its stuff correctly. I'm just criticizing CL,
and there unhappily seems to be no one to ask about fixing that.
(Well, actually, raising the problem in c.l.l will hopefully attract the
attention of implementers on the problem and its known solutions,
so they might provide efficient APIs to multivalent strings/streams
and modular integer operations).
> You have to get at the bytes where they are
> actually found, just after they have been read, and just before they are
> written. Anything else is pretty damn stupid.
Sure. Who said otherwise? This just means more buffering to handle
(costs development, performance, space, semantic gap, etc.)
Actually, it calls for doing everything with bytes, and nothing with
characters (unless wrapped in a macro for immediate conversion), in
any portable program sensitive to such problems -- except that this
precludes the use of many text-processing libraries, which is
the abstraction inversion.
> | > if you are dealing with text, you deal with characters, not their
> | > coding,
> | Not even. I could be dealing with words, with sentences, with layout
> | elements. In such contexts, characters are too low-level and not what I
> | like.
> I am sure you think this is relevant to something. Could you try to make
> it a bit more clear what it is might be relevant to? No, never mind.
>
Your claim all throughout was that text-processing was not about bytes.
Well, it isn't about characters either, you know.
For instance, I am currently writing a small lisp program that dumps
annotated diagrams in LaTeX+MetaPost, which can be considered text-processing,
and, mind you, nowhere in it does the concept of character even appear.
Does that mean that a language ought to not standardize on characters,
since they are NEVER an interesting human-level concept, and instead,
standardize on TeX-style glyphs and graphic or symbolic structures? No.
Languages should standardize on bricks with which to build applications.
Bytes are a sensible such brick, especially in a world that talks in bytes.
Characters are not such a brick, and never will be in any world.
Having characters as an *extra* feature is good. Making it so they divert
programming efforts in a hell of portability problems is bad.
> a good engineer knows when to use languages that are better
> for some particular tasks than others.
Sure. No question that. However, when a same application requires many
different tasks, and interfacing languages incurs both programming overhead
and portability issues, you will see good engineers pushing languages
into solving tasks for which they are not the best suited.
Yours freely,
[ François-René ÐVB Rideau | Reflection&Cybernethics | http://fare.tunes.org ]
[ TUNES project for a Free Reflective Computing System | http://tunes.org ]
The fundamental class division in any society is not between rich and poor, or
between farmers and city dwellers, but between tax payers and tax consumers.
-- David Boaz, CATO Institute
> >>>>> "Francois-Rene" == Francois-Rene Rideau <fare+...@tunes.org> writes:
>
> Francois-Rene> Lieven Marchand <m...@wyrd.be> writes:
> >> You've done the work on md5 and I haven't so this is guess work,
> >> but my first thought where the problem would lie is that a lot of these
> >> algorithms assume efficient 32 bit operations, which in CL will cons.
> Francois-Rene> Indeed, the *performance* problem is lack of efficient modular integer
> Francois-Rene> operations, with all the consing, unconsing, size-checking, etc.,
> Francois-Rene> that goes with it.
>
> Well, you can get rid of the consing size-checking, etc., by doing, as
> Erik says, 16-bit chunks.
>
> Or lie to the compiler so that your function
>
> (defsubst ub32-add/2 (x y)
> "Return 32-bit modular sum of 32-bit integers X and Y."
> (declare (type ub32 x y))
> (enforce-ub32 (+ x y)))
>
> becomes something like
>
> (defun ub32-add/2 (x y)
> (declare (type ub32 x y))
> (the ub32 (+ x y)))
>
> With the right speed and safety, this will probably be converted to a
> single 32-bit add instruction, which is what you wanted.
Probably not. The commercial lisps generally use two or three low
bits as a tag (and set them to zero), so although the compiler may
emit a 32-bit add instruction, it is really performing a 29 bit add.
> For 16-bit chunks, something like the following might work (barely
> untested):
>
> (defun ub32-add/2 (x y)
> (declare (type (unsigned-byte 32) x y) (optimize speed (safety 0)))
> (let* ((lo-x (logand x #xffff))
> (hi-x (logand (ash x -16) #xffff))
> (lo-y (logand y #xffff))
> (hi-y (logand (ash y -16) #xffff))
> (lo-sum (+ lo-x lo-y))
> (hi-sum (+ hi-x hi-y)))
> (declare (type (unsigned-byte 17) lo-sum hi-sum))
> (when (> lo-sum #xffff)
> (setf lo-sum (logand lo-sum #xffff))
> (incf hi-sum 1))
> (logior (ash (logand hi-sum #xffff) 16)
> lo-sum)))
>
> This shouldn't cons except for the result and probably runs faster
> than what you have because it doesn't have to call out to a generic +
> routine.
The problem is that an (unsigned-byte 32) won't fit in a boxed value
on a 32-bit machine. Your ub32-add/2 will cons a bignum when you ash
the high sum by 16 bits.
Francois-Rene Rideau <fare+...@tunes.org> writes:
...
> [ François-René ÐVB Rideau | Reflection&Cybernethics | http://fare.tunes.org ]
> [ TUNES project for a Free Reflective Computing System | http://tunes.org ]
> The fundamental class division in any society is not between rich and poor, or
> between farmers and city dwellers, but between tax payers and tax consumers.
> -- David Boaz, CATO Institute
Ordinarily I refrain from making politics comments on c.l.l., but a
quote from somebody from the CATO institute merits at least a
sarcastic remark. Especially when such Think-Tank essentially work as
a pundit for the rich tax payers who do not want to pay taxes on
behalf of the poor tax consumers.
There! I said it!
Cheers
--
Marco Antoniotti ========================================================
NYU Courant Bioinformatics Group tel. +1 - 212 - 998 3488
719 Broadway 12th Floor fax +1 - 212 - 995 4122
New York, NY 10003, USA http://bioinformatics.cat.nyu.edu
"Hello New York! We'll do what we can!"
Bill Murray in `Ghostbusters'.
> Ordinarily I refrain from making politics comments on c.l.l., but a
> quote from somebody from the CATO institute merits at least a
> sarcastic remark. Especially when such Think-Tank essentially work
> as a pundit for the rich tax payers who do not want to pay taxes on
> behalf of the poor tax consumers.
> There! I said it!
That doesn't prevent it from being a reasonably pithy saying, and even
if all you suggest is true, doesn't prevent it from having some truth.
If there's a serious and persistent imbalance between the tax burdens
of different groups of people, that _will_ lead to divisiveness,
regardless of whether CATO folk are to be regarded for good or for
ill.
.. Which vaguely ties to Lisp what with the old quote about Lispers
knowing the value of everything, but the cost of nothing ...
--
(reverse (concatenate 'string "ac.notelrac.teneerf@" "454aa"))
http://www.cbbrowne.com/info/sap.html
Talk a lot, don't you?
What a coincidence! It happens that earlier today, I typed ``md5.lisp''
into Google and it came up with this:
http://www.ai.mit.edu/people/naha/ftp/Cryptography/
>So I wrote a silly port of MD5 in CL.
> ftp://Samaris.tunes.org/pub/lang/cl/fare/md5.lisp
>On CMUCL, the result runs about 5.5 times slower than the equivalent optimized
>C code; that said, on CMUCL, it can also call the external md5sum utility
By the way, is this C code maximally portable ISO C? Let's see it.
>for fast processing of large files or streams.
>It purports to abide by (and extend) the MD5 interface defined in ACL6.
>
>Excellent things that helped: CL macros.
>Horrible things that get in the way: CL characters,
>and lack of builtin modular operators.
What modular operators are missing? The standard truncate function returns
an integer quotient and remainder. The logand function can be used
as a means of reduce modulo a power of two: (logand #xABCD #xFF) ==> #xCD
Looking at your code, I think I understand what you mean. In some places
in the computation, it's necessary to reduce a result modulo #x100000000.
This is because the algorithm is defined in terms of machine arithmetic,
specifically to be efficiently impementable in machine languages.
Note that a C program which assumes the presence of a type that is
exactly 32 bits wide is not maximally portable, so if you rely on
the addition of two unsigned longs, for instance, to do the
reduction for you, your code is not portable. In maximally portable
C, you have to do the & 0xFFFFFFFF operation to reduce a result
modulo 32 bits.
jrm> Raymond Toy <t...@rtp.ericsson.se> writes:
>>
>> (defun ub32-add/2 (x y)
>> (declare (type ub32 x y))
>> (the ub32 (+ x y)))
>>
>> With the right speed and safety, this will probably be converted to a
>> single 32-bit add instruction, which is what you wanted.
jrm> Probably not. The commercial lisps generally use two or three low
jrm> bits as a tag (and set them to zero), so although the compiler may
jrm> emit a 32-bit add instruction, it is really performing a 29 bit add.
Yes, this is true in general, but I'm assuming most commercial lisps
also support 32-bit integer types. That might not be true, and then
you are hosed. CMUCL does support 32-bit integer types so for
(defun foo (x y)
(declare (type (unsigned-byte 32) x y)
(optimize (speed 3) (safety 0)))
(the (unsigned-byte 32) (+ x y)))
You get something like
<stuff to get x and y into 32-bit integer form from possibly boxed values>
6B0: L1: MOV %NL1, %NL0
6B4: ADD %NL2, %NL0 ; No-arg-parsing entry point
<stuff to return this 32-bit result as a boxed answer>
>> This shouldn't cons except for the result and probably runs faster
>> than what you have because it doesn't have to call out to a generic +
>> routine.
jrm> The problem is that an (unsigned-byte 32) won't fit in a boxed value
jrm> on a 32-bit machine. Your ub32-add/2 will cons a bignum when you ash
jrm> the high sum by 16 bits.
With CMUCL, I'm pretty sure that the consing happens when it tries to
return the final 32-bit result. No consing happens for the 16-bit
shift of the high sum, because the compiler understands unboxed 32-bit
integers.
Ray
> By the way, is this C code maximally portable ISO C? Let's see it.
The md5.c file I had, a derivative of the reference implementation,
was the fairly portable one used in Erlang.
I don't remember if ISO C mandates two's complement arithmetics
(the earlier standard didn't; I remember rumors that this one does).
If it does, then it is maximally portable. If not, then indeed
it requires and'ing with 0xFFFFFFF (which in practice is optimized
away by all C compilers that matter).
That said, since the 1980's, 99.99% of the world have standardized
on hardware that does two-complement 8/16/32/64 bit arithmetics.
The only recent exception I know is Chuck Moore's F21
(20/21-bit two-complement architecture). Even an Ivory LISPM
has 32-bit fixnums. (Followup-To: comp.arch ?).
Moreover, various formal and informal standards that extend the ISO C
standard mandate 32-bit types. In other words, the world isn't just
the work of one committee - it's what everyone does.
Well, in the CL world, there is no more committee, and implementations
don't support any standard for modular arithmetics.
> What modular operators are missing? The standard truncate function returns
> an integer quotient and remainder. The logand function can be used
> as a means of reduce modulo a power of two: (logand #xABCD #xFF) ==> #xCD
Yes, and "I could also do the same even with a Turing machine".
The question was one of builtin support for efficient such operators.
[ François-René ÐVB Rideau | Reflection&Cybernethics | http://fare.tunes.org ]
[ TUNES project for a Free Reflective Computing System | http://tunes.org ]
"Sometimes it is said that man cannot be trusted with the government
of himself. Can he, then, be trusted with the government of others?
Or have we found angels in the forms of kings to govern him?
Let history answer this question."
-- Thomas Jefferson, First Inaugural Address
> | Once again, reading their specification, I happen to like the recent
> | things done by Franz (SIMPLE-STREAM), but it's unhappily not directly
> | applicable to me.
> Well, what makes it impossible for you to take their good ideas and
> implement them on your own?
Oh well, I guess it's a good time to announce that I'm implementing
simple-streams for CMUCL. It's far from usable as yet, but I'll put
something on http://www.actrix.gen.nz/users/mycroft/cl.html over the
weekend. If anyone wants to help out, please let me know.
--
The power of accurate observation is commonly called cynicism by those
who have not got it.
-- George Bernard Shaw
(setq reply-to
(concatenate 'string "Paul Foley " "<mycroft" '(#\@) "actrix.gen.nz>"))
No. Part of the reason I do not publish my code anymore is that there
are too many incompetents and assholes out there that I specifically do
_not_ want to get access to my work if they do not compensate me for it.
After all, you are whining and complaining and posting a bunch of crap
because you are unwilling to do the work on your own, so giving _you_
this code without any licensing terms seems like a really bad idea.
| You seem to be looking for things to argue over.
Wrong. For some people who think it is their birthright to be imprecise
and sloppy and disrespectful, being taken seriously and expected to be
precise is sometimes extremely provocative. You seem to be one of those.
| [Skipped ad-hominem attacks]
Well, gee, your own are apparently OK, while you have a problem with
mine. That kind of double standard _really_ annoys me. If you do not
want what you call ad hominem attacks (but you are still imprecise --
look it up), simply avoid them yourself -- if _you_ cannot do this or do
now _want_ to do it, shut the fuck up about what anyone else does, OK?
| I suppose I could have also written a FFI to C for CMUCL or CLISP, but I
| didn't feel like doing both of it, and wanted my code to run on both, as
| well as on Genera, ThinLisp, etc.
So design a common FFI framework! I have designed and implemented one
for my own needs, but I find the number of disgusting losers who would
benefit from it if I published my code to be too high. Sharing should be
rewarding, not felt as a loss. I choose to withhold what I do from the
public because of the number of assholes who would never respect my
rights as an owner, but fortunately, they are honest enough to scream
bloody murder if someone wants them to sign a license agreement.
Withholding from the general public is in fact the _only_ option an
author has in these days of "open source" and "free software". I find
that many of the problems people have are in fact solved in an hour or
two, but I have great fun solving problems for their own sake (and anyone
who enjoys mathematics knows what I mean), but the fun that used to be
found in seeing somebody else use my code vanished years ago with the
agressiveness of the demands of the consumers of open source and free
software -- there used to be a sense of gratitude and respect towards
those who solved your problems for you and gave you code, but this is
replaced by lazy fucks who demand that others solve their problems for
them and get pissed off if somebody else refuse to give them their work
for free. This gives me solid reason to believe that certain problems
are problems only to incompetents and it also gives me a good way to
determine if certain "problems" are posted by trolls who do not really
want a solution to them. There are lots of people on the Net who only
want to get sympathy for their plight, not actually solve their problems.
That kind of whining wimps tick me off, and if I can help one of them
lose their job or fail an exam by not answering their stupid requests for
somebody else's work, that is good!
| In other words, I purported to support the (maybe illusive) idea that
| there is a usable portable Common LISP language.
There is, and you have not been betrayed because you need to do some hard
work to get something you want. In fact, that sense of betrayal you feel
is that same irrational attitude problem that comes from believing in a
"perfection" that somebody else owes to you.
| > You really need to clue in that MD5 does not operate on characters.
| Who said it did?
You did, when you complained about the character concept.
| Still, it operates on streams that I also have to interpret as
| characters, in a different context (notably so as to use, e.g. WRITE,
| FORMAT, and all those text processing libraries).
Well, considering that I have actually done precisely the same thing and
did not have _any_ or your problems, what does that tell me about you?
Sometimes, the only problem _is_ the person, but you do not believe me,
and _stupidly_ think everything is an ad hominem attack. Clue in, dude,
an ad hominem attack is an attack on the arguments via the person, it is
_not_ an attack on the person for something that person does wrong.
Arguing tha you cannot trust someone because he has a bad credit record
is ad hominem, sending his unpaid bills to a collection agency is not.
Using the fact that somebody has been caught with a Swiss Army pocket
knife in Oslo against them in a debate over efficienty Java is ad
hominem, arguing that it was not particularly nice to lie to the police
about the reason he carried it so he would not get into serious trouble
is not. But because you are not very precise, you will probably not
understand this difference. So I do not argue that you cannot be trusted
or your arguments suck because you are not very precise or pay much
attention to detail -- I simply point out that you are imprecise and do
not pay much attention to detail, and then I expect you to _fix_ that,
but since you are that stupid antagonistic, imprecise dude who seems to
think that "you seem to be looking for things to argue over" is a much
better approach to the criticism, you will not quite grasp what you are
being told in any case. That kind of arrogance is something that those
who suffer from it will exhibit in many ways, and the belief that their
code is perfect (or any flaws somebody else's fault) goes with it.
| CL forces me to do double buffering (actually, treble, or more), which
| sucks because of coding nightmares even more than for the slowness.
No, the language does _not_ force you to do that, damnit. Your very own
incompetence and extremely annoying _arrogance_ forces you to do that.
Just be smarter. Think more, whine less, work better.
| > That some languages have no idea what a character is, but treat it
| > like a small integer is really not something you can blame either MD5
| > or Common Lisp for.
| I actually don't blame languages that treat characters as small integers.
Huh? Nobody said you did, either. Do you argue against straw men, now?
| I do blame CL for providing an implementation-dependent notion of
| character that is both too low-level to portably do any interesting thing
| with it, and too high-level to allow for portable interaction with
| standard low-level protocols.
I think you need to explain your understanding of the character type,
because this sounds like the rantings of an incredibly incompetent person
who has not paid a lot of attention to detail in his life. The _fact_ is
that the implementation-dependent aspects of the character are precisely
those that manifest itself in the coding and representation which you
want to get access to directly. How you can fail to understand this is
truly amazing. I wonder when you were satisfied with your bogus belief
in "character flaw" as a good explanation for your problems. (If you
pardon the pun -- I simply could not resist. :)
| That's why I was talking about double, treble, whatever, buffering, which
| is overhead in programming time as well as in running time and space, and
| qualifying that as "clumsy, inefficient, not portable, and
| underspecified".
That is how you would implement them. Your implementation is only partly
a consequence of the language, and only a small part, because you have
contributed a lot more than the language has. I get really annoyed by
people who think that their algorithm and implementation is perfect and
if it does not work the way they want, it is somebody else's fault. You
are obviously that kind of person, and there is a serious flaw with your
thinking that you need to fix before you are willing and able to listen
to counter-arguments. As long as you protect your notion of perfect
implementation, you will never get anywhere.
| Sure I can. (Well, someone else seems to be doing that for CMUCL).
| However, so it would be no more portable CL, and so that it remains
| "ported CL", I'd have to do it on each of the implementations I use
| (although most of it could hopefully be done in portable CL).
Yes, it seems that you are one of those perennially dissatisfied people
who do not understand that the _only_ way you can arrive at portable
_interfaces_ to some common functionality is to write non-portable,
implementation-dependent code that implements them efficiently in a
particular Common Lisp system. In fact, I am frankly _stunned_ by the
lack of insight among people who want _both_ portable interfaces _and_
portable implementations of such interfaces. That is simply not how
things work. Common Lisp itself is a prime example: It is a supremely
portable language, yet requires massively implementation-dependent code
to implement correctly. Actually, it seems that it takes a particular
willingness to think things through that many people lack to figure out
that what comes out elegant and beautiful at the other end of a long
production line has been through a very _dirty_ process. Like, do you
think the factory that makes office furniture is as clean as the offices
their furniture is sold to, or that writing an elegant poem about love
and happiness did not require the usual incredible amount of pain that
getting a poem "right" requires? No, creating something beautiful takes
a lot of ugly, painful work. If you are not up to that, you really have
no business _demanding_ that other people do it for you, or complaining
that they have or do not. It is that demanding attitude that makes me
_not_ want to give people like you an easy way out of your problems.
| > but for MD5, just break the 32-bit integers in half and operate on 16-bit
| > values, instead.
| Yes, I have thought about this. However, I began with 32-bit because it
| was more natural, and hoped CMUCL could do well with it. It could do better.
| I was happy enough with the implementation so as to decide to publish it
| before to optimize it, if I ever do it (but then instead of writing ugly
| implementation-specific LISP - some of my friends call that "bugware" -
| I'd rather write efficient assembly and FFI code, and/or develop
| a special-purpose subLISP compiler that would do that for me).
Well, if you have friends like that, no wonder you have problems choosing
good engineering practices. Using implementation-specific things to
implement a common/standard interface to some functionality is not wrong,
it is in fact right, and a very good way to move forward and _get_ that
functionality, but if people do not want the functionality because they
cannot get it their perfect way, which it seems that the several Lisp
communities suffer from to a frighteningly high degree, they will not
_get_ that functionality, either.
| It is small by for a code file (700 lines, including lots of comments),
| but I consider it large and noisy by USENET post standards.
700 lines!? Geez. Using implementation-specific features in Allegro CL,
the core algorithm is 100 lines. Setting up and preparing for this short
and fast algorithm takes another 150 lines.
| My code is not perfect, and part of the reason it isn't is that the
| language has deficiencies.
You ridiculous idiot. You probably even _believe_ this bullshit.
| But I don't want to do it for CMUCL, SBCL, CLISP, Genera, ACL, ThinLisp,
| and every other implementation.
Have you ever wondered how all these implementations sprung into being
from nowhere when people like you do not want to implement things they
say they want? Ever wondered how all of this "free software" depends on
people's willingness to implement things that sometimes are _boring_ and
which some lazy fuck like yourself does not want to do?
| In other words, if I pick one implementation and stick to it, I'd be fine
| - but then, so would I picking a Scheme implementation, OCAML, or a system
It is not a question of picking one implementation and sticking with it,
but of actually using an implementation to get what you want. If you are
so inept that you cannot design and implement something with an interface
that does not expose the implementation-dependent features, that is not
the fault of any language. Whether to "stick with" an implementation is
an orthogonal issue to whether you use implementation-specific features.
If you want to make something really useful that needs to be portable or
the foundation for something portable, you will probably need to use some
implementation-specific features. If not, you could have done it fully
portably, right?
Then there is the issue of how _often_ you need to use such featuers to
implement common/standard things and how hard it is to do so. You seem
to believe that as soon as it is necessary to do something like this, you
have found a flaw in the language. This is fantastically misguided.
| But each system does its own non-weird magic, in an incompatible way.
| That's called non-portability.
If you use one implementation's internal stuff and expect it to work
elsewhere, yes, but it is the assumption that you can do that that is
flawed. If you use another implementation's internal stuff to provide
the same interface to the same functionality, you have done a good thing.
This is how smart programmers design both compatibility layers and pave
the ground for new standards.
| I'm just criticizing CL, and there unhappily seems to be no one to ask
| about fixing that. (Well, actually, raising the problem in c.l.l will
| hopefully attract the attention of implementers on the problem and its
| known solutions, so they might provide efficient APIs to multivalent
| strings/streams and modular integer operations).
So if I understand you right, you think it is perfectly OK for a vendor
to use internal, implementation-specific features to implement a common
or standard specification (or, in case you are not quite up that level of
quality, just fix things your way), that is perfectly OK, but if you do
it yourself, it is _not_ OK? Just _why_ is it that you cannot do this
yourself? What makes it so important to you that somebody else do the
dirty work that you do not want to do yourself?
| > You have to get at the bytes where they are actually found, just
| > after they have been read, and just before they are written.
| > Anything else is pretty damn stupid.
| Sure. Who said otherwise?
You have strongly implied "otherwise", you insuffable numbnut.
| This just means more buffering to handle (costs development, performance,
| space, semantic gap, etc.)
... and this is where you say it! This "more buffering" crap that _you_
think is necessary is in fact _not_ necessary for your particular needs.
As you well know, the MD5 algorithm uses 64-byte blocks and it does not
care one hoot where they are. If you use the _same_ buffer that you just
read data into from the external source, you can actually get at the raw
bytes _before_ they are interpreted as characters. This is not hard to
do. This is not even difficult. This is _not_ rocket science. All this
requires is that you are willing to study your implementation or talk to
the vendor and get at the underlying buffer. You are really annoying in
the way you keep thinking that no better solution than your own can exist.
| Actually, it calls for doing everything with bytes, and nothing with
| characters (unless wrapped in a macro for immediate conversion), in any
| portable program sensitive to such problems -- except that this precludes
| the use of many text-processing libraries, which is the abstraction
| inversion.
Wrong, you insufferable numbnut.
| Your claim all throughout was that text-processing was not about bytes.
| Well, it isn't about characters either, you know.
Sigh. Quit your stupid game-playing, will you?
I think you are no more than another stupid troll who will never be
satisfied no matter what anyone provides you with, and who will certainly
never do any decent work on your own to get what you claim to want.
But it might box the result when returning it, unless the function call
is inlined or declared in to return unboxed results. E.g., Allegro CL
offers a means to do this which is pretty intricate, but which yields
significant speed-ups in some applications. I have only seen it used,
not used it myself, but if this is an issue, do ask and investigate.
> Incompetence on your scale should be punishable by law.
You mean one like this?
> Carrying a Swiss Army pocket knife in Oslo, Norway, is a criminal offense.
;-)
--
/|_ .-----------------------.
,' .\ / | No to Imperialist war |
,--' _,' | Wage class war! |
/ / `-----------------------'
( -. |
| ) |
(`-. '--.)
`. )----'
> On Thu, 01 Nov 2001 15:30:22 GMT, Erik Naggum wrote:
>
> > | Once again, reading their specification, I happen to like the recent
> > | things done by Franz (SIMPLE-STREAM), but it's unhappily not directly
> > | applicable to me.
>
> > Well, what makes it impossible for you to take their good ideas and
> > implement them on your own?
>
> Oh well, I guess it's a good time to announce that I'm implementing
> simple-streams for CMUCL. It's far from usable as yet, but I'll put
> something on http://www.actrix.gen.nz/users/mycroft/cl.html over the
> weekend. If anyone wants to help out, please let me know.
Thanks, Paul, for stepping up to this task. Too bad we will just miss each
other while I am on vacation down-under. :-(
(Paul and I have been discussing his implementation over the past month or
so, and he has made very quick progress on it. He has had advance access
to our 6.1 streams document, and that is now available on our website. I
also have a chapter on encapsulation which should become available in
a new version of that document, once it has been massaged by our
docuentation expert. Look for the new version within a week.)
--
Duane Rettig Franz Inc. http://www.franz.com/ (www)
1995 University Ave Suite 275 Berkeley, CA 94704
Phone: (510) 548-3600; FAX: (510) 548-8253 du...@Franz.COM (internet)
Similarly, people who apply the GNU license to the programs don't want
assholes to take code and spin it into a proprietary program that carries
use restrictions, doesn't permit redistribution, has no source code and
so on. So you see, it boils down to your definition of ``asshole'',
which is generally a subjective specialization of ``someone who does
things I very strongly disapprove of''.
> | [Skipped ad-hominem attacks]
> Well, gee, your own are apparently OK, while you have a problem with
> mine. That kind of double standard _really_ annoys me.
I have tried hard not to make any such attack in the current thread.
I apologize if there is anything that could be construed as such in
my messages.
> So design a common FFI framework!
That's indeed a good idea of thing to do.
> I have designed and implemented one for my own needs,
> but I find the number of disgusting losers who would
> benefit from it if I published my code to be too high.
> Sharing should be rewarding, not felt as a loss.
It sure should be. I regret that you do not feel it is.
If you are only ready to help people better than yourself,
you'll find that the only people whom you accept to help
are those who don't need your help.
> if I can help one of them
> lose their job or fail an exam by not answering their stupid requests for
> somebody else's work, that is good!
I think your are wasting your precious time with them? Just ignore them.
You will thus do yourself (and them) a favor.
You seem to me to react like you take perfection as a granted ideal
such that ethical behaviour consists in destroying whatever is imperfect.
I think that that on the contrary, perfection is an unreached ideal
such that ethical behaviour consists in building more perfect things.
> | In other words, I purported to support the (maybe illusive) idea that
> | there is a usable portable Common LISP language.
> There is, and you have not been betrayed because you need to do some hard
> work to get something you want.
I do not feel "betrayed" - nobody owes me anything.
I feel like there is a room for improvement,
the perception of which can be usefully discussed
in such a community forum as comp.lang.lisp.
> Clue in, dude,
> an ad hominem attack is an attack on the arguments via the person, it is
> _not_ an attack on the person for something that person does wrong.
Granted. Whereas you are only very rude and quick to ignore or dismiss
arguments (rather than actually attack them) once you decided that
someone was a bad person.
> I simply point out that you are imprecise
And I thank you for it.
> and do not pay much attention to detail,
> and then I expect you to _fix_ that,
I will try to.
> | CL forces me to do double buffering (actually, treble, or more), which
> | sucks because of coding nightmares even more than for the slowness.
> No, the language does _not_ force you to do that, damnit.
Indeed, if I manage to avoid characters altogether (and thus not use any
character-based library), or else use non-portable extensions (and lose
some interoperability) I can avoid double-buffering. This is a worthwhile
engineering tradeoff to consider. But I argue that this is a current flaw
in the language.
> | > That some languages have no idea what a character is, but treat it
> | > like a small integer is really not something you can blame either MD5
> | > or Common Lisp for.
> | I actually don't blame languages that treat characters as small integers.
> Huh? Nobody said you did, either. Do you argue against straw men, now?
I didn't say you did. I tried to clarify and argue my opinion,
which from your post I construed to be opposite to yours.
> The _fact_ is that the implementation-dependent aspects of the
> character are precisely those that manifest itself in the coding
> and representation which you want to get access to directly.
No. I do not want to access implementation-dependent aspects of the character.
I want to access protocol-dependent aspects of the character, in an
implementation-independent way. Sometimes, the protocol and the
implementation agree, and then I like to be able to take advantage of it;
sometimes they do not, and I find it a pity that it makes reuse of
code designed to manipulate characters a nuisance.
> I get really annoyed by
> people who think that their algorithm and implementation is perfect and
> if it does not work the way they want, it is somebody else's fault. You
> are obviously that kind of person,
I know many flaws in my code (it notably does much more consing
that it should, which currently makes it very slow on big data -
but for big data I call /usr/bin/md5sum, anyway, so that's not
a bottleneck to me right now - on the other hand, the way I call an
external program might or not leak memory, which is not a concern to
me right now but might become in the future).
> the _only_ way you can arrive at portable
> _interfaces_ to some common functionality is to write non-portable,
> implementation-dependent code that implements them efficiently in a
> particular Common Lisp system.
Well, the fact that something implementation-dependent has to be done
for efficiency is precisely what an "abstraction inversion" is about
when you try to do it portably. I argue it's a flaw in a language;
a flaw that may be part of a valid engineering tradeoff in the
design and implementation of said language, but a flaw nonetheless.
A lot of useful code is written in LISP, C, C++, Java, OCAML, SML,
Python, Perl, etc., that is written in a portable way and provide
portable interfaces efficiently. But various languages have various flaws;
CL has a lot of interesting features that other languages have not,
it has also flaws that other languages have not; this means that the
potential non-portability issues or abstraction inversions come at
different places in various languages. Tradeoff? Maybe.
But it is interesting to discuss these tradeoffs.
> creating something beautiful takes a lot of ugly, painful work.
Indeed. But the pain is not the goal, the beauty is. Fruitful discussions
help determine how to achieve more beauty with less pain.
> Using implementation-specific things to
> implement a common/standard interface to some functionality is not wrong,
> it is in fact right,
Indeed. *Having to do it* is the wrong, and *doing it* is the right
that hopefully fixes that wrong. The cost of doing it is the measure of
the wrong. Better ways of doing it alleviate the wrong,
worse ways increase it. Discussing is a way to find better ways.
> 700 lines!? Geez. Using implementation-specific features in Allegro CL,
> the core algorithm is 100 lines. Setting up and preparing for this short
> and fast algorithm takes another 150 lines.
I get the approximate same code size. The rest is documentation, and
a collection of functions to portably mock up the implementation-specific
features you use, until each implementation has them. I also add lots of
declarations in an attempt to keep the CMUCL compiler happy.
> Have you ever wondered how all these implementations sprung into being
> from nowhere when people like you do not want to implement things they
> say they want?
Uh? My post was precisely about code I was publishing.
I admit I should be back to coding -- wasted more than enough time
posting on USENET.
> Ever wondered how all of this "free software" depends on
> people's willingness to implement things that sometimes are _boring_ and
> which some lazy fuck like yourself does not want to do?
It's not boring when it's the Right Thing(tm)
(or rather, the joy overcomes the bore).
> It is not a question of picking one implementation and sticking with it,
> but of actually using an implementation to get what you want.
Maybe you should explain the difference.
> interface that does not expose the implementation-dependent features
In the case of modular integers that's easy.
In the case of doing the Right Thing(tm) with characters, that's difficult.
For other flaws in CL (modularity, concurrency, etc.),
I doubt it is possible.
> You seem to believe that as soon as it is necessary to do something
> like this, you have found a flaw in the language.
Yes. It might not be a big flaw (depending on what it is),
but it is a flaw nonetheless.
> | > You have to get at the bytes where they are actually found, just
> | > after they have been read, and just before they are written.
> | > Anything else is pretty damn stupid.
> | Sure. Who said otherwise?
> [...] You have strongly implied "otherwise", you insuffable numbnut.
In as much as I might not always be precise enough in what I say,
you read everything with negative prejudice and then become rude.
> [...] All this requires is that you are willing to study your
> implementation or talk to the vendor and get at the underlying buffer.
"All this requires" for a portable program is thus a lot of work in each
implementation to achieve desired functionality efficiently.
So this particular flaw is fixable (and being fixed, it seems).
It's still a flaw.
Back to coding,
[ François-René ÐVB Rideau | Reflection&Cybernethics | http://fare.tunes.org ]
[ TUNES project for a Free Reflective Computing System | http://tunes.org ]
I made it a rule to forbear all direct contradictions to the sentiments of
others, and all positive assertion of my own. I even forbade myself the use
of every word or expression in the language that imported a fixed opinion,
such as "certainly", "undoubtedly", etc. I adopted instead of them "I
conceive", "I apprehend", or "I imagine" a thing to be so or so; or "so it
appears to me at present".
When another asserted something that I thought an error, I denied myself the
pleasure of contradicting him abruptly, and of showing him immediately some
absurdity in his proposition. In answering I began by observing that in
certain cases or circumstances his opinion would be right, but in the present
case there appeared or semed to me some difference, etc.
I soon found the advantage of this change in my manner; the conversations I
engaged in went on more pleasantly. The modest way in which I proposed my
opinions procured them a readier reception and less contradiction. I had
less mortification when I was found to be in the wrong, and I more easily
prevailed with others to give up their mistakes and join with me when I
happened to be in the right.
-- Autobiography of Benjamin Franklin
> Indeed, if I manage to avoid characters altogether (and thus not use
> any character-based library), or else use non-portable extensions
> (and lose some interoperability) I can avoid double-buffering. This
> is a worthwhile engineering tradeoff to consider. But I argue that
> this is a current flaw in the language.
No, this seems rather more like a misunderstanding on your part.
You're half understanding that using characters is a Bad Idea; you
have to get the rest of the way, and conclude that using characters is
not only a Bad Idea, but also pointless.
--
(concatenate 'string "aa454" "@freenet.carleton.ca")
http://www.cbbrowne.com/info/sap.html
"Oh, I've seen copies [of Linux Journal] around the terminal room at
The Labs." -- Dennis Ritchie
I think you have missed something here, Erik's position does not
encumber other people by not releasing his code and the gpl does place
oblagations on people(in theory, it has not been tested in court as
far as I know) of the type you must give me back/make avalable your
source code. There are several expences involved in this, here is a
short list:
1: you need to keep it avalible on the internet, you need to rent some
space & bandwitdth
2: you need to keep backups and keep track of them, for all versions
of your software that is encumbered with gpl, to the best of my
knoledge
3: if you fail to do 1 and 2 you could get sued by some one else and
draged through the legal system, always fun.
A quick aside look at freebsd getting turned into OS X. Apple did the
right thing (darwin) and kept parts closed source, which is there
right under the bsd licence.
Also the GPL does not realy hurt big companys, they see an idea they
have the resources to copy it with out touching the source. The
people the gpl hurts are small businesses that do not have the
resources to reimplement everything by denying them the ability to
recoup there investment and/or protect any trade secretes that are
used in their derived work. This hurts people who could use the
product and the businesses that could make them. I would even say it
hurts open source because it deprives them of a source of good
commericaly viable ideas to build projects around, producte with an
installed base give open source cloning projects a much better chance
at success.
One last thing, if I add enough value to get people to pay me money
even when there is a free version avalable, am I not entitled to the
fruits of my labor?
Good night
,arc
Well every time anyone posts a question or a request for help here
thea are asking Erik, among many others, for help. And he does know
his lisp and programing.
>
>> | [Skipped ad-hominem attacks]
>> Well, gee, your own are apparently OK, while you have a problem with
>> mine. That kind of double standard _really_ annoys me.
> I have tried hard not to make any such attack in the current thread.
> I apologize if there is anything that could be construed as such in
> my messages.
>
>> So design a common FFI framework!
> That's indeed a good idea of thing to do.
>
>> I have designed and implemented one for my own needs,
>> but I find the number of disgusting losers who would
>> benefit from it if I published my code to be too high.
>> Sharing should be rewarding, not felt as a loss.
> It sure should be. I regret that you do not feel it is.
> If you are only ready to help people better than yourself,
> you'll find that the only people whom you accept to help
> are those who don't need your help.
>
I think you mis read this, Erik is complaining about leaches. What I
read in his statment is that he has a big problem with people who not
only use his work with out being gracious about it but they demand
more work from him for free. A few mails like "buddy where is my
fuckking feature!!!" would piss me off royally. One thing that is
glossed over in open source is that the majority of people who can not
produce software are asking the small minority who can to do them a
BIG FAVOR but most of the end users act like it is a right, "where is
my applacation, I want it now". Now if we have a contracr or I work
for you or you are a customer of mine then that attatude might be
reasonable, but as a person who I no business relation ship asking me
to do something that they could not do them selves for free and then
giving me shit, go fuck yourself.
>> if I can help one of them
>> lose their job or fail an exam by not answering their stupid requests for
>> somebody else's work, that is good!
> I think your are wasting your precious time with them? Just ignore them.
> You will thus do yourself (and them) a favor.
> You seem to me to react like you take perfection as a granted ideal
> such that ethical behaviour consists in destroying whatever is imperfect.
> I think that that on the contrary, perfection is an unreached ideal
> such that ethical behaviour consists in building more perfect things.
>
Being intolerant of bad work encourages good work, no? So if a person
is intolerant of junk he is encouraging people to make the world a
better place. So Erik apears to be helping you along the road to
perfection, acording to your statement he is behaving in an ethical
manner.
Good night
marc
Erik> * Raymond Toy
Erik> | With the right speed and safety, this will probably be converted to a
Erik> | single 32-bit add instruction, which is what you wanted.
Erik> But it might box the result when returning it, unless the function call
Erik> is inlined or declared in to return unboxed results. E.g., Allegro CL
I was leaving that as an exercise for the reader. :-)
Ray
> Probably not. The commercial lisps generally use two or three low
> bits as a tag (and set them to zero), so although the compiler may
> emit a 32-bit add instruction, it is really performing a 29 bit add.
Doesn't Lucid Common Lisp have some way to pass unboxed 32 bit
integers between functions? I once asked JonL about this, and he said
something about the red and pink registers (which hold untagged and
potentially untagged values, respectively), but I never remembered the
whole story.
I dunno if you can use an unboxed register for passing return values.
Lucid Common Lisp doesn't poll for interrupts, so it has to be careful
managing the registers so that a GC can parse the processor state at
any time. Partitioning the registers into boxed and unboxed sets
makes this easier.
I don't know about Lucid/Liquid, but the original non-x86 ports of CMU
CL use the (common) register partitioning strategy, in order not to
confuse the GC when it occurs while unboxed values are being worked
on, which is needed inside functions, too. On x86 this strategy is
suboptimal, since the iA32 architecture is so starved for registers,
that partitioning would leed to constant loading and unloading of
registers. So CMU CL on x86 doesn't partition its register set, and
uses a conservative GC.
The ability to pass unboxed values across function calls OTOH requires
something else: The receiving site needs to know to expect an unboxed
value (either in an unboxed register, or inside the normal registers,
if there is no partitioning), and the function itself must know that
all possible receiving sites can handle that unboxed value. Unless
you can pass the information "value is unboxed" dynamically to a
receiving site, and all receiving sites the implementation produces
are able to deal with this (which will introduce quite a bit of
overhead into function calls everywhere, for little gain), you need
some closed-world assumption, i.e. either all receiving sites must be
known at compile-time, or it must be ensured that all receiving sites,
including future receiving sites are capable of dealing with an
unboxed value return.
There are various ways of achieving that closed world. Inlining is
one obvious candidate. Another possibility is folding all cooperating
functions into one flet/labels form, from which no closures escape.
CMU CL allows a nice syntax for this via its block-compilation
declarations, which allows certain functions in the block to be
declared as external entry points, and all other functions as purely
internal functions. I.e. in the following code, only the return value
of baz needs to be returned re-boxed, all other values can be passed
around in unboxed form:
(declaim (optimize (speed 3) (debug 0) (space 0) (safety 0)))
(declaim (start-block baz))
(declaim (type (function ((unsigned-byte 32)) (unsigned-byte 32)) foo bar))
(defun foo (x)
(declare (type (unsigned-byte 32) x))
(logxor x #xF1F1F1F1))
(defun bar (x)
(declare (type (unsigned-byte 32) x))
(logxor #x7E7E7E7E (foo x)))
(defun baz (x y)
(declare (type fixnum x y))
(bar (+ x y)))
(declaim (end-block))
Other implementations provide other ways of "closing the world", in
order to allow optimizations like unboxed argument/result passing to
happen.
Regs, Pierre.
--
Pierre R. Mai <pm...@acm.org> http://www.pmsf.de/pmai/
The most likely way for the world to be destroyed, most experts agree,
is by accident. That's where we come in; we're computer professionals.
We cause accidents. -- Nathaniel Borenstein
> * Raymond Toy
> | With the right speed and safety, this will probably be converted to a
> | single 32-bit add instruction, which is what you wanted.
>
> But it might box the result when returning it, unless the function call
> is inlined or declared in to return unboxed results. E.g., Allegro CL
> offers a means to do this which is pretty intricate, but which yields
> significant speed-ups in some applications. I have only seen it used,
> not used it myself, but if this is an issue, do ask and investigate.
I agree; a user should ask and investigate.
However, there is a subtle snag here; Raymond's example uses
(unsigned-byte 32) values, and Allegro CL only does unboxed arithmetic
on (signed-byte 32). This isn't a big problem for someone who knows
how to use signed values as if they are unsigned values (i.e. the most
negative 32-bit number, when converted, looks like #x80000000, and the
machine integer representation for -1 in unboxed (signed-byte 32)
representation becomes #xffffffff.
But why only one choice? Why not allow both (signed-byte 32) _and_
(unsigned-byte 32)? The problem is in the range overlap in deciding
the type upgrade.
Background:
The compiler always tries to do regular boxed arithmetic whenever
the types assigned to calculations are within fixnum range, because
that is still most efficient. If the fixnum range is exceeded, but
the calculation remains within the "unboxed integer" range, then most
of the calculation can be done efficiently, but the final result must
be "boxed" by testing for fixnum and either shifting (for values in
fixnum range) or boxing into a bignum (for values too large for
a fixnum). We use a runtime primitive called fixnum-or-bignum
to do this. The final type upgrade is when the range of the calculation
exceeds even this unboxed integer range, and thus the compiler has to
generate generic code (in the generic sense, not in the CLOS sense).
In summary, there are three integer gradations: fixnum, then unboxed, and
then generic.
So consider the following function:
(deftype positive-fixnum () '(mod #.most-positive-fixnum))
(defun foo (x y)
(declare (optimize speed) (positive-fixnum x y))
(+ x y 10))
Each variable has a declaration of positive-fixnum, or in
normalized form: (integer 0 #.most-positive-fixnum).
There can actually be two additions implied here, but because
addition is associative I'll only describe the final calculation
result, which can be given a type of
(integer 10 #.(+ (* most-positive-fixnum 2) 10))
Now, the above type does not fall within the fixnum range, so it must
be upgraded. Question: does it fall within (unsigned-byte 32) range,
or (signed-byte 32) range? Answer: Yes!
This ambiguity would cause extra work for the compiler, to keep
track of what choice it has made, or to possibly keep two possible
compilation strategies, so as to know how to box the final result,
either using fixnum-or-bignum, or using unsigned-fixnum-or-bignum
instead. It should be possible to do this, but we chose not to,
because that would have made such compilations much more complex, and
introduced many possible bugs. Also, the decision to only track one
type allowed us to use the same unboxed-compilation mechanism
as we use for doing unboxed floating-point values. It also allowed us
to encode some of the low-level bit patterns representing gc states
into two-bit patterns, with four states each (lisp-value, single-float,
double-float, and (signed) machine-integer). This is useful for our
immediate-args concept, where unboxed arguments can be passed between
lisp funxtions.
Whether we made a correct decision to choose (signed-byte 32) over
(unsigned-byte 32) is debatable; I have little hard data, and only
a general sense, but I believe that the pros and cons are relatively
balanced; on the one hand, the obvious inadequacy of our choice is
that foreign interface communications are slightly harder to make
efficient (although since a 32-bit C compiler doesn't know the
difference between receiving an int or an unsigned int as an argument,
one could just lie to the foreign interface)
but on the other hand, most people don't create unsigned positive-fixnum
types, and instead tend to work with fixnum type declarations whenever
they want to say "this is a small number". Since fixnum is a signed
type, we chose to stay with the signed version rather than the unsigned,
as a philosophical balance to match the fixnum type.
The conclusion is the same as the start: a user should ask and
investigate.
> I think you have missed something here, Erik's position does not
> encumber other people by not releasing his code and the gpl does place
> oblagations on people(in theory, it has not been tested in court as far
> as I know) of the type you must give me back/make avalable your source
Lest you think that the fact that the GPL hasn't been tested in court
somehow makes it legally shaky, you might be interested in
http://www.gnu.org/philosophy/enforcing-gpl.html. In that article the
FSF's legal counsel argues that the GPL hasn't been tested in court
precisely because it is solid, potential GPL violators understand that, and don't
want to lose in court.
> code. There are several expences involved in this, here is a short
> list:
> 1: you need to keep it avalible on the internet, you need to rent some
> space & bandwitdth
> 2: you need to keep backups and keep track of them, for all versions of
> your software that is encumbered with gpl, to the best of my knoledge
> 3: if you fail to do 1 and 2 you could get sued by some one else and
> draged through the legal system, always fun. A quick aside look at
This is just silly. Maybe you're imagining a scenario in which you don't
provide the source along with binaries? If you really want to do that, you're allowed to
charge for providing the source if requested. I don't see anything in
the GPL that says you must provide the exact source that produced
whatever version an enduser has.
> One last thing, if I add enough value to get people to pay me money even
> when there is a free version avalable, am I not entitled to the fruits
> of my labor?
Sure, but not against the wishes of those who provided you the basis for
free.
Tim
first just because I dont want to go to court over it(spemd lots of
money and time) does not mean I think it is valid. Remember the FSF
has to defend ther GPL and its fellows because if they loose in court
it attacks there reason for existence. They loose there one big club.
And what else it the lawyer going to say, "this has wholes you could
drive a truck through" perhaps? He/she has a legal responability to
represent his clients best interests.
>> code. There are several expences involved in this, here is a short
>> list:
>> 1: you need to keep it avalible on the internet, you need to rent some
>> space & bandwitdth
>> 2: you need to keep backups and keep track of them, for all versions of
>> your software that is encumbered with gpl, to the best of my knoledge
>> 3: if you fail to do 1 and 2 you could get sued by some one else and
>> draged through the legal system, always fun. A quick aside look at
>
> This is just silly. Maybe you're imagining a scenario in which you don't
> provide the source along with binaries? If you really want to do
> that, you're allowed to
> charge for providing the source if requested. I don't see anything in
> the GPL that says you must provide the exact source that produced
> whatever version an enduser has.
I have to get in the source archiving busness for at least 3 years
from the date I stop developing to comply with the gpls licence if I
supply a binary package(rpm).
>
>> One last thing, if I add enough value to get people to pay me money even
>> when there is a free version avalable, am I not entitled to the fruits
>> of my labor?
>
> Sure, but not against the wishes of those who provided you the basis for
> free.
If they provided it to me for free then they would not have packaged
it with obligations that effect all my other work that comes in
contact with it. Since they did add this to there work by there
choice how can you call this free? There is definatly a charge
against me being made and the cost is linked to how much work I do
using gpled products.
>
> Tim
marc
I see. You think this all a game of insulting eachother the most.
| > | [Skipped ad-hominem attacks]
| > Well, gee, your own are apparently OK, while you have a problem with
| > mine. That kind of double standard _really_ annoys me.
| I have tried hard not to make any such attack in the current thread.
| I apologize if there is anything that could be construed as such in
| my messages.
Oh, for crying out loud, please quit the pathetic lying, you numbnut.
| If you are only ready to help people better than yourself,
Geez. Where did _this_ crap come from, numbnut?
| you'll find that the only people whom you accept to help are those who
| don't need your help.
Precisely. People who _need_ help should not get it for free. They
should pay for it. In an exchange of helpfulness where each party gives
help for free, the only "payment" one may get is that of having saved
someone else a little time who might save oneself a little time later on
in return. If you help people who _need_ to be helped, you do them a
major disservice -- you rob them of their only opportunity to learn by
working through some problem, you make them jump further than they should
and then they fill in the gaps with guesswork and assumptions that take a
lot of time to untangle, and they will keep asking for the same kind of
help over and over. Like that "ab talebi" numbnut.
| You seem to me to react like you take perfection as a granted ideal
| such that ethical behaviour consists in destroying whatever is imperfect.
Wrong. Striving for perfection I do take for granted. There are people
who do not want this and who strive for imperfection, instead.
| I think that that on the contrary, perfection is an unreached ideal
| such that ethical behaviour consists in building more perfect things.
You are too unware of your thinking processes to realize how it is _you_
who fail to live up to this.
| I do not feel "betrayed" - nobody owes me anything.
_Really_? Who do you think you are kidding? If the language is flawed
and other people should implement the things you "want", you spell it out
as betrayal and being owed something. It is pretty damn obvious.
| I feel like there is a room for improvement,
Yeah, right. "Flawed" means it is unusable as is, which you are also
quite explicit saying. "Improvement" means it is usable now and could be
more usable. The latter is _not_ your position.
| Whereas you are only very rude and quick to ignore or dismiss arguments
| (rather than actually attack them) once you decided that someone was a
| bad person.
Wrong, but you are both a bad person and incredibly unaware of your
thinking processes, so your arguments are also utter bunk.
| Indeed, if I manage to avoid characters altogether (and thus not use any
| character-based library), or else use non-portable extensions (and lose
| some interoperability) I can avoid double-buffering. This is a worthwhile
| engineering tradeoff to consider. But I argue that this is a current flaw
| in the language.
You keep saying that, and refuse to back it up with anything that has
been requested of you. I find this interesting. You also managed to
answer almost every paragraph in what I wrote, _except_ this one:
So if I understand you right, you think it is perfectly OK for a vendor
to use internal, implementation-specific features to implement a common
or standard specification (or, in case you are not quite up that level of
quality, just fix things your way), that is perfectly OK, but if you do
it yourself, it is _not_ OK? Just _why_ is it that you cannot do this
yourself? What makes it so important to you that somebody else do the
dirty work that you do not want to do yourself?
Why did you not respond this? Would it be too revealing if you did?
| I didn't say you did. I tried to clarify and argue my opinion, which from
| your post I construed to be opposite to yours.
Oh, cut the crap! What is an "opposite opinion"? Are you really such a
numbnut that you cannot even see that there are many axes along which to
construe opposite positions here? All I say is that your stupid line
about the language being flawed is a load of crap and that your use of
characters in the MD5 algorithm is fantastically misguided, so you just
_have_ to run into problems, which you blame on the language instead of
your sorry excuse for a brain and your own incompetence at your task.
| I do not want to access implementation-dependent aspects of the
| character. I want to access protocol-dependent aspects of the character,
| in an implementation-independent way.
Numbnut.
| Sometimes, the protocol and the implementation agree, and then I like to
| be able to take advantage of it; sometimes they do not, and I find it a
| pity that it makes reuse of code designed to manipulate characters a
| nuisance.
So use the _bytes_, you insufferable numbnut.
| I know many flaws in my code (it notably does much more consing ...
Oh, christ! Are you really so stupid? Do you not even understand that
the issue here is the character type you complain about? Do you again
think that there is only one axis along which to move from worse to
better? How annoyingly stupid is it possible for somebody to be? Geez,
some people! Look, numbnut, it is your attitude that your use of the
character type for something it is clearly not suited for is perfect and
that the language is flawed because your code certainly cannot take any
improvement that is the problem, here. Your code is bogus, crappy, a
load of shit, a misconceptualization, an abstraction inversion, what have
you, and you are too incredibly incompetent to realize it. That is all.
| Well, the fact that something implementation-dependent has to be done for
| efficiency is precisely what an "abstraction inversion" is about when you
| try to do it portably.
Efficiency _is_ implementation-dependent, you insufferable numbnut.
| I argue it's a flaw in a language;
Yeah, you and that other doofus, whatshisname tail-call "elimination",
think the language is flawed because you numbnuts cannot figure out how
to write better code and have deeply rooted psychological problems with
doing what it takes to get what you want.
| A lot of useful code is written in LISP, C, C++, Java, OCAML, SML,
| Python, Perl, etc., that is written in a portable way and provide
| portable interfaces efficiently.
This is really, _really_ wrong, numbnut. These languages are only
portable across a very specific platform type: 32-bit machines. Give
them something else and they are no longer "portable" at all. Of course,
_you_ live in a world of only 32-bit hardware, but Common Lisp does not.
| Indeed. *Having to do it* is the wrong, and *doing it* is the right that
| hopefully fixes that wrong.
You do not _have_to_ do it, you numbnut. You choose to do it because you
want better efficiency, and you choose to do it your way because you are
incompetent and much too arrogant.
| > Have you ever wondered how all these implementations sprung into
| > being from nowhere when people like you do not want to implement
| > things they say they want?
| Uh? My post was precisely about code I was publishing.
Grow a brain, numbnut. Lots of people have done lots of implemenation-
specific work to make the world of supremely usable _portable_ Common
Lisp possible for you to complain about.
| I admit I should be back to coding -- wasted more than enough time
| posting on USENET.
Another stupid choice of yours.
| > It is not a question of picking one implementation and sticking with it,
| > but of actually using an implementation to get what you want.
| Maybe you should explain the difference.
Oh, please do not play worse of an idiot than you are! You can use
multiple implementations to their fullest without choosing one and
stikcing with it. How hard can this be to grasp, numbnut?
| > interface that does not expose the implementation-dependent features
| In the case of modular integers that's easy.
| In the case of doing the Right Thing(tm) with characters, that's difficult.
You are only seriously confused about what the Right Thing is, numbnut.
| For other flaws in CL (modularity, concurrency, etc.),
| I doubt it is possible.
Of course you do. You cannot even get simple type choices right.
| > You seem to believe that as soon as it is necessary to do something
| > like this, you have found a flaw in the language.
| Yes. It might not be a big flaw (depending on what it is),
| but it is a flaw nonetheless.
The flaw is located in your pathetic excuse for a brain, numbnut. It is
not in the language.
| In as much as I might not always be precise enough in what I say,
| you read everything with negative prejudice and then become rude.
A numbnut who resorts to "always", "never", "nothing" and "everything"
has lost his touch with reality and prefers a vastly simplified, hugely
exaggerated world which is much simpler for this limited brain capacity
to deal with. You are _obviously_ wrong. Stupid exaggerations always
are. I am rude to idiots, numbnuts, and arrogant ignorants like you.
| It's still a flaw.
Are you going to put that on yout tombstone when you leave us alone? It
seems that numbnuts like you who have to defend themselves when they are
wrong about something will go into a mental state where they will never
admit to being wrong and will continue to spout some idiotic nonsense
just to keep from admitting it. This seems to be a pretty common trait
in the entire "tunes" project, by the way.
Some people want so badly to be "right" that they never change their mind
once they have found something to believe and it is challenged. You are
of that type, it seems. Other people want so badly to be _right_ that
they change their mind as soon as what they believe is challenged and
proven wrong. Since you do not recognize that I am of that type, but
think I am just as stupid and narrow-minded as yourself, you have missed
every opportunity to learn from what I have told you, and that makes you
a fucking numbnut. Now, go away and keep believing your wrong things so
you can save face of whatever you numbnut types need to keep smiling.
While I may not agree with Francois-Rene Rideau's statements,
he definitely know how to argue his points like an adult.
Your response is childish however and is an embarrassment
to this forum.
Why do I even bring this up? Well I asked readers a
month or so ago that if they wanted to raise the
intellectual level of this forum that they should
speak up when something clearly anti-intellectual was
posted. Since this is not a moderated forum this is
the only way for posters to get feedback. Feedback
is important.
So I simply state that in my opinion that post
went overboard. Yes, this isn't the first such
post in the last month but I've been too busy lately
to stay current enough with this newsgroup to
give timely feedback on some of the other posts.
I have one question, when were you elected the group censor? I did
not vote for you or even see a ballot with your name on it.
If you have been reading this news group for a while one thing you
should relize by now is that Erik follows through. I do not know if
Erik will respond to this, but if he does he will finish it. I do not
think you will get your desired end you will not muzzle anybody who is
worth a dam with this junk. In fact this is an invatation to a
responce from Erik that you are preaching against. Then you will
respond and he will respond ... and you have a lot more of the
behavior that you preach against because of your direct action. This
is not what I consider smart. It almost looks like you are setting
your self up to set your self up as the innocent victim in this so you
can claim some false moral high ground in this.
In the worse case when you have a choice between assholes and censors
you should always choose assholes, they make better neighbors. I am
not saying Erik is an asshole, just to be clear.
marc
If you study how usenet works you'll learn that there are no
censors for an unmoderated newsgroup so your statement makes
no sense.
I'm sure that there exist postings that you would consider
unacceptable. For example someone might start posting
multi-megabyte CMU CL distributions. You might speak up
and say "hey, this is not the place for that kind of
posting". You would not be a censor. Nothing you could do
could stop the postings. You would merely be stating your opinion.
*Your* opinion is that I should not state my opinion about
posts I find juvenile. Fine. I accept that is your opinion.
Just don't bring up censorship. That makes no sense.
No kidding, look who it's from. Basically, you are having a pointless
disagreement with someone on Usenet over his literary style---his highly
consistent and predictable style, I might add, which was probably honed
by years of practice, and as such would require considerable undoing.
For all you know, he could be playing a character in order to deliberately
tick you off, and possibly be deriving pleasure from grating on your
nerves.
Also understand that some people find overboard postings extremely
entertaining, and would miss them dearly if some people's censorship
fantasies were realized.
This is (Ab)Usenet! If you want to read some non-offensive,
censored-to-hell, insipid forum, try AOL.
then why did you attempt to set your self up as a tin pot censor with
your moralistic garbage post? And you were trying to censor through
the applacation of social pressure. By posting your message you were
fisshing for support and trying to polarize comp.lang.lisp into the
"good guys" and the "bad guys", and you get to "lead" the "good guys"
against the "bad guys" in a moral crusade to cleans CLL, for the
greater good of course. And trying this tactic against Erik is just
moronic, yes this goes beyond stupid, unless you are just picking a
fight so you can form your group and chastise us offensive heathens
into line. That is still pretty stupid.
>
> I'm sure that there exist postings that you would consider
> unacceptable. For example someone might start posting
> multi-megabyte CMU CL distributions. You might speak up
> and say "hey, this is not the place for that kind of
> posting". You would not be a censor. Nothing you could do
> could stop the postings. You would merely be stating your opinion.
>
binaries go against the charter of this grouo, as far as I know
anyway and responces to posted messages do not. Again you amaze me
with your wonderful ability to compair apples to dog dropping. I am
sure *you* see the link, wether it is there or not.
> *Your* opinion is that I should not state my opinion about
> posts I find juvenile. Fine. I accept that is your opinion.
> Just don't bring up censorship. That makes no sense.
>
no my opinion is that I do not like assocating with liars and cheats
so will you please go away. If anybody is curious here is the archive
from google( sorry about the line break):
http://groups.google.com/groups?q=g:thl1251669294d&hl=en&selm=
87itf1a2fh.fsf_-_%40piracy.red-bean.com
marc
John Foderaro, can you _please_ shut up? Your contributions to this
forum are fantastically predictable, exceptionally boring, utterly
useless, nothing more than childish whining, all of them sorry, pathetic
attempts to take revenge over once having lost a debate over your very
silly IF* macro. If you really want to raise the intellectual level in
this newsgroup, _quit_ the idiotic holier-than-thou act and just _do_
what you profess that only _other_ people should do: Post intelligent
articles. I do not think you actually _can_ do that, anymore, which is
why you keep _whining_ instead of _doing_, and which is why _you_ chose
to become an uintelligent moralistic asshole when you were criticized for
being unable to argue your case properly. Attacking your critics does
not make _you_ more intelligent, any more than any of the other morons on
this newsgroup have come out of such attacks with the face actually
saved. And just like every other pathetic moralistic loser on USENET,
you crawl out of the woodwork when a discussion is basically over.
Grow up, John Foderaro. _You_ are still unable to deal with conflict in
a mature way and there is _nothing_ you can teach anyone in this area,
and your extremely annoying and pathetic attacks on me are getting old.
> Oh well, I guess it's a good time to announce that I'm implementing
> simple-streams for CMUCL. It's far from usable as yet, but I'll put
> something on http://www.actrix.gen.nz/users/mycroft/cl.html over the
> weekend. If anyone wants to help out, please let me know.
As promised, this is now available.
--
C/C++/Java/Perl/etc are for people who want to make things that work.
Common Lisp is for people who want to make things that don't break.
-- Erik Naggum
FR> I purported to support the (maybe illusive) idea that there is a usable
FR> portable Common LISP language.
It is most definitely possible to write portable Common Lisp code that
is efficient in one implementation. It is very difficult, and possibly
impossible, to write Common Lisp code that is portably efficient.
X3J13 have made a few half-hearted attempts to make it more likely
that common idioms will generate efficient code, most notably by
giving some guarantees on the fixnum range and by making it possible
to write array-frobbing code using fixnums.
I don't think there is any portable language that enables the writing
of portably efficient code.
Juliusz
MS> A few mails like "buddy where is my fuckking feature!!!" would
MS> piss me off royally.
An Emacs Lisp function that replies ``I am not currently interested in
commercial consulting'' does wonders. You'll never hear from them
again.
The problem (I find) is with nice people who submit code for inclusion
in a future version, and get offended when you refuse on stylistic grounds.
Juliusz
Well, try submitting something that uses standard if, when, unless, or
loop, to people who believe in a certain "Lisp Coding Standard" document
and get chided for using standard Common Lisp. It is certainly rejection
on stylistic grounds, but so irrational that future attempts to deal with
such people is tainted with an unanswered "why bother?". In many cases,
stylistic grounds are indeed irrational as seen from the receiver, and
the most rational thing in the world by the person arguing them, but it
is probably fair to assume that the submitter of a thus rejected patch is
in his right to consider the argument irrational, and probably the person
who argues with them. On the other hand, the inability to continue to
use a style that the code alrady uses may just be irrationally stubborn
or ignorant, but it depends a little on how the style evolved. If it is
the kind of style that deprecates standard features in favor of a bogus
"invention" of the writer, that writer is trying to build a community all
of his own, explicitly rejecting the community that the suggester would
like to belong to. I find such behavior offensive and good grounds never
again to submit code to such people. Fortunately, there are usually only
single individuals who are so beyond reach.
Do you think this is because of the implementations or the language? I
think it is because of the implementations and the lack of pressure from
their users to be (more) efficient.
If you write code that is explicit in all its assumptions, a compiler
_should_ be able to produce optimal machine code.
> * Juliusz Chroboczek
> | It is most definitely possible to write portable Common Lisp code that
> | is efficient in one implementation. It is very difficult, and possibly
> | impossible, to write Common Lisp code that is portably efficient.
>
> Do you think this is because of the implementations or the language? I
> think it is because of the implementations and the lack of pressure from
> their users to be (more) efficient.
I don't think this is always the case.
I'm consulting for a company right now that is using clisp a lot. It
seems to be quite efficient in many ways, but since it's byte
compiled, it's hard for it to be compared apples to apples with
non-byte-compiled implementations. Using a system-defined operator
means jumping to C code, which gets really optimized stuff that a user
just can't write (because whole point of the byte code interpreter is
that you can't get to the C level). So, for example, as nearly as I
can tell, a call to a standard CL string-manipulation operator ends up
enormously faster compared to an open-coded inline loop doing calls to
CHAR on carefully type-declared strings, not because it does anything
gross and awful with those calls but because unless the system
literally recognizes that what you are doing is an idiom for a
system-defined function, it can't go out-of-frame and write C code
(where the optimizations you expect could happen).
I think similar issues come up with cache and prefetch issues that may
make things below the abstraction level not visible. And with
vendor-specific OS-level facilities like threads that may (depending
on shallow/deep binding tradeoffs, just for example) optimize some things
at the expense of others. ("No free lunch.")
I ran into this problem in doing Fortran->Lisp translation
http://world.std.com/~pitman/Papers/Fortran-to-Lisp.html
and it effectively came down to the same: if the compiler is restricted
to working from a certain abstraction level up, anything that tickles
the layer below that is going to sometimes work unoptimally.
I think this is, at its core, the reason for Gabriel's "worse is better"
paper series.
> If you write code that is explicit in all its assumptions, a compiler
> _should_ be able to produce optimal machine code.
Some code is kept from being explicit.
Some virtual machines are kept from exploiting this.
Some facilities use "magic" (by which I mean things like the MP package
for multitasking, which can accomplish multiprocessing in CL but can't be
implemented in CL for lack of core functionality).
Erik Naggum:
EN> Well, try submitting something that uses standard if, when, unless, or
EN> loop, to people who believe in a certain "Lisp Coding Standard" document
EN> and get chided for using standard Common Lisp.
I was thinking of a person who rewrote a quick hack of mine in what he
described as ``clean and elegant object-oriented Perl.'' He got badly
offended when I refused to maintain his code, and suggested that he
may want to distribute it himself.
EN> that writer is trying to build a community all of his own,
EN> explicitly rejecting the community that the suggester would like
EN> to belong to.
Yes, I think that's a fair description. I explicitly reject the
community that believes in such a thing as ``clean and elegant
object-oriented Perl.''
Juliusz
Erik Naggum:
EN> Do you think this is because of the implementations or the language?
To a great extent, it is unavoidable in any portable language.
The difference, however, is that most modern implementations of, say,
C, are pretty much identical from the programmer's point of view. In
most cases, C code that is efficient under both gcc/x86 and
SunPro/Sparc will be efficient on all (modern) platforms.
On the other hand, there is much more variety in implementation
strategies for Common Lisp, which makes it much more difficult to
write code that is efficient ``often enough.'' Let alone the issue of
byte-compiled vs. native implementations (already mentioned by Kent),
there are the issues of (off the top of my head) shallow vs. deep
binding, buffered vs. unbuffered streams, size of fixnums, ability to
work on full-word integers, ability to use a ``known call convention''
for functions with a proclaimed type, implementation of catch/throw,
etc.
I hope we all agree that this liberty of implementation is a good
thing; but it means that, in practice, writing portably efficient CL
code is next to impossible. (I am emphatically not speaking of
portable CL code that is efficient in a single implementation.)
Juliusz
> It is most definitely possible to write portable Common Lisp code that
> is efficient in one implementation. It is very difficult, and possibly
> impossible, to write Common Lisp code that is portably efficient.
I think this is really misleading.
For certain kinds of code, in particular code that does a lot of
low-level bit-twiddling (such as MD5) or code that does a lot of heavy
numerical computation (such as atomic bomb simulations) it is probably
true. It may also be true for code that is very heavily I/O
dominated.
However for a large amount of code which spends its time doing more
typical pointer-chasing and structure manipulation, I think it is
quite possible to write code which is portably efficient in CL. Code
I write which is of this kind has typically fairly small variations
between implementations - perhaps a factor of two or so, not including
CLISP which can often lose badly to native-compiled implementations
(although it can do surpsigingly well). Profiling (on more than one
implementation) doesn't show any awful bottlenecks, and in human terms
performance is pretty good.
Now of course this could be because I write uniformly dreadful code
but machines are so quick it runs OK, but I think that it's not that
bad.
So I think that with some exceptions (and these exceptions are largely
present in any language: ask someone who writes atomic bomb
simulations for a living aout portability and it's quite informative)
it is very possible to write portable, efficient, CL.
--tim
one point, you are making no distinction between proper use of the
power available and the abuse of that power. There is a serious moral
issue here, should I use the power I have with restraint where it is
proper to do so and with due consideration for its impact on the
community as a whole or not. Should macros be used to expand the
language or fragment it.
marc
I think they should be used to transform destructuring lambda lists into
objects to be treated as forms that are substituted in place of the
macros.
In what way would this be any different a question if asked about functions
and not macros?
Every macro expands the language *and* fragments it.
There will be people who understand the macro and those
that don't. That's your fragmentation.
Adding the extended loop macro has fragmented the
Common Lisp community more than any other macro.
The people who use it write code that the people who
dislike it can't even read.
Was it morally wrong to add the extended loop macro
to Common Lisp?
I don't think so. Lisp is a language you can evolve
to suit your needs. When you write a macro or even
a function you separate people into those who
know and understand it and those that don't.
The Common Lisp community is not one giant brain
that learns things simultaneously. People must develop
things independently and put them out there for
Lisp to grow.
> In article <slrn9ultpf...@oscar.eng.cv.net>, ma...@oscar.eng.cv.net
> says...
>> Should macros be used to expand the
>> language or fragment it.
>>
>
>
> Every macro expands the language *and* fragments it.
> There will be people who understand the macro and those
> that don't. That's your fragmentation.
I think it simply fragments people into those who _use_ it
and those who don't _use_ it. It has nothing to do with "understanding"
since that would imply that there is one right thing (tm) where often
both ways are perfectly rational.
> Adding the extended loop macro has fragmented the
> Common Lisp community more than any other macro.
> The people who use it write code that the people who
> dislike it can't even read.
> Was it morally wrong to add the extended loop macro
> to Common Lisp?
>
> I don't think so. Lisp is a language you can evolve
> to suit your needs. When you write a macro or even
> a function you separate people into those who
> know and understand it and those that don't.
Yes I agree (besides of the repeated "understand" here).
I think the problem is not that macros (or whatever facility else)
fragment the community but more what follows from there. If both camps
can tolerate each others preferences all goes well - if one camp tries to
shut up the other camp by postulating them evil, dumb or simply "not
understanding ones" *then* the things stop being manageable.
I particularily like Common Lisp because it is a language that often chooses
to include multiple ways of thinking about something if no final consensus
has been reached. You are perfectly welcome to invent new things if you do
not try forcing others that _their_ approach is not permitted to use.
I _always_ hated people that are trying to _forbid_ me doing things the way
I liked it and I prefer not working with them anymore instead of being a
slave drone.
The irony is that in reality "intolerance" is intolerable. ;-)
ciao,
Jochen
But it is fairly unlikely that C code compiled for both IA32 and SPARC
will be "efficient" in the same way. If you optimize too much for one of
them, it is no longer "efficient" in the other.
I also wonder what "efficient" means to you, and how you determine when
you have achieved it. It is not an absolute term.
As for the use of byte-compiled implementations or code, I completely
fail to see what their impact on this discussion is. If you want your
code to be "efficient", whatever it means, you choose a natively-compiled
implementation, not a byte-code interpreter, so whatever efficiency
issues may be perturbed by the existence of a such an implementation
appear to me completely irrelevant to those who actually seek efficiency.
>
> I think it simply fragments people into those who _use_ it
> and those who don't _use_ it. It has nothing to do with "understanding"
> since that would imply that there is one right thing (tm) where often
> both ways are perfectly rational.
>
I meant 'understanding' in the most basic sense.
when you see
(with-slot-frobbers (x 'slota 'slotb)
...)
you will either know what with-slot-frobbers does
or you won't.
So this macro has divided the world into those who
understand with-slot-frobbers and those who don't (yet).
> I meant 'understanding' in the most basic sense.
Why are you quoting the word "in"?
(Ignore me. It was out-of-place and probably failed humor that belonged
in a different thread. ;-)
>then why did you attempt to set your self up as a tin pot censor with
>your moralistic garbage post?
You don't understand what the word "censor" means. A censor has the
power to edit, or prevent the publication of something he doesn't
approve of. John Foderaro has no such power, that's why he's telling you
that talk of "censorship" makes no sense. He's only expressing his
views. He thinks people should be less abusive. That's his opinion, but
it has no binding force, so it can't possibly be considered "censorship."
In article <slrn9u6rc...@oscar.eng.cv.net>,
ma...@oscar.eng.cv.net (Marc Spitzer) wrote:
>In the worse case when you have a choice between assholes and censors
>you should always choose assholes, they make better neighbors. I am
>not saying Erik is an asshole, just to be clear.
Well this is damning with faint praise if I ever saw it.
Raf
--
Raffael Cavallaro, Ph.D.
raf...@mediaone.net
I see your point the if* function would be an equaly bad idea, but
I don't think it would be possable for this to work as a function.
marc
> In article <sfwk7x1...@shell01.TheWorld.com>, Kent M Pitman wrote:
> ...
> > In what way would this be any different a question if asked about functions
> > and not macros?
> >
>
> I see your point the if* function would be an equaly bad idea, but
> I don't think it would be possable for this to work as a function.
It's not about that.
Forget how they're applied. In code, you see a lot of
(this (that (the-other)))
where this, that, and the-other are variously functions or macros.
The question of whether macros should expand the language [community]
or fragment it is no different sociologically than the question of
whether functions or even variables should. Every name you introduce
that is nonstandard risks dividing the community, but on balance adds
potential power to someone at the same time.
If you'd had a CAR*, we'd be fighting over that. It's not a macro issue.
The problem comes when some people (I think somewhat rightly) feel
that IF doesn't really add power, and so it divides the community for
nothing. We made CL in the believe that being standard was more
powerful than being uniquely right. The choices in CL aren't all
defensible as "uniquely right", but they were intended to appease the
CL community enough that we didn't waste time (as we used to in the
past) arguing whose LET to use (does it have tagbody or not, must I
init my variables, etc), whose backquote (does it do a full copy or
only an if-needed copy), etc. It was getting boring. So we nailed it
down. We're supposed to have moved beyond those things to new areas
to bicker about.
If a Common Lisp programmer insists on using C's standard library names
for his string functions instead of the standard Common Lisp ones _and_
argues that those who use the standard functions are nuts, I think there
would probably be the same kind of uniform rejection of this stupidity as
what appears to be building towards the limited IF* crowd, not primarily
because of the specific idiotic new "feature" that nobody needs or wants,
but because of the sheer irrationality of the whole endeavor and because
of the incredible _arrogance_ exuded by those who thus reject the whole
community they _pretend_ or may even helplessly _want_ to be members of,
but are in fact rejecting completely. It is that initial rejection of
the community, the pretentious arrogance of one who thinks he knows so
much better than everybody else, and the holier-than-thou attitude when
criticized that comes from both of the former attitude problems, that
_really_ ticks people off. It is no longer about some stupid invention
of a macro or a function or a new sub-language, it is about the lack of
willingness to yield in traffic as opposed to a willingness to run into
people on purpose because one thinks one is a superior to others -- it is
the _exact_ same process that makes people become criminals.
It is actually a good thing to have lots of people argue vociferiously
for and defend a community standard because it shows that the community
comes before the person, but it is a really _bad_ thing to have someone
argue vociferiously _against_ community standards, especially when the
only reason for doing so is that those very few who argue against it
subjugate community interests to their own ego, even more so when it has
become badly bruised in a battle over its anti-community tactics.
At issue is not the specific new "features", whether they be macros,
functions, or anything else, it is simply a rejection of someone who has
decided to be an outlaw and force his own way regardless of consequences
instead of trying to work within the law to make people agree with him
how to make a better world -- probably because he realizes that it would
in fact not _be_ a better world if he did not rule everything in it.
I have long had an interest in law and the philosophy of law, but with it
comes an interest in why people choose to abide by or violate a law, or
even ethics. Everybody has their own ethical standards which come into
conflict with the law or at least other people's ethics at various points
in their lives. The really _big_ question is whether you are the kind of
person who realizes that the only thing the law and ethics _really_ say
is what is _wrong_ or you are the the kind of person who (mistakenly)
believes that law and ethics tell people what is _right_. The latter go
on to be quite the intolerable moralists who want people to follow a
specific path (i.e., whatever path they have chosen, and the two usually
become conflated) or else they are doomed sinners upon which all evil can
be hurled in a "defensive" action. The former find it interesting how
people choose among a very large number of ways to go about their lives,
but may also be intolerant of those who, by breaking law and ethics and
taking both in their own hands, make it harder or impossible for others
also to choose their own ways. It is threfore quite illuminating how our
perpetrator continues to argue that he is within the law and community
ethics when he does something he can have no doubts at all the community
has resoundingly _rejected_. The lack of willingness to stop doing,
indeed, the insistence on _continuing_ what the community has disapproved
of is precisely what defines the criminal mind.
Law and ethics are wisely set up by lots of smart people working very
slowly to ensure that proper procedure is followed, resulting in both
being _vastly_ smarter than the average joe, in order to ensure that
_very_ different people can live together under the same rules without
needing special privileges for particular groups, which was the general
situation before these intricate procedures were followed. "Equality
before the law" is definitely not in the _personal_ interest of most
people, who would rather get a break than be held responsible for their
actions. (Punishment also does not work on those who do not understand
what happened to them, only the threat of punishment does, although it
can take an initial actual punishment for some people to "get it", but
without real punishment, there is no threat, so this is a very hard
problem to resolve.)
What defines a community is in part its process of agreeing on its laws
and ethics and other standards. We have a language standard that should
have united us. Because of some lunatics who value being rebels higher
than a working community, this is not quite so, and we still have to
fight battles over what the community standards-setting procedures are.
In essence, it will be fought over whether some nutcase can publish a
"Coding Standard" document where he ridicules and undermines the standard
that the community has in fact agreed upon and which thus rejects the
community _and_ get away with it through stubbornness and sheer tenacity,
or whether the community rejects this nutcase and moves on, despite the
everpresent lack of _total_ agreement with any community standard.
Some people will always disagree with some part of what has been agreed
upon for a large population, and there are many reasons for this, but the
real question is not what people disagree with, not with what they do
when they disagree, not with how they plan to "convert" people to their
ways, but with whether they wish to maintain a respect for that community
standard or seek to destroy that respect and thus obliterate what holds
the community together.
This is not about some language feature or another, which, typically and
predictably, the perpetrator will continue to whine that it is. This is
about how we wish to hold a community together. There is no doubt that
this insipid if* macro stunt is fragmenting the community like nothing
else, despite the perpetrator's propagandistic lies about loop, which is
the object of another of his destructive machinations. The _only_ issue
is whether the perpetrator can manage to stop fragmenting the community
when he realizes that that is precisely what it does. So far, all we
have seen is an _increasing_ arrogance and even more stubbornness in his
fight against the community. Clearly, this nutcase/perpetrator values
his protest _much_ higher than that which he knows that he is destroying
in the process. That kind of destructive attitude cannot be tolerated.
If the nutcase/perpetrator had been willing to back down early, this
would never have gotten to be such an issue. It has become an issue only
because he does _not_ back down. Now he cannot back down because he
would lose his personal prestige doing so, wrecking his "standing" among
whoever still supports him. This is pretty pathetic, but that is how
things evolve when you are _wrong_ and are prevented from realizing it in
time for personal and highly irrational reasons. We must expect the
perpetrator to protest his innocence too much and continue to pester the
Common Lisp community with his bogus claims about the standard and how
the language and the community should welcome his stupid stunt.
Finally, if* has already become a symbol for the clueless rebels, but the
likelihood that whoever initially thinks that stupid macro is a good idea
will stick to it as they see what they are buying into by using this
symbol of anti-standard, anti-community, childish rebellion against
authority, will also decrease, hopefully further isolating the rebels.
I have used an Emacs Lisp function to transform if* into an if, cond,
when, or unless form as deemed appropriate through some simple measures,
but it needs tweaking to make it work better. It reverts the form to the
bogus if* form when saving the file, unless it has been modified so as
not to affect patches and other updates to the code from people who have
yet to rid the code of the bogosity. It should probably also realize
when the if* nonsense is really trying to macroexpand a case, typecase or
any of the other numerous much better ways of expressing things than an
overly verbose and poorly formatted list of elseifs.
>
> The difference, however, is that most modern implementations of, say,
> C, are pretty much identical from the programmer's point of view. In
> most cases, C code that is efficient under both gcc/x86 and
> SunPro/Sparc will be efficient on all (modern) platforms.
Again, I have to disagree with this, or at least qualify it. It is
probably
true for the kinds of trivial integer/float benchmarks that are all
people tend to look at (and it probably *isn't* true for the Lisp
equivalents of these same benchmarks, which is why people get so hung
up on this). Sure, C is portably efficient for a program which sums
the integers from 1 to 10^6, or one that does some simple-minded
floating-point computation. But is it portably efficient for, say,
large array-bashing code which represents the kind of things people do
in the real world that can be mapped efficiently onto machine
resources? I suspect it really isn't - you need to know a whole load
of stuff about really low-level details like what floating-point
registers there are and how big cache lines are and all sorts of
really obscure things. In fact I suspect that *no* language is
portably efficient at that level.
And again for the more common kinds of programs (in C as well as Lisp)
that do complex data structure bashing and lots of pointer chasing,
and other operations which don't map trivially onto machine
operations, the performance tends to be dominated by algorithms rather
than by some low level question of implementation.
Of course there are counterexamples - md5 might be one (though I
question its portability in C since it depends very much on integer
sizes and so on). But I've written a fair amount of CL and by *far*
the overwelming problems with my programs are algorithmic deficiencies
and just plain bad design, with the sole exception of I/O. I/O is a
sore point, because it's traditionally been rotten in Lisp, although I
think the situation is much better now. However I would be *really*
surprised if I/O is portably good in any language: this is the kind of
thing that serious people spend a *lot* of time tuning per platform.
For small machines, of course, the problem has mostly gone away (even
in Lisp) since the machine is almost always I/O (and memory-bandwidth)
starved to the extent that it's hard for a program to not beat the
disk. For large machines where I/O is closer to keeping up you have
to tune *extensively* anyway.
--tim
However suppose you were given the power today to tell me that I can no
longer use if*. Would you tell me that?
.. and unrelated to that here's an editorial opinion (not directed
specifically at any one person):
You talk about "community standards" and that's a very politically
correct term that doesn't raise anyone's shackles. However I think
that Marc Spitzer hit the nail on the head when he talked about the "morality"
of writing a macro. We can make the definition that if it was
immoral of me to write the if* macro then if* is an immoral macro.
Now I hope that people are starting to get bothered by such
a declaration. Is it the case that the ANSI spec laid down the laws
as to what's a legal and non-legal Common Lisp program but now
some people are saying that legal Common Lisp programs are divided
between moral and immoral programs? The decision as to what's moral
is made by self appointed people who read the scriptures (ANSI spec)
and come to their own interpretation and feel they can speak for the members
of the congregation (er.. I mean common lisp community).
Shall we anoint a Pope? I know of one militant Common Lisp fundamentalist
who's been terrorizing non believers here for years who would love to
be able to force his will on others in the name of the community.
The beauty of morality arguments over proofs is that contradictions
are just fine. You can say "Thou shalt not write control flow macros
that duplicate what's in Common Lisp" and claim that if* is immoral
and at the same time say that when and unless are perfectly find macros
and in fact divinely inspired.
Or just maybe we should once again step back from the brink of registering
Common Lisp as a religion. It's a programming language folks!!
It's a tool to get a job done. Use it any way you want and don't
let anyone tell you differently. If you do something interesting
share it with the group. They may not pick up on it but at least
you tried. Chance are a few people will find it interesting.
A lot has occurred in the software world since Common Lisp was designed.
Lisp can and must absorb new ideas from other languages to maintain
its leadership position (even if these new ideas end up being
control flow macros that duplicate existing common lisp ones).
Also no person on this newsgroup speaks for the community. Don't
be bullied into believing otherwise.
> The if* macro is much older than Common Lisp. I've used it a long
> time and since I have to read code that uses it and code that doesn't
> use it I'm continually made aware that it solves the problem it was
> intended to solve. Thus I'd like to continue to use it.
>
> However suppose you were given the power today to tell me that I can no
> longer use if*. Would you tell me that?
At least _I_ would never tell you that *you* are not allowed to use IF*.
But we _still_ have to disjunct arguments here:
- Should you be forced not to use IF*?
No - definitely not! But at the _same_ emphasis _you_ cannot force
others to use it or even to use it explicitely!
- If IF* a good idea for inclusion into a standard
To answer this question we would have to discuss (again...) what the
merits of IF* are. For building a community standard I think it is
ok to include it if a significant amount of people use it and as long
as a reference implementation is made public. (At least the latter is
already done)
Note that my opinion of the latter point is because I think it is better to
include a facility used by a significant subset of the community over
disciminizing them by explicitely not including it. Note too that this does
_not_ imply including the attitude to forbid use of IF, WHEN , UNLESS
instead of IF*.
We have to realize that the topic IF* is not only yet another control-macro
but also the try to enforce the not-usage of some other facilities!
Now you can claim that it was the whole point of IF* was to replace the
other constructs and without that it would not much sense - if that is true
then the answer if IF* (seen at a whole) is _not_ morally tolerable because
it would include discriminating others style of programming.
> Now you can claim that it was the whole point of IF* was to replace the
> other constructs and without that it would not much sense - if that is
> true then the answer if IF* (seen at a whole) is _not_ morally tolerable
> because it would include discriminating others style of programming.
Sorry this paragraph got terribly wrong - I want to rephrase it.
Now you can claim that it was the whole point of IF* to replace the other
constructs and without that it would not make much sense to use it. If that
is true, then the answer if IF* (seen at a whole is _not_ morally tolerable
is simply answered, because it would include discriminating others style of
ok.. let's see if we can find the key points of your letter:
>> because of the specific idiotic new "feature" that nobody needs or wants,
>> but because of the sheer irrationality of the whole endeavor and because
>> of the incredible _arrogance_ exuded by those who thus reject the whole
>> community they _pretend_ or may even helplessly _want_ to be members of,
>> but are in fact rejecting completely.
You shouldn't use absolutes like this. People know that you're wrong and
when you start out being wrong so early they aren't going to trust
the rest of what you say. "nobody needs or wants" is clearly wrong.
I need and want it. There are others here that need and want it.
And I've heard from people via email that need and want it.
"..but are in fact rejecting completely." -- I can't see that I'm
rejecting *anything* let alone rejecting *everything.* If I rejected
everything then I would be off programming in some other language.
>> _really_ ticks people off. It is no longer about some stupid invention
>> of a macro or a function or a new sub-language, it is about the lack of
>> willingness to yield in traffic as opposed to a willingness to run into
>> people on purpose because one thinks one is a superior to others -- it is
>> the _exact_ same process that makes people become criminals.
I really love this one. Writing a perfectly legal Common Lisp macro
and continuing to using it despite your vocal dislike of it is like
running into people on the streets.
>> Some people will always disagree with some part of what has been agreed
>> upon for a large population,
Macros are part of Common Lisp. The large population agreed that they
should be part of the language. Using macros is not wrong. Using
macros that a few people on comp.lang.lisp dislike is not wrong.
>> in their lives. The really _big_ question is whether you are the kind of
>> person who realizes that the only thing the law and ethics _really_ say
>> is what is _wrong_ or you are the the kind of person who (mistakenly)
>> believes that law and ethics tell people what is _right_. The latter go
>> on to be quite the intolerable moralists who want people to follow a
>> specific path (I.e., whatever path they have chosen, and the two usually
>> become conflated) or else they are doomed sinners upon which all evil can
>> be hurled in a "defensive" action.
What I enjoy about when I read your messages is that you always put up
some strawman to attack and more often than not the behavior of the
strawman is precisely your own. In this case you're the one who
believes that the Common Lisp spec says tell us precisely what
is right (if, when, unless) and that anything else you write that's
similar to if, when and unless must therefore be wrong. You're the one who
is the intolerable moralist about this whole thing.
>> about how we wish to hold a community together. There is no doubt that
>> this insipid if* macro stunt is fragmenting the community like nothing
>> else, despite the perpetrator's propagandistic lies about loop, which is
>> the object of another of his destructive machinations.
I don't think that if* has fragmented the community one bit.
Does anyone out there feel that there is any fragmentation due
to if*???
>> If the nutcase/perpetrator had been willing to back down early, this
>> would never have gotten to be such an issue.
I did a google groups search and the last message I can find from me
on the if* topic was Sept 5th, over two months ago. In that time
you've posted nearly every day some reference either direct or
indirect to if*. Who is the nutcase here? Why are you
so obsessed with this macro? I've written plenty of other macros
which, if you read my code, you'll have to deal with. Why not get
obsessed about one of them and give if* a break?
I don't know what your problem is. It certainly isn't about
some insignificant macro that most people couldn't care less about.
I suggest you look in the mirror. You are one person. You are
*not* the Common Lisp community. Everyone's opinion is important
but no one can speak for us all. Keep that in mind.
I'm not telling anyone here how to program. I simply codified my own
personal programming style. I could have written "I don't use
if, when and unless for secret reasons that I'll never reveal"
and maybe that would have reduced the contraversy. Frankly
I thought that people could handle reading opinions different
than their own.
As for whether if* should be part of a future standard, I probably
wouldn't push for it given the current state. It's not like there are
every likely to be competing incompatible if* macros out there.
Even if if* were to be part of the standard I would fight any
effort to remove if, when and unless. Lisp has always been
about the inclusion of different personal styles, not the exclusion.
> The if* macro is much older than Common Lisp. I've used it a long
> time and since I have to read code that uses it and code that
> doesn't use it I'm continually made aware that it solves the problem
> it was intended to solve. Thus I'd like to continue to use it.
Common Lisp is not the language you are programming in, then.
> However suppose you were given the power today to tell me that I can no
> longer use if*. Would you tell me that?
I read a wonderful piece of text yesterday. This reminds me of it.
http://www.mit.edu/people/dpolicar/writing/prose/text/godTaoist.html
You can't force anything on other peopre here, on USENET. And why
would you want that?
> .. and unrelated to that here's an editorial opinion (not directed
> specifically at any one person):
> ...
> Is it the case that the ANSI spec laid down the laws as to what's a
> legal and non-legal Common Lisp program but now some people are
> saying that legal Common Lisp programs are divided between moral and
> immoral programs?
Yes. See section 1.5.2 of The Standard. Unless your programs include
the definition of if* macro they are non-conforming.
I won't comment on morality.
> The decision as to what's moral is made by self appointed people who
> read the scriptures (ANSI spec) and come to their own interpretation
> and feel they can speak for the members of the congregation (er.. I
> mean common lisp community).
You are not talking about anyone specifically, do you?
> Or just maybe we should once again step back from the brink of
> registering Common Lisp as a religion.
You keep dragging this in. Why?
> It's a programming language folks!! It's a tool to get a job done.
> Use it any way you want and don't let anyone tell you differently.
What kind of political propoganda is this? Do you think we're a bunch
of brainless folks here waiting for someone to tell us what to do?
As long as argumentation goes -- Erik out-argumnts you hands down. I
don't take any sides here. I like seeing the brain-at-work in his
posts. Will we see a _real_ reply with quotes of the poster you reply
to any time soon? Or will they be this "nothing personal in here, just
my opinion; I have the rights to express my opinion, right?" stuff you
picked up recently?
I actually liked your posts before this "I'll help you get rid of
Erik" duty you have taken on yourself. I have learned a lot of things
from your open-source software as well. Thank you for that.
> If you do something interesting share it with the group. They may
> not pick up on it but at least you tried. Chance are a few people
> will find it interesting.
Ok, you tried. You failed with some people, prevailed with other. Will
it stop now?
> A lot has occurred in the software world since Common Lisp was
> designed. Lisp can and must absorb new ideas from other languages
> to maintain its leadership position (even if these new ideas end up
> being control flow macros that duplicate existing common lisp ones).
I think Common Lisp does not have to "absorb" something. It has to
pick the best out of it and incorporate it in a way consistent with
the language.
--
Janis Dzerins
Eat shit -- billions of flies can't be wrong.
> You can't force anything on other peopre here, on USENET. And why
> would you want that?
You miss the point of the question. I was trying to see whether
Kent believed more in personal freedom or what he personally believes
to be the will of the people.
> Yes. See section 1.5.2 of The Standard. Unless your programs include
> the definition of if* macro they are non-conforming.
>
What are you talking about???
> > Or just maybe we should once again step back from the brink of
> > registering Common Lisp as a religion.
>
> You keep dragging this in. Why?
>
Because it's appropriate.
>
> What kind of political propoganda is this? Do you think we're a bunch
> of brainless folks here waiting for someone to tell us what to do?
>
I'm expousing a different view that that "some macros are immoral view"
That's the point of this newsgroup, to post views.
> > If you do something interesting share it with the group. They may
> > not pick up on it but at least you tried. Chance are a few people
> > will find it interesting.
> Ok, you tried. You failed with some people, prevailed with other. Will
> it stop now?
I'm not the one whose been continually bringing up this if* thing
for the last two months. So I can't make it stop.
John Foderaro <j...@xspammerx.franz.com> writes:
> In article <87itckg...@asaka.latnet.lv>, jo...@latnet.lv says...
> >
> > Common Lisp is not the language you are programming in, then.
> >
>
> Partially correct. As has been mentioned here a few times if* is just
> the If macro from Franz Lisp which preceded Common Lisp.
> However it's *not* correct to say that that I'm programming
> in Common Lisp now (and for the last many years).
>
> > You can't force anything on other peopre here, on USENET. And why
> > would you want that?
>
> You miss the point of the question. I was trying to see whether
> Kent believed more in personal freedom or what he personally believes
> to be the will of the people.
Personal freedom is accompanied by personal responsibility. You have
the right to use macros and functions of your own devising. You have,
I think, the responsibility to include their definitions in a
distribution that uses them and that purports to be runnable in
conforming CL. Of course, you can write conforming code that isn't
runnable. For example (foo x) is conforming, but without a definition
of FOO it's not worth much. If you make a claim that a module
implements a certain functionality, but it leaves out definitions of
operations necessary to make the module go, it seems to me that either
the claim that the module implements the functionality is false or
else you need to explicitly document what other modules are
prerequisites to running your system. And in that sense, you are not
running just on CL but on some layered system defined by
CL+the-other-modules. e.g., you can write MACSYMA or CLIM
in CL and a program that uses that system, and that's fine. But saying
that (clim:accept 'integer :prompt "Type a number:") is the CL way
to do program input or (MACSYMA:$INTEGRATE '((MACSYMA:$SIN) $X) '$X) is the
"CL way" to integrate sin(x) is a bit of a stretch.
> > Yes. See section 1.5.2 of The Standard. Unless your programs include
> > the definition of if* macro they are non-conforming.
> >
>
> What are you talking about???
I believe the point is that people shouldn't have to separately
download if*. If it's just a personal macro, its definition will
appear in any distribution that uses it, just like any other
user-defined function that makes said distribution work. The entire
fuss over "where do we get that definition" was artificial because one
doesn't ask that about any other user-defined variable, function, or
macro--the answer is: loading the user module defines it. If the user
module doesn't define it, then the language/environment is expected
to. The CL language doesn't, so if you're depending on it, it's not
CL you're depending on.
> > Ok, you tried. You failed with some people, prevailed with other. Will
> > it stop now?
>
> I'm not the one whose been continually bringing up this if* thing
> for the last two months. So I can't make it stop.
I'd be willing to take your side and lobby for the rhetoric to stop if
I were assured that if* were just a normal definition as part of any
facility (such as AllegroServe) you export that purports to run
outside of Franz life support, or if, failing such an added
definition, you tell me that you put #+Allegro in front of each its
uses to make it clear that it's system-dependent just as you would (or
should) with any other non-portable aspect of such a system.
You might have already done this; I'm not asserting you haven't.
I'm just assuming that the rhetoric can be triggered by actions, and some
rhetoric is legit and some is not. Tell me that the rhetoric is not
legit by asserting you've met these or some other definable criteria
that establish an equivalent sense of "predictable platform" and I'll
help you lobby for more calm.
The normal way to do what you did, btw, is to make a new package.
In my software at HyperMeta, Inc., I don't like a few operators
(DEFPACKAGE and ASSOC) so I changed them (mostly upward-compatibly, but
in the case of DEFPACKAGE, technically there is a possibility of
obscure clashes). I just made another package called COM.HYPERMETA.CL
that has my versions of these. No one will use it by accident; anyone
using my software can feel free to import either CL's versions or
mine. I don't expect to get heat from this approach because I'm not
fighting other people's uses. I just made my own space to play in
non-invasively. People who don't want the extra DEFPACKAGE options I
offer, or who don't want to use SETF of ASSOC, can just ignore my
extensions.
Also, I *do* regard my changed package as a new language. I don't know why
you don't think of CL+IF* as a new language. Maybe you're worried it will
lose you the support of CL users, and as an empirical thing, it may. But
if so that isn't because of your being a new language, it's because you
made a bad choice that people don't want to flock toward. Like you,
I expect people to flock toward my changes, but if they don't, I'm not
going to hide behind "it's just CL". I'll say it's because they didn't
like the trivially different language I made.
Incidentally, I have another language, COM.HYPERMETA.LISP which is
much less trivially different -- that is, contains a lot of other junk
/ goodies (depending on yourpoint of view). I just went in two stages,
first changing CL non-invasively, then adding other stuff as
extensions to that, in case people cared to only go one of the two
steps. Or there are ways they can pick and choose from only the parts
of COM.HYPERMETA.LISP they like... but it's easier with my DEFPACKAGE. ;-)
I also didn't try to pick bad names. I personally don't like IF* because
it looks bad. But if you called it EXT:IF, I'd be fine with it because
I could either import it or not. If I did, I'd be programming in your
language. If I didn't, I'd be programming in mine. That feels cleaner
to me. If I'd wanted co-resident operators, CL:IF and your:if-surrogate,
I'd have named the operator something prettier. UPON or WHENEVER or
BECAUSE or DO-IF, or something whose name didn't confusingly seem like
it was a friend of LIST* or LET*, two name conventions that already clash
and don't need yet a third source of competition. Or else I'd have done
what COM.HYPERMETA.CL:DEFPACKAGE does, and I'd just be "mostly compatible"
and say that I distinguish based on whether a
macro-whose-name-was-formerly-IF* keyword was present, doing its actions
only if they were, and doing CL:IF's actions otherwise. Yes, not totally
compatible, and no, not "CL", but still "defensible" as long as you're
willing to admit you've carved out your own langauge (which isn't a sin
but one of many the purposes of CL to enable)...
could you please elaborate?
--
Sam Steingold (http://www.podval.org/~sds)
Keep Jerusalem united! <http://www.onejerusalem.org/Petition.asp>
Read, think and remember! <http://www.iris.org.il> <http://www.memri.org/>
Someone has changed your life. Save? (y/n)
Have I ever made a claim that any of the code that I've distributed
can be run in any conforming CL? If I did then it was a mistake.
The code that I find interesting enough to distribute generally
has dependencies on multithreading, sockets and acl-dependent streams.
In fact I can only promise that it runs on certain recent versions of
ACL.
Why should I even distribute it? Well, the people using ACL can use it
off the shelf and those that use other Lisp may be able to port it or at least
may be curious how something was done.
The cost to me to ensure that it works in all the various conforming CL's
out there would probably mean that I'd just not distribute anything.
>> I believe the point is that people shouldn't have to separately
>> download if*. If it's just a personal macro, its definition will
>> appear in any distribution that uses it, just like any other
>> user-defined function that makes said distribution work.
The best solution here is a Compatibility Library. If users of
CL A want to load code written for CL B with minimal changes,
then the CL A users have to write and maintain a library B->A.
That's something the community here can help get going. This library
would be a lot bigger than just the if* macro.
If I merely added the definition of if* to all my source files it would
add nearly nothing to making the code easier to run on other Common Lisps.
>> I'd be willing to take your side and lobby for the rhetoric to stop if
>> I were assured that if* were just a normal definition as part of any
>> facility (such as AllegroServe) you export that purports to run
>> outside of Franz life support, or if, failing such an added
>> definition, you tell me that you put #+Allegro in front of each its
>> uses to make it clear that it's system-dependent just as you would (or
>> should) with any other non-portable aspect of such a system.
Now that I've made it clear that the code I offer does not purport
to run on any Common Lisp other than recent versions of ACL, can
I eliminate that need to mark the acl-specific parts of it?
I know that this sounds like I'm lazy or selfish but remember back
to what Erik said about not distributing code any more because he finds
the people receiving it are ungrateful and just complain.
I've got three choices (and yes technically it's Franz's choice but
in the case of code I've written I think they would go along with
what I wanted).
1. I could not opensource the code
2. I could opensource what I've written which is ACL only
3. I could make it work on all lisps and open source that.
well 3 is out, since I don't have the time, knowledge or energy to
coordinate such an effort, and it may not be the best thing for
the code.
So I could either do 1 or 2. If people are offended that I chose 2
I can always do 1. That's very easy to do. Would that benefit
the community more?
>>
>> Also, I *do* regard my changed package as a new language. I don't know why
>> you don't think of CL+IF* as a new language.
It can or cannot be considered a new language based on what you intend
to infer from 'new language'.
If by 'new language' you mean that due to the addition of if* existing
Common Lisp books are invalid, this is not true at all.
if* is actually excl:if*. If you work in a package that doesn't
use the excl package then it is as if the if* macro didn't exist.
So by my definition of 'new language' you can add a million functions
and macros to a Common Lisp system and not change the language
a single bit as long as the user still has the capability of
sees the ansi defined common-lisp package.
In the case where you're shadowing ANSI defined functions then you
are indeed defining a new language.
>> I also didn't try to pick bad names. I personally don't like IF* because
>> it looks bad.
I would have preferred to use If as in Franz Lisp but you know quite
well why that's not a practical choice.
if*'s a better name than shadowing 'if' since emacs doesn't have to
be very clever to distinguish 'if' from 'if*' and indent each correctly.
Also you can give someone some code and the if* macro and they can run it.
They don't have to go through shadowing 'if' in a package to use it.
If I were to publish code using a shadowed 'if' that had the 'if*'
keywords it would totally baffle the newbies and even old timers
would dislike it.
In my programming style if* is the single most important conditional
expression, so I want it to have a terse name. If people used
multiple-value-bind a lot it wouldn't be called multiple-value-bind,
just like car is car and not contents-of-address-register.
> > * In message <sfweln7...@shell01.TheWorld.com>
> > * On the subject of "Re: MD5 in LISP and abstraction inversions"
> > * Sent on Fri, 9 Nov 2001 16:51:44 GMT
> > * Honorable Kent M Pitman <pit...@world.std.com> writes:
> >
> > SETF of ASSOC
>
> could you please elaborate?
I was just giving an example of a function one might want to redefine.
One is not allowed to extend definitions of CL symbols, so you have to
shadow them. I did this for ASSOC. It's not extraordinarily useful
in practice, but people often ask why it's not there since the PLIST
setters are present, so I figured why not add it. It is, by the way,
an annoying pain to write correctly if you DO want it:
(setq x '()) => ()
(setf (assoc 'a x) (cons 'a 4)) => (a . 4)
x => ((a . 4))
(setf (assoc 'a x) (cons 'a 5)) => (a . 5)
x => ((a . 5))
(setf (assoc 'a x) (cons 'b 1)) => (b . 1)
x => ((b . 1) (a . 5))
I also add the more useful functions, like this one:
(association 'a x) => 5
(setf (association 'a x) 6) => 6
(association 'a x) => 6
x => ((b . 1) (a . 6))
(setf (association 'c x) 0) => 0
x => ((c . 0) (b . 1) (a . 6))
(decf (association 'c x) 3) => -3
x => ((c . -3) (b . 1) (a . 6))
Getting the value and not the cell makes things like INCF/DECF more useful.
I have functions for the other-style ALIST, too. But then, the point
is that I spent a bit over six months full-time just writing all kinds
of support for things I was tired of not having... (So you'll forgive
me if I don't just post the lot of it on some free software site, btw;
I've burned through that many months' salary worth of savings and credit
card buildup, and now have to figure out how to make some money back on
all that investment. I promise it's not all as trivial as SETF of ASSOC,
though...)
Anyway, is that what you wanted to know?
Don't you think there is a big difference between a pervasive control flow
construct and functionality that is not included in the standard at all?
> Why should I even distribute it? Well, the people using ACL can use it
> off the shelf and those that use other Lisp may be able to port it or at
least
> may be curious how something was done.
>
> The cost to me to ensure that it works in all the various conforming CL's
> out there would probably mean that I'd just not distribute anything.
>
True, but the cost of making it an order of magnitude easier is small.
> >> I believe the point is that people shouldn't have to separately
> >> download if*. If it's just a personal macro, its definition will
> >> appear in any distribution that uses it, just like any other
> >> user-defined function that makes said distribution work.
>
> The best solution here is a Compatibility Library. If users of
> CL A want to load code written for CL B with minimal changes,
> then the CL A users have to write and maintain a library B->A.
> That's something the community here can help get going. This library
> would be a lot bigger than just the if* macro.
>
This indicates more than anything else you have written that you *prefer* to
create incompatible branches in the Common Lisp tree. It may be very hard to
avoid for some areas not forseen when the ANSI work was done, but it is
something one should at least *try* to avoid. I truly belive that Franz has a
business plan similar to MS - gain marketshare --> dominate --> ignore
community standards to damage competitors --> monopolize. This is not the only
way to be successful in business.
I think it is very disengenuous of you to use arguments based on things like
multi-processing and sockets which unfortunately are *not* defined in the
standard in a discussion of a simple control-flow macro. Nuts and bolts stuff
is usually where incompatabilities lie and are usually easy to confine. When
you use something non-standard of your own devising to the exclusion of all of
the other control flow constructs this seems to me very different.
Again you have every right to write and use something like if* and the religion
argument you keep setting up and knocking down is not what most people (any
people, really) have been raising. Surely you realize most of the fuss was
over the attitude that came with it. It is obvious that if* is _not_ just a
utility to you, it has history and political baggage that, while I don't know
the details, the existence of is very evident. I use personal little utilities
all the time, they are kept in a utilities file and go everywhere with the rest
of the source. Why is that so difficult?
> If I merely added the definition of if* to all my source files it would
> add nearly nothing to making the code easier to run on other Common Lisps.
>
That doesn't seem to be a common position. And it would sure do alot to
satisfy peoples concerns.
> >> I'd be willing to take your side and lobby for the rhetoric to stop if
> >> I were assured that if* were just a normal definition as part of any
> >> facility (such as AllegroServe) you export that purports to run
> >> outside of Franz life support, or if, failing such an added
> >> definition, you tell me that you put #+Allegro in front of each its
> >> uses to make it clear that it's system-dependent just as you would (or
> >> should) with any other non-portable aspect of such a system.
>
> Now that I've made it clear that the code I offer does not purport
> to run on any Common Lisp other than recent versions of ACL, can
> I eliminate that need to mark the acl-specific parts of it?
>
> I know that this sounds like I'm lazy or selfish but remember back
> to what Erik said about not distributing code any more because he finds
> the people receiving it are ungrateful and just complain.
>
Most of the attacks you have endured were prompted by the insult you delivered
with your gift. (ie your coding standards v. 1.0(a) document). It is
understandable people took exception to that. Especially as it was hosted by
one of the major vendors.
> I've got three choices (and yes technically it's Franz's choice but
> in the case of code I've written I think they would go along with
> what I wanted).
> 1. I could not opensource the code
> 2. I could opensource what I've written which is ACL only
> 3. I could make it work on all lisps and open source that.
>
> well 3 is out, since I don't have the time, knowledge or energy to
> coordinate such an effort, and it may not be the best thing for
> the code.
>
> So I could either do 1 or 2. If people are offended that I chose 2
> I can always do 1. That's very easy to do. Would that benefit
> the community more?
What about 2(a). Do 2 and include the code for if* and any other logically
significant macros and functions you use?
Coby
--
(remove #\space "coby . beck @ opentechgroup . com")
this last looks weird to me.
I would expect an error.
> I also add the more useful functions, like this one:
>
> (association 'a x) => 5
> (setf (association 'a x) 6) => 6
> (association 'a x) => 6
> x => ((b . 1) (a . 6))
> (setf (association 'c x) 0) => 0
> x => ((c . 0) (b . 1) (a . 6))
> (decf (association 'c x) 3) => -3
> x => ((c . -3) (b . 1) (a . 6))
>
> Getting the value and not the cell makes things like INCF/DECF more useful.
this looks more natural to me.
do you mind if something like this finds its way into CLISP and/or CLOCC?
> I have functions for the other-style ALIST, too.
what's that? "RASSOC"?
> (So you'll forgive me if I don't just post the lot of it on some free
> software site, btw; I've burned through that many months' salary worth
> of savings and credit card buildup, and now have to figure out how to
> make some money back on all that investment. I promise it's not all
> as trivial as SETF of ASSOC, though...)
Sure. Your freedom is yours, and I quite understand you.
Good luck with your company.
(You are aware that you _can_ use CLISP commercially, aren't you?
Paul Graham did!)
> Anyway, is that what you wanted to know?
yep.
thanks.
--
Sam Steingold (http://www.podval.org/~sds)
Keep Jerusalem united! <http://www.onejerusalem.org/Petition.asp>
Read, think and remember! <http://www.iris.org.il> <http://www.memri.org/>
The only time you have too much fuel is when you're on fire.
I believe the best notion of what is right will emerge by itself if you
keep the definitely wrong away. Evolution works this way: Contrary to
popular belief and the statement "survival of the fittest", a much more
accurate description is "early death of the unfit". Among all the weird
ideas people get, weed out the bad ones early, and whatever is not bad
enough to stand out as monumentally stupid at the time may have enough
merit to make a difference somewhere down the line. Believing in the
survival of "right" leads to _really_ bad social experiments.
| So we nailed it down. We're supposed to have moved beyond those things
| to new areas to bicker about.
But this requires people who are cognizant of the necessarily political
nature of _every_ community consensus-forming process and who are not
irrationally allergic to forming networks of agreement with other people
despite the lack of a "uniquely right" way. People _cannot_ agree on
what is right -- that would starve a community of every opportunity to
evolve. They _can_, however, agree on what is _wrong_, and if they can
limit that to that which is _definitely_ wrong, the more room there is
for things right. However, it does require that people in the community
are able to listen when their suggestions fall in the "definitely wrong"
category. So far, nothing suggests that the if* stunt, _including_ its
abject rejection and attempt at full replacement of _all_ the standard
conditionals in the language, if, when, unless, case, typecase, etc, is
going to avoid falling in the "definitely wrong" category, mostly because
it does nothing but add some redundant noise to cond and is no _actual_
replacement for or _definite_ improvement over anything. It is simply an
irrational stylistic issue (the part about rejecting everything else),
and a historical accident perpetuated for irrational reasons. "Move on"
is precisely what we should do, but, unfortunatley, it require that the
perpetrator of this silliness respects when the community rejects him.
So far, that that is _not_ going to happen is the only thing we know
about the current situation.
In the case under question the difference is obvious: the control
flow construct is no impediment to porting the code, the
non-common lisp functionality may make porting extremely difficult.
Are you implying by your question that if I came up with a new
control flow construct that require special runtime system support
(and thus only worked on ACL) that you wouldn't mind if I use
that pervuasively throughout my code? In other words you're willing
to allow me to use any amount of non-common-lisp code but are unhappy
when the common lisp macro facility to write something that is
in fact totally portable??
>> True, but the cost of making it an order of magnitude easier is small.
ok, I'll ask Jochen Schmidt: If I had included the source to if*
with AllegroServe would it have made the port to LispWorks an order
of magnitude easier?
>> > The best solution here is a Compatibility Library. If users of
>> > CL A want to load code written for CL B with minimal changes,
>> > then the CL A users have to write and maintain a library B->A.
>> > That's something the community here can help get going. This library
>> > would be a lot bigger than just the if* macro.
>> This indicates more than anything else you have written that you *prefer* to
>> create incompatible branches in the Common Lisp tree.
Not at all. This is a practical response to the problem of there
being multiple lisps out there each of which has grown unique features.
We in fact wrote (and I think still distribute) a Lucid compatibility package
for those who want to port from Lucid Lisp to our lisp, as just one example.
This is simple software engineering based on the reality that exists today.
Franz may write a Lispworks to Allegro compatibility package and
the Lispworks folks may write an Allegro to Lispworks compatibility package.
Creating a compatibility package from X to Y does not imply any kind
of judgement of the relative values of X and Y.
>> That doesn't seem to be a common position. And it would sure do alot to
>> satisfy peoples concerns.
>>
To be honest I haven't seen concerned raised by many people.
And for some people I think they are arguing in principle rather than
any experience. I say that because a grep through AllegroServe
shows the following internal macros used that no one has
ever complained or asked about:
excl::atomically
excl::with-dynamic-extent-usb8-array
excl::fast
>>
>> What about 2(a). Do 2 and include the code for if* and any other logically
>> significant macros and functions you use?
>>
I already direct people to the if* macro in a few places.
The software engineer in me says the correct place to deal with
implementation incompatibilities is in a compatibility library.
I won't promote what I know to be bad design by putting if* in
the code for each of the packages I opensource.
If people have questions about constructs in the code I opensource
that don't exist or seem to work on their Lisp they should
send me email. I'll tell you what it does in ACL.
I'm not using ACL specific things to exclude other Lisps, I'm
simply writing the code in what I think is the best way for ACL>
> > * In message <sfwbsib...@shell01.TheWorld.com>
> > * On the subject of "Re: (SETF ASSOC) was Re: MD5 in LISP and abstraction inversions"
> > * Sent on Fri, 9 Nov 2001 21:08:52 GMT
> > * Honorable Kent M Pitman <pit...@world.std.com> writes:
> >
> > Sam Steingold <s...@gnu.org> writes:
> > > > SETF of ASSOC
> > > could you please elaborate?
> >
> > I was just giving an example of a function one might want to redefine.
> > One is not allowed to extend definitions of CL symbols, so you have to
> > shadow them. I did this for ASSOC. It's not extraordinarily useful
> > in practice, but people often ask why it's not there since the PLIST
> > setters are present, so I figured why not add it. It is, by the way,
> > an annoying pain to write correctly if you DO want it:
> >
> > (setq x '()) => ()
> > (setf (assoc 'a x) (cons 'a 4)) => (a . 4)
> > x => ((a . 4))
> > (setf (assoc 'a x) (cons 'a 5)) => (a . 5)
> > x => ((a . 5))
> > (setf (assoc 'a x) (cons 'b 1)) => (b . 1)
> > x => ((b . 1) (a . 5))
>
> this last looks weird to me.
> I would expect an error.
I wrote it here by hand, didn't paste it in. Yes, it signals an
error. I meant (setf (assoc 'b x) (cons 'b 1)). Sorry.
In fact, the code error-checks for this specific case--you can only
set a value whose car is the indicator. [Just noticed a bug, tho; I
use EQ for the test, but obviously should use the supplied test. I'll
fix that...]
> > I also add the more useful functions, like this one:
> >
> > (association 'a x) => 5
> > (setf (association 'a x) 6) => 6
> > (association 'a x) => 6
> > x => ((b . 1) (a . 6))
> > (setf (association 'c x) 0) => 0
> > x => ((c . 0) (b . 1) (a . 6))
> > (decf (association 'c x) 3) => -3
> > x => ((c . -3) (b . 1) (a . 6))
> >
> > Getting the value and not the cell makes things like INCF/DECF more useful.
>
> this looks more natural to me.
> do you mind if something like this finds its way into CLISP and/or CLOCC?
Not really. One can't copyright ideas, and it probably isn't even my
idea. But you might want to wait until I post my list.
I hope to separate the issue of "spec" from the issue of "implementation".
> > I have functions for the other-style ALIST, too.
>
> what's that? "RASSOC"?
No, I meant the dot-free alists a lot of people use.
(alist-ref '((a 1) (b 2)) 'a) => 1
[I turned the args around because all my ref functions take
aggregate first and index-object second.]
> > (So you'll forgive me if I don't just post the lot of it on some free
> > software site, btw; I've burned through that many months' salary worth
> > of savings and credit card buildup, and now have to figure out how to
> > make some money back on all that investment. I promise it's not all
> > as trivial as SETF of ASSOC, though...)
>
> Sure. Your freedom is yours, and I quite understand you.
> Good luck with your company.
> (You are aware that you _can_ use CLISP commercially, aren't you?
> Paul Graham did!)
(Yes, I'm aware. :-)
For external, published code, in order to keep the community stability,
all of us rid our code and even our prose, of personal idiosyncrasies.
Publishing houses and their copy editors exist primiarily to get rid of
the "personal dialects" of its staff of authors, and series editors of
technical books make sure that all authors agree on the terminology. We
have a large number of other examples of how people have to extinguish
their pet peeves in order for the community to work better. To reject
_all_ of the consensus-forming procedures in a community is hostile to
every single memer of that community, because every one of us has already
made, and will continue to make, sacrifices in order to further the goal
of a coherent community. It has been obvious for a very long time that
you have no such goal, and would rather sacrifice the community coherence
to your ability to "use" (read "publish"; nobody cares about unpublished
code) your macro. Other people have used other forms predating Common
Lisp, too, but they do in fact not publish hostile documents that tell
people _not_ to use the standard.
| I know of one militant Common Lisp fundamentalist who's been terrorizing
| non believers here for years who would love to be able to force his will
| on others in the name of the community.
You are quite alone in this psychotic delusion which only further your
own insane rage. You have created a deamon that keeps haunting you, but
it is not real. _Nobody_ wants what you think they want. You are the
kind of person who believes in dictating what is _right_, and that is
actually quite amazingly stupid of you. Most other thinking people know
that anyone who has even looked the philosophy of law in western cultures
would argue for dictating what is _wrong_, given solid grounds and good
evidence. That you cannot distinguish one from the other only paints you
as rather stupid and ignorant and arrogant. Which is why you get most of
the reactions you get here.
| You can say "Thou shalt not write control flow macros that duplicate
| what's in Common Lisp" and claim that if* is immoral and at the same time
| say that when and unless are perfectly find macros and in fact divinely
| inspired.
Can you _please_ get it into your stale mind that nobody argues what you
keep saying they do? Last time we had this annoying round, you kept
making a large number of completely bogus claims about what other people
had said, and you simply cannot quit living in your psychotic delusion of
a make-believe world.
What is being said is actually this: "Please quit denouncing the standard
and people who happen to like it and want it simply because you think you
are the singularly most brilliant genius on the face of this planet past,
present and future who came up with the if* macro."
The fact that your macro is not being adopted _should_ have told you
something. The fact that lots of people denounce it, quite independently
despite your paranoid delusions that there is a conspiracy against you,
does not register with you. You do not get your will, and therefore you
fight people with _amazingly_ dirty tactics. This does _not_ win you
friends, nor does it influence people to adopt if* -- which has become a
symbol of irrational, arrogant stubbornness _only_ because of your lack
of ability to back down and consider other people's opinions. One _has_
to wonder what kind of personality problem has caused this, when you make
a very strong point of arguing that people should voice their objections
when they do not like what is posted to this newsgroup -- obviously, if
anyone happens not to "agree" with you in their objections, they must be
shot down -- by you. This lack of insight into your own behavior is not
rational. In fact, it is _so_ irrational that any hope of you _ever_
getting the picture and starting to figure out that you would benefit a
lot by not _publishing_ code with that annoyingly stupid if* sunt is nil.
| Or just maybe we should once again step back from the brink of
| registering Common Lisp as a religion.
The _only_ religion here is called "if*". People object to your stupid
accusations of a religion in ways that cause your bigoted mind to think
they are guilty _because_ they object. That people object to some insane
accusation does not make the accuser any more right, but an insane
accuser will not notice this, because he has already made up his mind.
| It's a programming language folks!! It's a tool to get a job done.
Then why the hell do you have such a problem writing standard Common Lisp?
Your _entire_ chain or agumentation falls flat on its face when you make
this argument.
| Lisp can and must absorb new ideas from other languages to maintain its
| leadership position (even if these new ideas end up being control flow
| macros that duplicate existing common lisp ones). Also no person on this
| newsgroup speaks for the community. Don't be bullied into believing
| otherwise.
Geez, did those objections to you believing you are the censor of this
newsgroup not even _register_ with you? _You_ are the bully here, John
Foderaro, trying to make people _not_ use the standard, trying to force
people to shut up. Go away and create comp.lang.lisp.foderaro, where you
_are_ the supreme genius and censor and everything else you seem to be
really pissed that you are in fact _not_ in this newsgroup.
The moment you understand that you are a worse bully than anyone else
here and far more destructive to the community than anyone else, there
might a chance you achieve enlightenment. The world will know that this
has happened when you publish code without the stupid if* conditional.
The controversy would indeed have been significantly less, because it
would only make you look pretty stupid and would not insult anyone who
actually like and want to use if, when, and unless.
| Frankly I thought that people could handle reading opinions different
| than their own.
Good. Keep on thinking that. However, when your "opinion" is about
other people and it is factually and definitely _wrong_, expect to be
criticized for it. If you cannot deal with criticism, guess who cannot
handle opinions different from their own. Guess what people think when
you have to invoke "religion" to attack people whose opinions you cannot
handle. Do you think anyone actually _fails_ to understand who is the
real culprit of all of your accusations? Get a better grip on yourself.
Now, now. It is nothing personal, John.
I shall consequently strive not to respond to people who defend
_themselves_ rather than whatever they are criticized for.
> I truly belive that Franz has a
>business plan similar to MS - gain marketshare --> dominate --> ignore
>community standards to damage competitors --> monopolize. This is not the only
>way to be successful in business.
Comparing Franz to Microsoft! This surely is a high point of my day.
(Picking myself off the floor...)
I guess Franz has not been quite as successful at implementing that strategy.
They've been around about as long.
In any case, this is not at all fair. The only thing those companies share,
in my opinion, is longevity, which is a tribute to both. Most of us would prefer
to see the market penetration difference between Franz and Microsoft diminish.
One way to help is to support Franz.
Regarding John Foderaro's work, I much appreciate that Allegroserve was
written and freely distributed with source. Chris Double ported it to Corman
Lisp. I know it took some time to port it, but I assume downloading the 49-line
IF* macro was the easiest part. Anybody who is objective about this would
clearly see that the value offered for free, by distributing Allegroserve and
the IF* macro, far exceeds the inconvenience of having to download them
separately. IF* is included with Corman Lisp now (thanks to John for putting it
in the public domain and encouraging vendors to include it).
Lisp is still here today, and will still be here when C++ is a historic
footnote, because it can evolve so easily. Just like English.
People in power, or the media, invent new words all the time. Nobody cares that
they aren't in the dictionary (which makes no claim to be authoritative). Nobody
says they are making up a new language. If all the smart people working in lisp
develop new macros, and we toss them into a package that all the vendors can
distribute, the language would probably benefit. The good ones would get used
more than the others, and provide obvious candidates for future standardization.
>What about 2(a). Do 2 and include the code for if* and any other logically
>significant macros and functions you use?
I agree wholeheartedly with this. It would only cost John about 5 minutes of
work, and would have saved each person who had to port Allegroserve at least 5
minutes to download it and insert it. Overall, probably a good 10 minutes more
productivity.
Yes--I am being somewhat sarcastic, but I still think including it makes sense.
It would save countless hours of debate on this newsgroup if nothing else.
Roger
> Juliusz Chroboczek <j...@pps.jussieu.fr> wrote in message news:<87bsidb...@pps.jussieu.fr>...
>
> > The difference, however, is that most modern implementations of, say,
> > C, are pretty much identical from the programmer's point of view. In
> > most cases, C code that is efficient under both gcc/x86 and
> > SunPro/Sparc will be efficient on all (modern) platforms.
>
> Again, I have to disagree with this, or at least qualify it. It is
> probably
> true for the kinds of trivial integer/float benchmarks that are all
> people tend to look at (and it probably *isn't* true for the Lisp
> equivalents of these same benchmarks, which is why people get so hung
> up on this). Sure, C is portably efficient for a program which sums
> the integers from 1 to 10^6, or one that does some simple-minded
> floating-point computation. But is it portably efficient for, say,
> large array-bashing code which represents the kind of things people do
> in the real world that can be mapped efficiently onto machine
> resources? I suspect it really isn't - you need to know a whole load
> of stuff about really low-level details like what floating-point
> registers there are and how big cache lines are and all sorts of
> really obscure things. In fact I suspect that *no* language is
> portably efficient at that level.
I find it really strange that people claim C to be portable, because
who actually writes portable C code? Sure, I'll sometimes write code
that I intend to be compilable by a wide range of C compilers, but if
I'm at all concerned about efficiency, or representation in memory,
that's pretty much out the window. Many of the C programers I've seen
dig through the compiler documentation, look at disassemblies, poke
around the program in the debugger, etc, looking for ways to make the
program a better fit for the hardware. That's fundamentally
unportable. Some things are written in such a way that they make life
easier for porters, but how many serious C programs can you drop in a
new compiler/OS/architecture, and just compile, unchanged?
--
/|_ .-----------------------.
,' .\ / | No to Imperialist war |
,--' _,' | Wage class war! |
/ / `-----------------------'
( -. |
| ) |
(`-. '--.)
`. )----'
> Sam Steingold <s...@gnu.org> writes:
>
> > > * In message <sfweln7...@shell01.TheWorld.com>
> > > * On the subject of "Re: MD5 in LISP and abstraction inversions"
> > > * Sent on Fri, 9 Nov 2001 16:51:44 GMT
> > > * Honorable Kent M Pitman <pit...@world.std.com> writes:
> > >
> > > SETF of ASSOC
> >
> > could you please elaborate?
>
> I was just giving an example of a function one might want to redefine.
> One is not allowed to extend definitions of CL symbols, so you have to
> shadow them. I did this for ASSOC. It's not extraordinarily useful
> in practice, but people often ask why it's not there since the PLIST
> setters are present, so I figured why not add it. It is, by the way,
> an annoying pain to write correctly if you DO want it:
No kidding. I tried to write it once, and decided that it was too
high of a pain-to-usefulness ratio.
> (setq x '()) => ()
> (setf (assoc 'a x) (cons 'a 4)) => (a . 4)
> x => ((a . 4))
> (setf (assoc 'a x) (cons 'a 5)) => (a . 5)
> x => ((a . 5))
> (setf (assoc 'a x) (cons 'b 1)) => (b . 1)
> x => ((b . 1) (a . 5))
Particularly for something like this (I know you fixed the example
later). Should the last x have been
((b . 1) (a . 5))
or
((b . 1))
or have signaled an error, or what? I figured that if the rest of the
lisp world was getting along fine without it, I could too.
> I also add the more useful functions, like this one:
>
> (association 'a x) => 5
> (setf (association 'a x) 6) => 6
> (association 'a x) => 6
> x => ((b . 1) (a . 6))
> (setf (association 'c x) 0) => 0
> x => ((c . 0) (b . 1) (a . 6))
> (decf (association 'c x) 3) => -3
> x => ((c . -3) (b . 1) (a . 6))
>
> Getting the value and not the cell makes things like INCF/DECF more useful.
Oooh, yes, this is one of my favorites. I was so happy when I got it
to work (though I think your name is a lot better than the assocd I
chose)
> I have functions for the other-style ALIST, too. But then, the point
> is that I spent a bit over six months full-time just writing all kinds
> of support for things I was tired of not having... (So you'll forgive
> me if I don't just post the lot of it on some free software site, btw;
> I've burned through that many months' salary worth of savings and credit
> card buildup, and now have to figure out how to make some money back on
> all that investment. I promise it's not all as trivial as SETF of ASSOC,
> though...)
If you spent 6 months on it, I'd hope not ;-)
In article <raffael-430DFB...@lrnws01.ne.mediaone.net>,
Raffael Cavallaro wrote:
> In article <slrn9u72i...@oscar.eng.cv.net>,
> ma...@oscar.eng.cv.net (Marc Spitzer) wrote:
>
>>then why did you attempt to set your self up as a tin pot censor with
>>your moralistic garbage post?
>
> You don't understand what the word "censor" means. A censor has the
> power to edit, or prevent the publication of something he doesn't
> approve of. John Foderaro has no such power, that's why he's telling you
> that talk of "censorship" makes no sense. He's only expressing his
> views. He thinks people should be less abusive. That's his opinion, but
> it has no binding force, so it can't possibly be considered "censorship."
>
first "tin pot" when used as I did means not realy there, ie tin pot
dictator. This is the orignal unedited paragraph:
then why did you attempt to set your self up as a tin pot censor with
your moralistic garbage post? And you were trying to censor through
the applacation of social pressure. By posting your message you were
fisshing for support and trying to polarize comp.lang.lisp into the
"good guys" and the "bad guys", and you get to "lead" the "good guys"
against the "bad guys" in a moral crusade to cleans CLL, for the
greater good of course. And trying this tactic against Erik is just
moronic, yes this goes beyond stupid, unless you are just picking a
fight so you can form your group and chastise us offensive heathens
into line. That is still pretty stupid.
Now in this paragraph I think I did demonstrate a grasp of the fact
that John F. lacks the authority to be a "real" censor even though he
was trying to get there by other means. At least until you edited out
all the supporting text.
>
>
> In article <slrn9u6rc...@oscar.eng.cv.net>,
> ma...@oscar.eng.cv.net (Marc Spitzer) wrote:
>
>>In the worse case when you have a choice between assholes and censors
>>you should always choose assholes, they make better neighbors. I am
>>not saying Erik is an asshole, just to be clear.
>
> Well this is damning with faint praise if I ever saw it.
no That was just a statement of fact for the anti Erik club that is
all.
>
> Raf
>
> --
>
> Raffael Cavallaro, Ph.D.
> raf...@mediaone.net
Well now lets move on to some comments on the quality of your work
here. It realy is substandard in my opinion. Since you have a phd
according to your sig I can only assume you have some formal training
in using the written word to prove a point, your dissertation. Now
with all this training and experience, 4+ years, could you not do a
better job with this post of your? Could you not respond to the
points raised in the paragraph instead of just cutting them out as
something you did not have an answer for? You are trained to do so
much better then this. Why not use this training and raise the bar of
this discussion. At least in the future do better then an above
average college freashman. I much prefer discussing things, friendly
or otherwise, with people who make me work hard and learn to make and
defend my point. I prefer this for the simple reason that win, loose
or draw I will always learn something and/or improve some skill with
the exchange. This makes me a better educated person and I like
that.
marc
> In article <87itckg...@asaka.latnet.lv>, jo...@latnet.lv says...
> > Yes. See section 1.5.2 of The Standard. Unless your programs include
> > the definition of if* macro they are non-conforming.
> >
>
> What are you talking about???
That you are completely free to define an IF* macro or any other macro
in your code as you like but that publishing major pieces of source
code that use IF* without defining it or refering to a definition
gives users of the particular implementation you help to maintain the
impression that it is standard. This does fracture the CL community.
We went over all of this the previous time. You didn't acknowledge any
arguments or points except your own last time and you probably won't
this time so I'll drop this mess now.
--
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
>>> Don't you think there is a big difference between a pervasive control
>>> flow construct and functionality that is not included in the standard at
>>> all?
>>>
>
> In the case under question the difference is obvious: the control
> flow construct is no impediment to porting the code, the
> non-common lisp functionality may make porting extremely difficult.
>
> Are you implying by your question that if I came up with a new
> control flow construct that require special runtime system support
> (and thus only worked on ACL) that you wouldn't mind if I use
> that pervuasively throughout my code? In other words you're willing
> to allow me to use any amount of non-common-lisp code but are unhappy
> when the common lisp macro facility to write something that is
> in fact totally portable??
>
>
>
>>> True, but the cost of making it an order of magnitude easier is small.
>
> ok, I'll ask Jochen Schmidt: If I had included the source to if*
> with AllegroServe would it have made the port to LispWorks an order
> of magnitude easier?
Hehe - no certainly not a magnitude ;-)
I think Chris Double who had the first port of AllegroServe (on Corman
Lisp) working agrees too that IF* was no real problem for porting
AllegroServe and I think we should honor the work John did with
AllegroServe particularily that he made it public under a well suited
license. (Btw. the extended Reader conditionals of ACL was by far more
hassle while porting than IF*...)
I did and do not like IF* because of stylistic issues and
because I see no gain for _me_ but this does not mean that I would go so far
like claiming the creation and usage of IF* would be morally wrong to
anyone. The only thing I really do not like is forcing others not to use
facilities they like (this counts _for_ and _against_ John).
You said that you cannot really force anyone to use IF* but I wonder how you
would react if I would offer you some code for AllegroServe that would
contain IF, WHEN, UNLESS, COND or probably the extended LOOP? Would you
take it? Would you change it to IF* and simple LOOPs before adding? Would
you say me I had to rewrite it using only IF* and simple LOOP?
> We in fact wrote (and I think still distribute) a Lucid compatibility
> package for those who want to port from Lucid Lisp to our lisp, as just
> one example.
>
> This is simple software engineering based on the reality that exists
> today. Franz may write a Lispworks to Allegro compatibility package and
> the Lispworks folks may write an Allegro to Lispworks compatibility
> package.
It may be interesting to note here that Portable AllegroServe already
contains such a package (called ACL-COMPAT). It offers the ACL style
socket API, multiprocessing API and some other stuff (including IF*)
for at least LispWorks and CMUCL so far.
I do not claim that the package provides the complete ACL API but it is at
least enough to get AllegroServe (and some other packages) running.
> To be honest I haven't seen concerned raised by many people.
> And for some people I think they are arguing in principle rather than
> any experience. I say that because a grep through AllegroServe
> shows the following internal macros used that no one has
> ever complained or asked about:
> excl::atomically
> excl::with-dynamic-extent-usb8-array
> excl::fast
As I already said - most of this things were no real problem while porting.
The biggest problems were things like the bivalent socket support or
differences in multithreading APIs.
>>> What about 2(a). Do 2 and include the code for if* and any other
>>> logically significant macros and functions you use?
>>>
>
> I already direct people to the if* macro in a few places.
> The software engineer in me says the correct place to deal with
> implementation incompatibilities is in a compatibility library.
> I won't promote what I know to be bad design by putting if* in
> the code for each of the packages I opensource.
>
> If people have questions about constructs in the code I opensource
> that don't exist or seem to work on their Lisp they should
> send me email. I'll tell you what it does in ACL.
> I'm not using ACL specific things to exclude other Lisps, I'm
> simply writing the code in what I think is the best way for ACL>
Through my experience in porting AllegroServe I can agree with this.
It was not rocket science to make AllegroServe portable.
There are still some missing things like chunking support for CMUCL,
Unicode, Proxy-Cache and so on.
Well it depends on how central the code is to the functioning of
AllegroServe. The main code has to follow the standard. What good
is it establishing a standard if you don't follow it?.
You may note that one of the example files (puzzle.cl), a very
cool aserve application written by another developer at Franz
(Charley Cox) actually uses when and unless. Some day I plan
on converting that over to use if* but I don't feel
an urgency to do so.
>> Would you take it?
>> Would you change it to IF* and simple LOOPs before adding?
If we assume that you're talking about core AllegroServe code
then I would see converting it over the the standard as a cost
to including the code. If I felt that the cost was low enough
and the benefits high enough then I would take it and convert
it myself. I may not even be able to read and understand
the extended loop code though.
>>Would
>> you say me I had to rewrite it using only IF* and simple LOOP?
If you give me a gift I don't complain about it and tell *you*
to do anything
for me. You may not see your code incorportated in the source I have
though very quickly or even in the same form if I see that I'm going
to have to do a lot of work on it to incorporate it.
And to turn things around, you have distributed code yourself
for various things. My response is simply "Thank You". I'm
never going to look at your code and tell you that you better
change it so that it's more readable to me or that it use only
standard Common Lisp forms. If you've invented some new interesting
macros, especially for control flow, I'll study them to see if
you've discovered something that I'd find useful myself. Even if
I don't like it (of even if I despise it) I won't tell you to
change it. It may be that due to your style I may not
be able to use the code as much as if it were written in a
style I like, but that's all on me. You take no blame for that.
> The difference, however, is that most modern implementations of, say,
> C, are pretty much identical from the programmer's point of view. In
> most cases, C code that is efficient under both gcc/x86 and
> SunPro/Sparc will be efficient on all (modern) platforms.
Uhhh? If C is so portable, why is there configure, automake,
autoconf and/or makemake and xmake and the whole smeary mess of
bodging make files to work on different platforms?
Even within a single implementation of c, gcc say, to get stuff to
build you need to spend 10 minutes running scripts to ferret around
and find out what is the state of the system (sic).
:)w
> Juliusz Chroboczek wrote:
>
> > The difference, however, is that most modern implementations of, say,
> > C, are pretty much identical from the programmer's point of view. In
> > most cases, C code that is efficient under both gcc/x86 and
> > SunPro/Sparc will be efficient on all (modern) platforms.
>
> Uhhh? If C is so portable, why is there configure, automake, autoconf
> and/or makemake and xmake and the whole smeary mess of bodging make
> files to work on different platforms?
Well I think one can not blame for it. But the bunch of libraries. If
I used e.g GTK+ this is not standardized so it has to be checked. If
you were able to stick to C entirely there won't be the need for such
tools.
>
>
> Even within a single implementation of c, gcc say, to get stuff to
> build you need to spend 10 minutes running scripts to ferret around
> and find out what is the state of the system (sic).
Well isn't it nice that there are such tools? Guess if something
simular would exist for Common Lisp...
Regards
Friedrich
> Will Deakin <aniso...@hotmail.com> writes:
>
> > Uhhh? If C is so portable, why is there configure, automake, autoconf
> > and/or makemake and xmake and the whole smeary mess of bodging make
> > files to work on different platforms?
> Well I think one can not blame for it. But the bunch of libraries. If
> I used e.g GTK+ this is not standardized so it has to be checked. If
> you were able to stick to C entirely there won't be the need for such
> tools.
No one would complain if it was only such inherently problematic
components as GUI toolkits, etc. But autoconf and friends were
invented to solve much more low-level problems, namely the large
differences in C runtime libraries, even within one OS family, namely
Unix and friends.
So yes, if you are able to stick to C entirely (possibly even
excluding standard mandated stuff in the support libs), then you will
be fairly portable, except of course that you still can't write MD5
portably, since you still don't know how to specify that you want to
work on 32bit integers (is it unsigned int, or unsigned long, or both
or neither). And you can't write anything that does more interesting
things than MD5, since that brings you into the land of OS and libc-
dependencies.
At least Common Lisp allows you to write MD5 portably, even if not
portably efficient.
> > Even within a single implementation of c, gcc say, to get stuff to
> > build you need to spend 10 minutes running scripts to ferret around
> > and find out what is the state of the system (sic).
> Well isn't it nice that there are such tools? Guess if something
> simular would exist for Common Lisp...
For most things it does: It is called the vendor or implementor of
your Common Lisp implementation, who has the unenviable task of taking
all the randomized crap that is called an API (implementation) today,
and presenting to you a half-way sane and portable interface to the
underlying functionality, either as part of the ANSI CL part of his
implementation, or as part of extended functionality.
It isn't differences like CAPI vs. Common Graphics that autoconf and
friends were designed to handle (they can't), but differences like
"which libraries are needed to get access to BSD sockets, without
breaking other stuff", "in which order do we need to link those
libaries", "which header contains which of 10 variants for a certain
flag we need", etc. Consider the following very small excerpt from a
real-life configure script:
# lie...@skyler.mavd.honeywell.com says without -lsocket,
# socket/setsockopt and other routines are undefined under SCO ODT
# 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary
# on later versions), says si...@lia.di.epfl.ch: it contains
# gethostby* variants that don't use the nameserver (or something).
# -lsocket must be given before -lnsl if both are needed.
# We assume that if connect needs -lnsl, so does gethostbyname.
echo $ac_n "checking for connect""... $ac_c" 1>&6
And this is but the comment of one of several tens of tests only to
get access to the correct versions of connect, gethostbyname, etc. on
the various Unices that purport to implement BSD sockets. And that's
just purely syntactical differences on Unix. Then go talk to one of
the Netscape engineers who had to make all of the differences in
semantics and syntax disappear on X versions of Unix and Windows and
the Mac...
Now take a look at the socket interface presented to you by your
vendor, or even the 5 socket interfaces presented to you by all
vendors, and be very happy...
For example our in-house HTTP/1.0+ server code base, which only
comprises HTTP-related functionality[1], no HTML-specific stuff, etc.,
weighs in at 4KLoC, yet it has remained portable to any ANSI CL
implementation that offers access to sockets connections via streams,
and offers some form of MP. Of the 4KLoC code base, only 200 LoC are
implementation dependent, which comes out to around 50 LoC for each
supported implementation.
It should now become apparent that we don't _need_ autoconf and
friends, and lucky we are that we don't.
Regs, Pierre.
Footnotes:
[1] Including full MIME support, including lazy MIME/multipart
handling, but excluding HTML generation or parsing stuff, or
anything else content-related.
--
Pierre R. Mai <pm...@acm.org> http://www.pmsf.de/pmai/
The most likely way for the world to be destroyed, most experts agree,
is by accident. That's where we come in; we're computer professionals.
We cause accidents. -- Nathaniel Borenstein
EN> I also wonder what "efficient" means to you, and how you determine when
EN> you have achieved it. It is not an absolute term.
Fair point. In the context of the discussion started by F.-R. about
implementing MD5, efficient means ``within a factor of 2 of well-writ-
ten, mostly-portable, unsafe C code compiled with maximum optimisation
using a decent C compiler.'' I think that's a fair target for judging
an implementation of a real programming language (be it Common Lisp,
ML, or something else).
Of course, in practice ``efficient'' often means ``fast enough to be
painless on the slowest machine I currently have access to.'' I am
glad to say that every single native-code Common Lisp implementation
is ``efficient'' in that sense for the type of programs I tend to
write.
(Two exceptions to the above: when doing intensive text I/O (e.g. ge-
nerating complex PostScript figures), or when running into problems
with the interaction between the GC and the underlying VM.)
(And yes, I do bind *PRINT-PRETTY* to NIL.)
Juliusz
Tim Bradshaw:
TB> And again for the more common kinds of programs (in C as well as
TB> Lisp) that do complex data structure bashing and lots of pointer
TB> chasing, and other operations which don't map trivially onto
TB> machine operations, the performance tends to be dominated by
TB> algorithms rather than by some low level question of
TB> implementation.
I think you're changing the domain of discourse here. The original
issue, as raised by F.-R., was whether it is possible to write Common
Lisp code that is in the same ballpark as C, for the particular class
of problems that C is good at. I'm arguing that this is sometimes
difficult.
I am not arguing whether this is significant -- in fact, I am more
than happy with the performance of all of CMU, ACL and LW[1] on the
type of programs that I tend to write, and even CLISP is usually good
enough.
TB> Of course there are counterexamples - md5 might be one (though I
TB> question its portability in C since it depends very much on
TB> integer sizes and so on).
I fully agree -- whence my insistence on ``modern architectures'',
which tend to have pretty uniform integer sizes.
#if (sizeof(unsigned) < 32)
#error "Please buy a new PC"
#endif
TB> But is it portably efficient for, say, large array-bashing code
TB> which represents the kind of things people do in the real world
TB> that can be mapped efficiently onto machine resources? I suspect
TB> it really isn't - you need to know a whole load of stuff about
TB> really low-level details like what floating-point registers there
TB> are and how big cache lines are and all sorts of really obscure
TB> things.
Floating-point code (which I'm not competent to discuss) put aside,
though, on most modern machines micro-optimisation consists in minimi-
sing the number of non-local memory accesses. While the precise defi-
nition of ``non-local'' is hardware-dependent, you won't go wildly
wrong by minimising memory accesses in your code.
In C, I know exactly how an ``unsigned[1024 * 1024]'' is going to be
laid-out, and that accessing an element will cost exactly one memory
access. There is no portable way in Common Lisp to ensure that any
form of array-bashing code will not be doing non-local pointer chasing
-- I have to know whether my implementation is going to specialise for
the type of simple-vector element I happen to be manipulating.
To be fair, though, all the implementations I know do specialise for
BIT, FIXNUM, and (UNSIGNED-BYTE 32), which turns out to be good enough
for the type of code that I tend to write.
Another sore point is that there is simply no way in any Common Lisp
implementation that I know to manipulate an array of structures (as
opposed to an array of references to structures). Thus, you either
pay an extra memory reference per element field access, or use a
structure of specialised arrays (together with some macrology), which
does minimise the number of accesses but perturbs their locality.
Juliusz
[1] One thing that annoys me with both commercial implementations is
the fact that by default they produce incorrect code when SPEED=3 and
SAFETY=0: they silently assume that the result of an arithmetic
operation on fixnums operation is going to be a fixnum. You can turn
this ``feature'' off, of course.
But those tools are precisely what makes C portable. Ironic, eh?
No responsible Open Source programmer fails to take these tools into
account when programming. Writing fully portable code using these tools
is considered the mark of a conscientious, caring, professional C author.
It takes great effort, but in the end, it is worth it because the whole
Open Source world has actually learned to cope with its portability
issues. In the Common Lisp world, however, at least one Open Source
author thinks conscientiousness, caring, and professionality is a waste
of his presumably exceptionally precious time. I find this very sad, but
more, an insult to the community. Caring about one's own values is good,
but when it means not caring about those of others, it becomes bad, and
one has to wonder what the purpose of "sharing" code really is.
> Erik Naggum:
>
> EN> I also wonder what "efficient" means to you, and how you determine when
> EN> you have achieved it. It is not an absolute term.
>
> Fair point. In the context of the discussion started by F.-R. about
> implementing MD5, efficient means ``within a factor of 2 of well-writ-
> ten, mostly-portable, unsafe C code compiled with maximum optimisation
> using a decent C compiler.'' I think that's a fair target for judging
> an implementation of a real programming language (be it Common Lisp,
> ML, or something else).
I'm not going to quible about the utility of such a definition of
effcient. Prompted by a related query from F.-R. on his MD5
implementation on cmucl-help, I have revived a silly implementation I
had done some time ago, and -- incorporating advice and information
contributed by other developers and users on the mailing-list -- tuned
it for CMU CL in such a way that it runs within a factor of 1.15 (on
an UltraSPARC 10) to 1.5 (on an AMD K6-2/550) to the native md5sum
implementations on files of between 40-60 MB in size. Total invested
time is about 4-6 manhours.
The implementation is available from http://www.pmsf.de/pmai/MD5.html
It consists of around 500 LoC and should work in all conforming CL
implementations. Since it uses arithmetic on (unsigned-byte 32)
values, it will only work efficiently in implementations that support
unboxed operation on such values. It could also be tweaked to work
efficiently on implementations, like ACL, that provide unboxed
operation on (signed-byte 32) values. For other implementations it
would probably be preferable to switch to a 16bit implementation
strategy.
So is CL portably efficient? No, the code uses 18 conditionals to use
special CMU CL features for performance or flexibility reasons, and as
told above, it depends on implementations offering unboxed operation
on (unsigned-byte 32), which not many implementations do.
OTOH, it was possible to write a portable MD5 implementation, that
will work on all compliant CL implementations. The standard C
implementation will _break_ on anything that doesn't offer
a 32bit integer type (it doesn't have to, but who cares about
portability when writing in C? Very, very few, IMHE).
I still think that MD5 as defined in RFC 1321 is not a very good
test-case for the portability of efficiency: It is a very simple
program, that heavily depends on modulo 32bit arithmetic and
bit-diddling, to the exclusion of everything else. Normal
applications, even those with heavy numeric parts, don't do this kind
of stuff...
Just take a look at the huge variation in performance of malloc
implementations of various platforms, to see how unportable dynamic
memory performance is across C implementations, something that is far
less the case with CL implementations, in my humble experience.
Regs, Pierre.
> The standard C implementation will _break_ on anything that doesn't offer
> a 32bit integer type
Modern C standards standardizes such a type, when available.
In C99, #include <stdint.h> uint32_t foo;
The only C targets that don't have 32-bit integer types
are small embedded systems that don't run CL either.
So, for all that matters, this point is moot.
> Just take a look at the huge variation in performance of malloc
> implementations of various platforms, to see how unportable dynamic
> memory performance is across C implementations, something that is far
> less the case with CL implementations, in my humble experience.
Granted. On the other hand, C has plenty of malloc libraries to choose from,
so you can pick one that fits your needs (including Boehm's GC).
For high-level languages, an interesting approach to memory management,
that seems to give the best of both world, is that of the ML-Kit with regions:
the compiler does efficient static allocation where applicable, dynamic
allocation otherwise, seamlessly. It requires static analysis that isn't
possible in CL, though, unless you add lots of declarations (and I'm not
sure the standard declarations suffice). Maybe some LISP implementation
targetting real-time control will pick up on such technology.
Yours freely,
[ François-René ÐVB Rideau | Reflection&Cybernethics | http://fare.tunes.org ]
[ TUNES project for a Free Reflective Computing System | http://tunes.org ]
Politicians are like diapers: they must be changed often.
And for the same reasons. [Also, adults don't need either of them. -- Faré]
Which is pretty clearly your way of saying that it took you a day come
up with a post that blithely ignores your original use of the word
"censor." But let's refresh your memory:
In article <slrn9u6rc...@oscar.eng.cv.net>,
ma...@oscar.eng.cv.net (Marc Spitzer) wrote:
>I have one question, when were you elected the group censor? I did
>not vote for you or even see a ballot with your name on it.
No use of the colorful "tin-pot." You called John Foderaro a "censor."
Later, after he correctly stated that he was just expressing his
views, and not censoring anyone, you wrote a second post, in which you
called him a "tin-pot censor."
>Could you not respond to the points raised in the paragraph instead
>of just cutting them out as something you did not have an answer for?
Or even better still, just ingnore an entire post altogether. So much
easier than a "deliberate edit for content."
Raf
No I was kinda busy so I was thinking about it when I did my other
stuff and you are quoting a different post of mine, not the one we
were discussing. Now I am going to repost a chunk of the last post I
posted in this thread:
here is the mesage id: slrn9upk4k...@oscar.eng.cv.net
###start
In article <raffael-430DFB...@lrnws01.ne.mediaone.net>,
Raffael Cavallaro wrote:
> In article <slrn9u72i...@oscar.eng.cv.net>,
###end
so that is where tin-pot came from, for the purposes of this
discussion, you brought it in by quoting an old post of mine. I realy
have to hand it to you. You are putting me in my place with your well
formed arguments and your perfect grasp of logic.
>
> In article <slrn9u6rc...@oscar.eng.cv.net>,
> ma...@oscar.eng.cv.net (Marc Spitzer) wrote:
>
>>I have one question, when were you elected the group censor? I did
>>not vote for you or even see a ballot with your name on it.
>
> No use of the colorful "tin-pot." You called John Foderaro a "censor."
> Later, after he correctly stated that he was just expressing his
> views, and not censoring anyone, you wrote a second post, in which you
> called him a "tin-pot censor."
>
no I did not, I posed a question to him because he was acting as if he
was granted some kind of licence to behave as some kind of censor.
eather through some real licence or grant or as voice of some kind of
"moral force". In previous posts John F. got caught making clames
that were not true. Because of this repeated moralless behavior on
his part I have much less tolerance for him then I would have for
someone who has not *earned* such a reputation. I am old fashioned, I
considder dishonesty a choice not a mistake. And I have acted as I
feel proper in responce to John F.'s choice to be a dishonest person.
I am not making any comment on his code just his choices.
>>Could you not respond to the points raised in the paragraph instead
>>of just cutting them out as something you did not have an answer for?
>
> Or even better still, just ingnore an entire post altogether. So much
> easier than a "deliberate edit for content."
>
> Raf
Now why should I be silent when you are engageing dishonest behavior
that could damage my reputation in this group? I am perfectly capable
of damaging my own reputatoin with out the help of some dishonest
asshole. The thing is I try not to, I try to do what I think is the
right thing. Now I have been wrong and have been mistaken and have
been held accountable by the people I have damaged unintentionally and
promptly appoligized where I agree the mistake was mine.
One question, if I may? Where did you get your PHD? based on your
skill arguing things it may be a place best avoided if I ever go back
to school for an advanced degree.
marc