[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Slow response about if, bind and tables
> this [if] macro clashes with the Scheme language standard: keywords
This is a clear design principle, case closed.
But what about => in cond? I do not wish to complain. It's a usefull
feature that I use often, and I do not have a better idea. Anyone care to
give a rational?
> There are two ways to fix this clash that I can think of:
> - Change the name of your macro. If T were case-sensitive like franz,
> you could do what Foderaro did, and call yours "If", not "if".
> But it isn't. You could call it "iph", which is gross. Better
> names fail me.
> - Leave poor IF alone, but define THEN and ELSE to be macros synonymous
> with BLOCK. John Ellis does this with his lisps. Now your IF is
> implemented in a manner consistent with the standard IF.
> Actually, ELSE is a standard T identifier, so maybe you ought to
> use THEN and ELS. Or something.
I think it is a bad idea to use case or non-standard spelling to
differentiate variables. This is very error prone. It is to easy to type
ELSE when meaning ELS, etc. Don't forget, that variable names used in T are
based on English sematics. The closer the argeement, the less the
I did consider the Ellisp approach, but I opted for a bit restiction on the
use of THEN and ELSE. Note that the Ellisp approach does not get around the
function named THEN problem. Try defining a function called ELSE. It is
too bad that T chose ELSE instead of OTHERWISE.
> I should apologize about BIND's misleading name -- it doesn't bind the
> variable (like DEFINE, LAMBDA, and LSET do), it does a temporary assignment.
T's BIND could be renamed SHADOW.
> However I think it would be a good idea to have a way to bind a variable
> without assigning it. MIT Scheme does this with the syntax
> (define foo)
> and in T this would want to be written as
> (lset foo)
> instead (because SET!, and therefore BIND, is in principle illegal on
> variables bound with DEFINE -- an unfortunate incompatibility with R^3
If I Could then write (define foo) and not undo the effects of a previous
assignment to foo, this would be just fine.
> No, you don't need two tables, you just need some distinguished object to
> represent a false entry. And you needn't modify the source if you
> simply shadow T's definition of TABLE-ENTRY.
OK, I could use the symbol NIL for (), or better yet when #f and () are
nolonger the same I can usually map on to the other. But wait, did we
separate these concepts for a reason? Sorry, I'm being facetious, but you
still have to check everything going into or coming out of the table for
this "distinguished object" or #f and convert it to the other.
"Modify the source" was a bad choice of words; read "reimplement table stuff".
> I consulted with the person who wrote the table package and it seems
> that it's an error to modify a table while it is being walked. That it
> sometimes works is gratuitous. Unfortunately it would be prohibitively
> expensive to detect this error situation; tables must be fast. And to
> change this would require that WALK-TABLE in effect copy the table
> before it starts walking; that would make WALK-TABLE too expensive.
> This restriction should definitely be documented.
> I recommend that you create a brand new table when you want to do
> something like this, and let the old one be gc'ed.
I am writing an interactive graphics program and shudder to think of letting
anything just be gc'ed! Besides, copying the table is overkill. Let me
suggest that the reasonable thing to do is retrict table modifications to
1) changing the value of the current key, and
2) deleting the current key from the table.
Changing the current key works as is because the table size doesn't change.
(I do not consider (set (table-entry foo) nil) to be in this case because it
is really a remove-table-entry in disguise.) Deleting the current key can
be done by BINDing REMOVE-TABLE-ENTRY or in this case the SETTER of
TABLE-ENTRY to a function that puts a distinguished undefined value in the
value position for the current key and delete them all at the end or adjusts
the current position in the array to account for the deleted key. In this
way almost no overhead is incured for walks that don't use these features.
Supporting both of the above is independent of how entries are delete. If,
however only 1) is really needed, it comes for free if
(set (table-entry foo) nil)
does not really mean REMOVE-TABLE-ENTRY. For whatever it's worth, CL
supports both and no more.
Are methods in a object really found using SELECT or is this just for
interpreted code? Is there any performace penalty for listing a method last
in an object instead of first? All my draw methods are listed last!