You tell me equality is extensible, and now I know that, and I go look at that page and scan it from top to bottom. I do the usual things I do to read stuff online, and I've been pretty successful with my reading, my reading comprehension scores were excellent in standardized tests, I have a phd that was about nothing if not reading opaque publications, and now I'm faced with this page and I still have no idea how to tell that equality is extensible, or how to go about extending it. If you hadn't told me I'd look at that page about booleans and have no reason to expect it to bear the slightest relationship to equality for complex user-defined data structures[1]. Search for 'extensible'. Nope. Oh, 'inspectable structures.' What the sam hill are those? It has to do with prop:equal+hash, which doesn't even look like a single token to my eyes. Is it a function? How do I use it? All this goes through my mind in a flash, and all I feel is stupid.
I keep waiting for the racket reference to gradually become clear, but it's been a year now of poring over it and I don't think it'll ever happen. It's a blind spot, platform nine and three quarters, just around the corner but at ninety degrees from all three dimensions that I can see. I would never ever have noticed that equality is extensible until you told me that was so.
[1] I scan back up and it's right there in the title: "Booleans and equality." See what I mean about feeling stupid? Why should booleans and equality be grouped together? Why should equality be in the section on datatypes and not say structures?
0. Note that the actual link is broken -- it's missing a ")" in the end
(it's there, but it wasn't included in the url for some reason (I
don't know about the local markdown language...))
1. Yes, some of these issues are known, and we're in a constant race
with improving the documentation in various ways. As always, emails
to the mailing list or bug reports -- or better: suggestions and
possibly patches -- all of these are always welcome.
2. In this particular case, I didn't need to guess -- I knew that it was
added, so I just needed to find that reference.
3. But if I were trying to find it, the first place I'd look would be
the documentation for `equal?' -- and it is indeed there, at the end
of the second paragraph.
4. As for how you use this property, the text that I referred to has a
link to "Structure Type Properties", which describes all of that.
5. Re the organization -- booleans and equality are grouped because
they're related... It also appears as the first subsection in the
datatypes chapter, which makes sense there. If you have an idea how
to organize it better, then see #1.
6. Yes, it would be nice to have some section that lists all of the
properties that could be used for structs. The main problem with
doing this is that it's an open system, so anyone can add more
properties, but it won't make sense for the core to list properties
from modules outside of it. This was discussed recently, and I don't
think that anyone had an idea what to do about it.
"if I were trying to find it, the first place I'd look would be the documentation for `equal?' -- and it is indeed there, at the end of the second paragraph."
Part of the problem is that I never tried finding it, because it didn't occur to me that racket would have extensible equal?
A few months ago I was flattened - absolutely flattened - to find out that PLT has optional args and keyword args. (http://arclanguage.org/item?id=12591)
I have no idea why this is. Perhaps the problem is that people expect scheme to be a small language.
Well, the optionals and keyword arguments have been in for a long time now... In fact, the current thing is a second iteration after a first facility that was more CL-like...
In any case, Racket is certainly not a small language...
Yes, as I was ranting I was feeling bad for not having contributed to improve things. I wasn't being rhetorical about feeling stupid and guilty. Lack of understanding is a barrier but no excuse. For me to say "I have a phd, but this I can't read" is akin to saying "I've learned spanish, but chinese is hard." Well, d'uh. Deal.
Perhaps PLT needs a user guide in addition to a reference, a level of redundancy with a kinda orthogonal organization (focusing on complex tasks involving multiple advanced concepts) that'll help people triangulate on understanding, or just use what works for them.
I'm going to withdraw my rant. It's something specific about my stupidity that's causing me these problems. Still investigating.
Ah, I think I see what's been happening. Since I started out with arc I've restricted myself to the mzscheme 'ghetto' and not paid as much attention to the racket language itself. My attitude was "who knows what works in mzscheme and what doesn't." This has been the root cause of my troubles, I think.
Thanks for the link to Guide: Racket. I've also had trouble getting into Racket's documentation, but this looks like a much more accessible starting point than Reference: Racket.
Given that prop:equal+hash exists, are there any commonly used convenience macros for implementing it for a structure? It's niftiest if they support cyclic structures too, since Racket's equality API makes that possible, but I'm not picky. ^_^ I'll probably just write something myself either way, but I'm on the lookout for inspiration.
Unfortunately, it doesn't do paren- or quote-matching, and it doesn't interact well with the current arc> prompt.
$ racket -il readline -f as.scm
Welcome to Racket v5.0.2.
Use (quit) to quit, (tl) to return here after an interrupt.
arc>
(+ 1 2)
3
arc>
"bad"
"bad"
arc>
(quit)
With access to the underlying Racket, one can (require readline/readline) and do (readline "arc> ") to get the proper prompt, but a) this requires redoing the Arc REPL, either by hacking (tl) in ac.scm or by writing something like (while t (prn:eval:read ($.readline "arc> "))), and b) it still doesn't do the matching, which I find an important feature.
You can do all of these as macros (etc) rather than a compiler. For example, an `fn' macro would inspect the body and plant `nil' return values; for arbitrary `='s see swindle's `setf!', the convenient indexing is easily done with generalized functions, rest notation and destructuring also exist in plt and would be easy to incorporate. The difficulties lie more in the subtle points: for example, plt macros have phase separation, and arc is more lispish with a single phase for everything -- and doing that would be very difficult at best. As another example, mutable cons pairs are hacked onto arc (when using the newer plt versions) in a way that works out because arc is essentially serializing its own lists -- but if you use more plt-isms, and end up using more consed lists, you are more likely to run into problems with stepping over the plt assumption of pairs being immutable.
Fexprs are very different from macros. Not having them is considered by most people as a feature, not a wart. In fact, the common approach to fexprs is a wart. One implication is that eval, as implemented in MzScheme and in Arc is doing the right thing. (And macros are much more well behaved than fexprs, which keeps the language sane.)
I don't follow. Are modern lisps not using f-exprs?
If so I have been imprecise. I was using Alan Kays quote to refer to lisp's special-forms and their many rules on what gets evaluated in what position when.
No, modern lisps don't do that. (Except maybe for newlisp, which does what you'd call "the right thing" with `eval`, and even encourages doing so; but this goes with the fact that it throws lexical scope out the window.)
As for the quote, it depends on how you view it. You can take it anywhere to proper criticism of fexprs (which has become the popular view since then), or you can take it as criticizing the fact that special forms are needed, or if you squint hard enough, you can say that it's advocating a language like Haskell. Considering the first two options, I think that the first one (criticism of fexprs) is very explicit, the second one is less likely.
In any case, trying to get an `eval` that works with lexical scope is related to fexprs. So the feature that you want is one that Kay criticizes.
You could come up with a new "subtype" of symbols which is reserved for gensymed symbols -- then use some mapping of unique names for new such gensyms (say, a counter), and then use some new syntax like `__name' to evaluate to these things (assuming that you want code to be able to write such gensyms literally)...
But doing all of that is equivalent to just creating gensyms as done now, with a `__' prefix -- so if you really want that last property then nothing needs to be changed (perhaps only the `gs' prefix)...
Well, custodians are not really a workaround -- they're intended just for situations where you want to close up all resources that belong to a server thread, for example.
But in any case, I don't know about such a leak... AFAIK, if you're closing the port, then everything should work properly. Is there some example code that shows the problem? (Better to mail me, btw, since keeping track of this thing is difficult and there's no email alerts...)