A function is a value. eg. (lambda (v) v)
gets evaluated to a function object. Often functions are bound to variables. eg.
(define identity (lambda (v) v))
(define num 19)
identity
is a variable, the same as num
is but the values they become when variable is evaluated are of different types. One is a function (aka closure, procedure), the other a number. All variables can be evaluated:
+ ; ==> #<procedure:+>
#<procedure:+>
is a visual representation of the core function commonly named +
in racket and Racket mentions the name even though the name is irellevant. You could do this:
(define my-add +)
(my-add 1 2 3) ; ==> 6
A Predicate is a function that returns a boolean #f
or #t
and often they have variable names ending in ? as a convention, but it is not enforced. The language doesn't have any opinion on this so it is treated like any other function by the implementation. I've seen predicated not using the convention as well ad bad code using a predicate naming scheme to something that isn't a predicate at all. The last one is actually worst of the two.
Whenever you see a variable with parentheses, like (want num)
you know that either want
is a function and takes num
as argument or want
is something else and the program will fail miserably. Thus while Scheme does not type check it will fail when you try something crazy like (num identity)
. You'll get an error saying that the application went terribly because num
was a number and not a function.
So to your code. The programmer should perhaps made the variable name conformant to the suggestion that it is a predicate. This does not change the code the slightest, but aids reading it. Like this:
(define (arghelp predicate? value call)
(if (predicate? value)
value
(value (error "Invalid value" value predicate? call))))
This still looks bad. We know that value
isn't a function from it's use. Also the nature of it's use is to signal an error and what it returns isn't important. Lets fix that. I suggest it should be written like this instead:
(define (assert predicate? value call)
(when (not (predicate? value))
(error "No" value predicate? call)))
In the helpers you see it does:
(assert integer? p take-help)
I've renamed the function to my better name. By using substitution rules we know this would be the same as writing:
(when (not (integer? p))
(error "No" p integer? take-help)))
Now your posted code split
is strange since it checks for numbers where frmo looking at it it will never ever be anything else. What it doesn't check is if l
is a list so that we can be sure length
doesn't fail. Thus both calls to check for numbers can be removed and I suggest this instead:
(assert list? l split)