; Write a function, validate, which will check that :name and :glitter-index are
; present when you append. The validate function should accept two arguments:
; a map of keywords to validating functions, similar to conversions, and the
; record to be validated
I assume validate-name and validate-index are functions that return a boolean (true if the value is valid, false if not).
From the requirements of validate it appears that the second parameter to it should be a single suspect, not “suspects” (plural).
What you now want is to extract the value of each key (mentioned in validations) from suspect and then call the corresponding validation function on that value. Then you want to check that all of the validators return true.
Here is one way of defining a key-validator.
(defn key-validator [validators key suspect]
;; First verify that the key exists in the suspect
;; Then call the validator of the given key on the value of the key in suspect
(and (get suspect key) ((get validators key) (get suspect key))))
Clojure’s compiler is single pass, if you want to use a function before defining it, you should declare it. In this case, you could just move the defns upward to before they’re used.
I will then have to experiment with this because both are not allowed to be empty so in your first example the a answer must be false because the glitter-index is missing.
Then you just need to change your validation functions. You could do (and (string? name) (< 0 (count name))) for example. The interesting bit is the validate function itself.
If you want to validate for a set of keys, you basically need to run the validate function for each key.
Also, sorry I had a missing key in the validate fn above.
There you’re iterating over a map, which will give you 2-tuples for your function, so it’s unlikely that it’s doing what you want. The solution I gave you checks that the keys are present, and that the values are valid according to the validator functions you have defined… not sure how much simpler you can have it. You still need to iterate over the keys you want to test, and test that a) the “suspect” object contains the key, and b) that the value is valid according to your validator.
Ok, let’s go by parts. constantly returns a function that constantly returns whatever argument you passed, regardless of what value you pass as arguments. So if you do (def constant-fn (constantly 4)), any calls to constant-fn will return 4, regardless of what you pass to it.
reduce abstracts an important recursion pattern, which is that of “collapsing” the values of a collection into a single value. In this case, it takes the collection of keys you want to test, and checks whether they are al valid in the suspect object. If one of them isn’t, it will end early (by calling reduced) and return false. You could do something similar calling (every? some?... ) on the result of (map (fn[k] (validate validators k suspect)) keys-to-test).
#((get validators %) would then be (get vl %)
an (get suspect %) would get me the value of a key of suspect so that would be the v
so together It would be (#(get vl % v)
but some how that is not working so I make somewhere a thinking error but I do not see where
Perhaps the thing that is confusing is that the anonymous function that is used with every? is not the same function that should be used with reduce-kv.
The reduce function is calling the validator (as you have), but then it has also to check the return value and if it is false, it should return false from now on. For that reason, the initial value for the reduce-kv needs to be a boolean (not a map) - the value that would be returned if there were no elements in the collection passed to reduce-kv.