Reputation: 339
I am new to Scheme and this is homework, so I am asking for hints rather than whole solutions. I am writing a procedure called type-checked that takes as arguments a procedure and zero or more type predicates. The value of the procedure is a variable-arity procedure: If its arguments match the corresponding types given to type-checked, then it returns the value of the procedure called on the arguments. Otherwise, it reports an error.
I have this procedure working for something like this:
((type-checked sqrt number?) 100)
But not for this:
((type-checked + number?) 1 2 3 4 5)
That is, I can run the procedure correctly with one argument, but not a variable number of arguments. Here is the pertinent code:
(define (type-checked procedure types)
(lambda args
(if (types-match? (list types) (list args))
(procedure args)
(error "type mismatch"))))
If I enclose args with parentheses, I can run it on one argument. Otherwise, I always get the type mismatch error.
Here is the recursive procedure that type-check calls. It checks to see if the types given match the arguments. I know it is not optimized, but for now my goal is working code. types-match? takes in two lists, type predicates and values, and checks to see if they all match. I have attempted to comment it in a way that makes sense. The code below seems to work on its own.
(define types-match?
(lambda (types values)
(if (= 1 (length types)) ;if there is only one type left
(if (null? values) ;if values is empty, finished
#t
(if ((car types) (car values)) ;else, check types with the rest of the list
(types-match? types (cdr values))
#f))
(if (null? values)
#t
(if ((car types) (car values)) ;if there is more than one type in types, call
(types-match? (cdr types) (cdr values)) ;compare with the first type in the list, then call on the rest of both types and values
#f)))))
I am trying to figure out how to accept the variable number of arguments when calling the procedure. Any help is greatly appreciated, and thank you in advance!
Upvotes: 1
Views: 337
Reputation: 48745
types
needed to be a rest argument just like args, since both arguments are always lists of values you don't need to wrap them in lists and you need to use apply
to use a list as multiple arguments to a procedure:
(define (type-checked procedure . types) ; types is a rest argument
(lambda args ; args is a rest argument
(if (types-match? types args) ; both are lists
(apply procedure args) ; (apply + '(1 2)) == (+ 1 2)
(error "type mismatch"))))
I spot that when you do the last iteration of a multiple type argument list it will assume all the last arguments are the last type you supplied. eg. the following will actually work:
((types-match? map procedure? list?) + '(1 2 3) '(1 2 3)) ; ==> (2 4 6)
Upvotes: 2