Again in the context of automating tests - is there a sensible way of getting a name-string for a given handler at run-time ?
(Parallel question to
Detecting at run-time how many arguments a handler expects? )
Error-trapping (always the worst way to structure code, but does have some hacky marginal uses) provides an almost-solution, as long as we are testing handlers that don’t have missile-launching side-effects …
Is there a cleaner and more sensible alternative to this kind of thing ? :
(JS functions, for example, have properties like .name and .length (arity), as well as methods like .toString() (source code), which I find I am rather missing in AS, in an attempt to set up a dual-language testing framework for generic functions )
Interim sub-optimal approach – reading error messages:
-- handlerName :: Handler -> String
on handlerName(h)
tell mReturn(h)
try
|λ|()
|λ|(missing value)
on error e
set {dlm, my text item delimiters} to {my text item delimiters, space}
set xs to text items of e
set my text item delimiters to dlm
text 1 thru -2 of (last item of xs)
end try
end tell
end handlerName
-- TEST: What is the name string of a given handler ?
on run
map(handlerName, {hello, succ, min, zipWith})
--> {"hello", "succ", "min", "zipWith"}
end run
-- SAMPLE HANDLERS FOR TESTING -----------------------------------------------
-- hello :: () -> String
on hello()
"hello"
end hello
-- succ :: Int -> Int
on succ(x)
x + 1
end succ
-- min :: Ord a => a -> a -> a
on min(x, y)
if y < x then
y
else
x
end if
end min
-- zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
on zipWith(f, xs, ys)
set lng to min(length of xs, length of ys)
if lng < 1 then return {}
set lst to {}
tell mReturn(f)
repeat with i from 1 to lng
set end of lst to |λ|(item i of xs, item i of ys)
end repeat
return lst
end tell
end zipWith
-- GENERIC FUNCTIONS ---------------------------------------------------------
-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
tell mReturn(f)
set lng to length of xs
set lst to {}
repeat with i from 1 to lng
set end of lst to |λ|(item i of xs, i, xs)
end repeat
return lst
end tell
end map
-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
if class of f is script then
f
else
script
property |λ| : f
end script
end if
end mReturn