2009/5/24 D.McClain dbm@asyrmatos.com:
Delimiting "monomorphic data extents" speeding up compiled code sounds interesting. Could you please explain what this really means?
consider:
(define (assq-k tag a-list k-fail k-success) ; ML type: symbol -> (symbol . 'a) list -> (symbol -> 'b) -> ((symbol . 'a) -> 'c) -> 'd (cond ((null? a-list) (k-fail tag)) ((eq? tag (caar a-list)) (k-success (car a-list))) (else (assq-k tag (cdr a-list) k-fail k-success) ))
(define (assq tag a-list) ; ML type: symbol -> (symbol . 'a) list -> (boolean | (symbol . 'a)) (assq-k tag a-list (lambda (x) #f) (lambda (x) x)))
In ASSQ-K all of the types are well-determined: there is no additional type checking introduced by its application, because the scope of all introduced type variance is limited to the continuation functions K-FAIL and K-SUCCESS. This is not the case for ASSQ because it introduces a union type which must be subsequently discriminated either by user or run-time system (in the case of an error) code.
Admittedly this is a trivial example, but the principle does scale up to more complicated APIs. I use it heavily in network and DB programming. It also turns out to be a lovely way to design in error-handling at the very beginning of a project - something that *always* turns out to be a pain to retrofit. Using explicit CPS also turns out to be a lovely way to replace CALL-WITH-VALUES because you avoid the extra machinery implicit in the schizophrenic Scheme semantics for that function.
Strictly speaking though, none of this has anything to do with whether a compiler uses a CPS-based internal representation. All of the above has to do with realising and taking advantage of the expressive capabilities of a language with full tail call optimization. Very few people seem to get this, even in the hard-core Scheme world.
david rush