[plt-scheme] Re: polymorphism of primitive types
Matthias Felleisen wrote:
> On Oct 19, 2005, at 3:04 PM, David Van Horn wrote:
>> Matthias Felleisen wrote:
>>> But it would blow up on this:
>>>
>>> (let/ec jump
>>> (mymap (lambda (x y) (if (= x y) (jump #f) (+ x y))) '(1 2 .
>>> 3) '(1 . 2)))
>>>
>>> Should it? -- Matthias
>>
>> The jump is a red herring here. The function breaks even without
>> escaping continuations:
>>
>> (mymap (lambda (x y) (+ x y)) '(1 2 . 3) '(1 . 2)))
>
>
> There is no proper list so it should throw up.
Right. I misunderstood your original question, but I see what you were
getting at now. I think the answer must be yes, it should. The
arguments don't meet the contract. If we want to allow this sort of
thing, the contract and verbal description of the function should be
changed.
(Moreover, the description of SRFI 1 map explicitly states the dynamic
order in which the procedure is applied to the elements of the list is
unspecified. Your example relies on a left-to-right order to avoid the
improper lists at the tail.)
There are other problems with this contract, eg. the contract diverges
when any of the lists are circular. I believe the correct contract is
as simple as:
;; (Listof X) -> Boolean
(define (pre-mymap argl)
(ormap proper-list? argl))
Where proper-list? is given as in SRFI 1, ie. it returns true iff the
list is of the form:
<proper-list> ::= () (Empty proper list)
| (cons <x> <proper-list>) (Proper-list pair)
To enforce the condition that the procedure has the correct arity, you
can do the following:
(provide/contract
[mymap (->r ([proc
(and/c procedure?
(lambda (_)
(procedure-arity-includes? proc
(length arg-lists))))])
arg-lists (lambda (_) (ormap proper-list? arg-lists))
proper-list?)])
Note that the arg-lists contract is applied to each element. The only
way I could think to state an aggregate property was to ignore each
element and assert the property for the whole list, which means the
contract repeats work needlessly. Is there a better approach?
David