I'm having trouble figuring out how to go about creating a function that can take a series of the same function as arguments with the last argument as an operand. For example:
(func sqrt sqrt sqrt 390625)
The call above should return 5 as (sqrt 390625) > (sqrt 625) > (sqrt 25) > 5
I'm having trouble figuring out the exact way I should write this as any way I have tried has given me errors or achieved an infinite loop.
This the code is have so far:
(define func
(lambda L
(cond ( (equal? (length L) 2) ((car L) (cadr L)) ) ;; If the list consists of only 2 elements, carry out the function (element 1) onto the operand (element 2)
( #t (apply (car L) (func (cdr L))) ) ;; otherwise, apply the function (1st element) onto the rest of the list
)
)
)
The first condition works, for example returning 5 if i call (func sqrt 25)
, however the recursive call is throwing errors.
I would appreciate any help with this.
CodePudding user response:
The OP doesn't provide a definition for chain
, so that part is unclear, but I think that a fundamental problem here is that there is no recursive call to func
; further, apply
isn't used in the right position.
Instead of using (equal (length L) 2)
as a base case, it might be nicer to make recursive calls as long as the first element in the input is a procedure, or otherwise just return the element:
#lang racket
(define multi-call
(lambda args
(let ((arg (car args)))
(if (procedure? arg)
(arg (apply multi-call (cdr args)))
arg))))
Here, when arg
is a procedure, then it is applied to the result of calling multi-call
recursively on the remaining arguments. Note that multi-call
takes an arbitrary number of arguments, wrapping them in the list args
. The reduction step provides (cdr args)
, which is a list of the remaining arguments. This means that apply
should be used to call multi-call
on those remaining arguments because multi-call
expects an arbitrary number of arguments, not a list of arguments.
multi-call.rkt> (multi-call sqrt sqrt sqrt 390625)
5