For example, converting an 'association list' of key-value pairs like:
{{"alpha", 1}, {"beta", 2}, {"gamma", 3}, {"delta", 4}}
to an AppleScript record like:
{gamma:3, delta:4, alpha:1, beta:2}
and also converting from a record to an association list:
AppleScript source:
use framework "Foundation"
use scripting additions
-- pairListAsRecord :: [(Key, a)] -> Dict
on pairListAsRecord(kvs)
script addedToRecord
on |λ|(accumulator, kv)
set {k, v} to kv
mapInsert(accumulator, k, v)
end |λ|
end script
foldl(addedToRecord, {name:""}, kvs)
end pairListAsRecord
-- recordAsPairList :: Dict -> [(Key, a)]
on recordAsPairList(rec)
zip(my keys(rec), my elems(rec))
end recordAsPairList
-- TEST ------------------------------------------------------------------
on run
-- kvs :: [(Key, Value)]
set kvs to {{"alpha", 1}, {"beta", 2}, {"gamma", 3}, {"delta", 4}}
-- ASSOCIATION LIST CONVERTED TO APPLESCRIPT RECORD
set rec to pairListAsRecord(kvs) --> {gamma:3, delta:4, alpha:1, beta:2}
log rec
-- APPLESCRIPT RECORD CONVERTED TO ASSOCIATION LIST
set associationList to recordAsPairList(rec)
end run
-- elems :: Dict -> [a]
on elems(rec)
set ca to current application
(ca's NSDictionary's dictionaryWithDictionary:rec)'s allValues() as list
end elems
-- foldl :: (a -> b -> a) -> a -> [b] -> a
on foldl(f, startValue, xs)
tell mReturn(f)
set v to startValue
set lng to length of xs
repeat with i from 1 to lng
set v to |λ|(v, item i of xs, i, xs)
end repeat
return v
end tell
end foldl
-- keys :: Dict -> [String]
on keys(rec)
(current application's NSDictionary's dictionaryWithDictionary:rec)'s allKeys() as list
end keys
-- mapInsert :: Dict -> k -> v -> Dict
on mapInsert(rec, k, v)
set ca to current application
set nsDct to (ca's NSMutableDictionary's dictionaryWithDictionary:rec)
nsDct's setValue:v forKey:(k as string)
item 1 of ((ca's NSArray's arrayWithObject:nsDct) as list)
end mapInsert
-- mapKeys :: (Key -> Key) -> IntMap a -> IntMap a
on mapKeys(f, dct)
script
property g : mReturn(f)
on |λ|(kv)
set {k, v} to kv
{g's |λ|(k), v}
end |λ|
end script
map(result, zip(keys(dct), elems(dct)))
end mapKeys
-- min :: Ord a => a -> a -> a
on min(x, y)
if y < x then
y
else
x
end if
end min
-- 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
-- zip :: [a] -> [b] -> [(a, b)]
on zip(xs, ys)
set lng to min(length of xs, length of ys)
set lst to {}
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 zip