Some basic introspective and other ops in terms of NSMutableDictionary and NSDictionary
(Clearly more work than in JS, but not out of reach)
use AppleScript version "2.4"
use framework "Foundation"
use scripting additions
on run
set macOS to dictFromList({{"10.14", "Mojave"}, {"10.15", "Catalina"}})
--> {|10.14|:"Mojave", |10.15|:"Catalina"}
keys(macOS)
--> {"10.14", "10.15"}
elems(macOS)
--> {"Mojave", "Catalina"}
assocs(macOS)
--> {{"10.14", "Mojave"}, {"10.15", "Catalina"}}
set macOSMore to insertDict("10.13", "High Sierra", insertDict("10.12", "Sierra", macOS))
--> {|10.12|:"Sierra", |10.15|:"Catalina", |10.14|:"Mojave", |10.13|:"High Sierra"}
set macOSLess to deleteKey("10.14", macOSMore)
--> {|10.12|:"Sierra", |10.15|:"Catalina", |10.13|:"High Sierra"}
script lookup
on |λ|(k)
maybe("Not found", my identity, lookUpDict(k, macOSLess))
end |λ|
end script
map(lookup, {"10.11", "10.12", "10.13", "10.14", "10.15", "10.16", "10.17"})
--> {"Not found", "Sierra", "High Sierra", "Not found", "Catalina", "Not found", "Not found"}
end run
-- REUSABLE GENERAL FUNCTIONS ---------------------------------------------------
-- https://github.com/RobTrew/prelude-applescript
-- Just :: a -> Maybe a
on Just(x)
-- Constructor for an inhabited Maybe (option type) value.
-- Wrapper containing the result of a computation.
{type:"Maybe", Nothing:false, Just:x}
end Just
-- Nothing :: Maybe a
on Nothing()
-- Constructor for an empty Maybe (option type) value.
-- Empty wrapper returned where a computation is not possible.
{type:"Maybe", Nothing:true}
end Nothing
-- assocs :: Map k a -> [(k, a)]
on assocs(m)
set c to class of m
if list is c then
zip(enumFromTo(1, length of m), m)
else if record is c then
tell current application to set dict to ¬
dictionaryWithDictionary_(m) of its NSDictionary
zip((sortedArrayUsingSelector_("compare:") of ¬
allKeys() of dict) as list, ¬
(allValues() of dict) as list)
else
{}
end if
end assocs
-- deleteKey :: k -> Dict -> Dict
on deleteKey(k, rec)
tell current application to set nsDct to ¬
dictionaryWithDictionary_(rec) of its NSMutableDictionary
removeObjectForKey_(k) of nsDct
nsDct as record
end deleteKey
-- elems :: Map k a -> [a]
-- elems :: Set a -> [a]
on elems(x)
if record is class of x then -- Dict
tell current application to allValues() ¬
of dictionaryWithDictionary_(x) ¬
of its NSDictionary as list
else -- Set
(allObjects() of x) as list
end if
end elems
-- enumFromTo :: Int -> Int -> [Int]
on enumFromTo(m, n)
if m ≤ n then
set lst to {}
repeat with i from m to n
set end of lst to i
end repeat
lst
else
{}
end if
end enumFromTo
-- dictFromList :: [(k, v)] -> Dict
on dictFromList(kvs)
set tpl to unzip(kvs)
script go
on |λ|(x)
x as string
end |λ|
end script
tell current application
(its (NSDictionary's dictionaryWithObjects:(item 2 of tpl) ¬
forKeys:(my map(go, item 1 of tpl)))) as record
end tell
end dictFromList
-- identity :: a -> a
on identity(x)
-- The argument unchanged.
x
end identity
-- insertDict :: String -> a -> Dict -> Dict
on insertDict(k, v, rec)
tell current application
tell dictionaryWithDictionary_(rec) of its NSMutableDictionary
its setValue:v forKey:(k as string)
it as record
end tell
end tell
end insertDict
-- keys :: Dict -> [String]
on keys(rec)
tell current application
(allKeys() of its (NSDictionary's dictionaryWithDictionary:rec)) as list
end tell
end keys
-- lookupDict :: a -> Dict -> Maybe b
on lookUpDict(k, dct)
-- Just the value of k in the dictionary,
-- or Nothing if k is not found.
set ca to current application
set v to (ca's NSDictionary's dictionaryWithDictionary:dct)'s objectForKey:k
if missing value ≠ v then
Just(item 1 of ((ca's NSArray's arrayWithObject:v) as list))
else
Nothing()
end if
end lookUpDict
-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
-- The list obtained by applying f
-- to each element of 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
-- maybe :: b -> (a -> b) -> Maybe a -> b
on maybe(v, f, mb)
-- The 'maybe' function takes a default value, a function, and a 'Maybe'
-- value. If the 'Maybe' value is 'Nothing', the function returns the
-- default value. Otherwise, it applies the function to the value inside
-- the 'Just' and returns the result.
if Nothing of mb then
v
else
tell mReturn(f) to |λ|(Just of mb)
end if
end maybe
-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
-- 2nd class handler function lifted into 1st class script wrapper.
if script is class of f then
f
else
script
property |λ| : f
end script
end if
end mReturn
-- min :: Ord a => a -> a -> a
on min(x, y)
if y < x then
y
else
x
end if
end min
-- unzip :: [(a,b)] -> ([a],[b])
on unzip(xys)
set xs to {}
set ys to {}
repeat with xy in xys
set end of xs to item 1 of xy
set end of ys to item 2 of xy
end repeat
return {xs, ys}
end unzip
-- 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