-
Notifications
You must be signed in to change notification settings - Fork 161
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Lists: proper error messages for linear update procedures
- Loading branch information
Showing
1 changed file
with
22 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8e27b63
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not a good way to do it, there should be one "private" procedure for each pair, e.g.,
delete|delete!
, and the public procedures should call that one procedure and pass the name of the public procedure for the error message.I'll think about it some more.
8e27b63
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that this is not the best way to do it because it creates a lot of code bloat for procedures that are superfluous (because
delete
anddelete!
do exactly the same thing, so a programmer knowing this will likely just use the shorter name). Creating this much bloat just to get the right name in the error messages is not a good tradeoff.What you suggest, i.e. passing the procedure as a
prim
parameter to a common auxiliary procedure, is probably the best solution. It has been used in other places in the Gambit runtime library (see for exampleopen-tcp-client
). It will reduce bloat but unfortunately it will probably impact the execution speed because theprim
parameter may cause stack spilling. Still, probably the right tradeoff here.8e27b63
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Marc: I now think that capturing and replaying the continuation of one of these comparison procedures is a violation of the "linear update" assumption for the
!
procedures, and that the Gambit implementation of these procedures should correspond more with the SRFI 1 sample implementation and not take care that continuations might screw things up. I sent a too-long comment to the SRFI 1 list about this yesterday. BradEdit: There's this patch to chibi, which I find interesting and might be relevant: ashinn/chibi-scheme@967b888 that
8e27b63
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Marc: I've been thinking about an implementation of
filter!
along the lines of SRFI 1's sample implementation with proper error checking.It appears that one wants to check that the
list
argument is indeed a proper list beforeset-cdr!
ing any of the pairs inlist
.That implies at least two passes through the
list
argument, one to check that it's a proper list, the next to actually callpred
on thecar
of each pair to see whether that pair should be part of the result.That may be faster than just calling
filter
, which allocates new pairs, but it's not clear it's worth the trouble.8e27b63
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried checking that the argument is a proper list, and then using Olin's
filter!
implementation:and got, with a very big heap,
So this is noticeably faster than Gambit's implementation of
filter!
=filter
.call/cc
inpred
can screw it up, but I believe "linear update" implies "Don't usecall/cc
inpred
."Should I pursue this?
8e27b63
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the implementation you propose is correct and it would be preferable to
filter!
=filter
.I want to point out that in general it is not possible to check a property of the list (such as being a proper list) and then acting upon that when walking the list because it is not thread safe. This is because there are separate moments when the list is checked for being a proper list and when the list is walked "knowing" that it is a proper list. There could be a separate thread that mutates the list (into an improper list) after the proper list check and before walking the list. So be mindful of this trap.
A typical example is computing the length of a list to make sure it is of length 2, and then doing an unsafe
(##cadr list)
to get the second element. This is not safe because a separate thread could(set-cdr! list '())
just before the(##cadr list)
.I think your code doesn't suffer from that because even if a separate thread mutates the list it will give some coherent result and not crash the program.
Note that your code could be improved by interleaving the proper list check and the walking of the list. The only downside is that if an improper list is detected, some of the list will already have been mutated so there isn't a clean separation between checking that the parameters are OK and doing the requested operation. Note that other Gambit procedures mix type checking and performing the operation:
8e27b63
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm beginning to think that mutation with the goal of "speeding things up" makes "defensive programming" (i.e., correct programming) a pain in the ass,
I've only sorta understood how continuations and mutation interact for about 18 months now, learning how threads and mutation interact is hurting my brain too much.
I decided that this "downside" you mentioned:
is enough reason to keep
filter
=filter!
, as any error message would be referring to an already modified argument and would be impossible to debug.And I'm OK with the code duplication, too, unless we want to refactor to have both
filter
andfilter!
be one-liners that call a procedure##filter
that does all the work and accepts an extra argument for proper error messages.