Hmm... so you're thinking of renaming testify to fun or asfn? I don't know if testify is general enough to earn one of those names. Aren't there other common utilities that turn expressions into functions, like thunk?
Have you considered testifn?
Update: Here are some other naming possibilities you made me think of, though I'm not sure if/where they fit in:
- fnify
- fnize
- fnk (sounds like "thunk")
To be sure, I do like your asfn, I just don't think testify is the right fit for it.
Aren't there other common utilities that turn expressions into functions, like thunk?
Well, thunk creates a function out of code, but I'm not aware of any other function that turns data into functions.
In wart testify is now generic. If it sees a non-function by default it compares, if it sees a function it returns it, and if it sees a list it checks for membership.
In Penknife I've been mulling over 'testify a lot, trying to figure out whether there's a way to stop special-casing the 'fn type or to make it an everyday coercion function by introducing a 'test type or renaming it to 'fnify. I think I have the start of some answers....
Recently I posted an example utility, 'copdate, that acted exactly like 'copy but called functions on the existing values to get the replacement ones. http://arclanguage.org/item?id=13652
It would be cool if 'copy itself did that. Essentially we'd check the replacement value, and if it was a function, we'd treat it as a conversion function, and otherwise we'd just use it directly. This check could be done by a satellite utility:
(def conversionify (x)
(case type.x fn x [do x]))
This is just as arbitrary about the 'fn type as 'testify is, and it has just as much right (IMO) to be called 'fnify. But now we have two cousins, so we can extract their common warts into another function:
(def abehavior (x)
(isa x 'fn))
(def testify (x)
(check x abehavior [iso x _])) ; not using 'is here!
(def conversionify (x)
(check x abehavior [do x]))
This 'abehavior utility is naturally extensible. Its default behavior can be nil, and each of its extensions can return t under new conditions. The question "Is this type of value supposed to be idiomatic for specifying custom behaviors for everyday Arc utilities?" isn't hard to answer. A behavior will need to have a 'defcall implementation anyway, so that's a good way to decide (but not perfect, 'cause indexable data structures use 'defcall too).
Also, 'testify and 'conversionify have a kinda nice common semantics: Each of them coerces to the behavior "type" based on its own idea of what a normal behavior is.
Is there a way to expose a design flaw in between 'abehavior and the places it's used? What if there's a type of value that's especially good at encoding tests or conversions, but not idiomatic for specifying callbacks? In fact, you've already mentioned one:
if it sees a list it checks for membership
I totally agree. I really like how Groovy's switch statements have that behavior. XD However, what's to say a list is an idiomatic way to give a list of options but a string isn't? Well, maybe I'd go with another function:
However nice (or paranoid ^^ ) this setup might be, what happens if you're looking for nil? Should nil be interpreted as an unsatisfiable condition? Well, that's probably not too bad; it's up to the utility designer to say what nil does, and we're in that realm at the moment. People will just have to say (some [iso x _] foo) instead of (some x foo) if x could be nil, even if they don't expect x to be any other kind of container or behavior.
Hopefully this rant has helped you nearly as much as it's helped me. :-p