257 lines
5.3 KiB
AppleScript
257 lines
5.3 KiB
AppleScript
-- asciiTable :: () -> String
|
|
on asciiTable()
|
|
script row
|
|
on |λ|(x)
|
|
concat(map(justifyLeft(12, space), x))
|
|
end |λ|
|
|
end script
|
|
|
|
unlines(map(row, ¬
|
|
transpose(chunksOf(16, map(my asciiEntry, ¬
|
|
enumFromTo(32, 127))))))
|
|
end asciiTable
|
|
|
|
|
|
-------------------------- TEST ---------------------------
|
|
on run
|
|
|
|
asciiTable()
|
|
|
|
end run
|
|
|
|
|
|
------------------------- DISPLAY -------------------------
|
|
|
|
-- asciiEntry :: Int -> String
|
|
on asciiEntry(n)
|
|
set k to asciiName(n)
|
|
if "" ≠ k then
|
|
justifyRight(4, space, n as string) & " : " & k
|
|
else
|
|
k
|
|
end if
|
|
end asciiEntry
|
|
|
|
-- asciiName :: Int -> String
|
|
on asciiName(n)
|
|
if 32 > n or 127 < n then
|
|
""
|
|
else if 32 = n then
|
|
"Spc"
|
|
else if 127 = n then
|
|
"Del"
|
|
else
|
|
chr(n)
|
|
end if
|
|
end asciiName
|
|
|
|
|
|
-------------------- GENERIC FUNCTIONS --------------------
|
|
|
|
-- chr :: Int -> Char
|
|
on chr(n)
|
|
character id n
|
|
end chr
|
|
|
|
|
|
-- chunksOf :: Int -> [a] -> [[a]]
|
|
on chunksOf(k, xs)
|
|
script
|
|
on go(ys)
|
|
set ab to splitAt(k, ys)
|
|
set a to |1| of ab
|
|
if {} ≠ a then
|
|
{a} & go(|2| of ab)
|
|
else
|
|
a
|
|
end if
|
|
end go
|
|
end script
|
|
result's go(xs)
|
|
end chunksOf
|
|
|
|
|
|
-- concat :: [[a]] -> [a]
|
|
-- concat :: [String] -> String
|
|
on concat(xs)
|
|
set lng to length of xs
|
|
if 0 < lng and string is class of (item 1 of xs) then
|
|
set acc to ""
|
|
else
|
|
set acc to {}
|
|
end if
|
|
repeat with i from 1 to lng
|
|
set acc to acc & item i of xs
|
|
end repeat
|
|
acc
|
|
end concat
|
|
|
|
|
|
-- concatMap :: (a -> [b]) -> [a] -> [b]
|
|
on concatMap(f, xs)
|
|
set lng to length of xs
|
|
if 0 < lng and class of xs is string then
|
|
set acc to ""
|
|
else
|
|
set acc to {}
|
|
end if
|
|
tell mReturn(f)
|
|
repeat with i from 1 to lng
|
|
set acc to acc & |λ|(item i of xs, i, xs)
|
|
end repeat
|
|
end tell
|
|
return acc
|
|
end concatMap
|
|
|
|
|
|
-- 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
|
|
return lst
|
|
else
|
|
return {}
|
|
end if
|
|
end enumFromTo
|
|
|
|
|
|
-- 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
|
|
|
|
|
|
-- justifyLeft :: Int -> Char -> String -> String
|
|
on justifyLeft(n, cFiller)
|
|
script
|
|
on |λ|(strText)
|
|
if n > length of strText then
|
|
text 1 thru n of (strText & replicate(n, cFiller))
|
|
else
|
|
strText
|
|
end if
|
|
end |λ|
|
|
end script
|
|
end justifyLeft
|
|
|
|
|
|
-- justifyRight :: Int -> Char -> String -> String
|
|
on justifyRight(n, cFiller, strText)
|
|
if n > length of strText then
|
|
text -n thru -1 of ((replicate(n, cFiller) as text) & strText)
|
|
else
|
|
strText
|
|
end if
|
|
end justifyRight
|
|
|
|
|
|
-- length :: [a] -> Int
|
|
on |length|(xs)
|
|
length of xs
|
|
end |length|
|
|
|
|
|
|
-- 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
|
|
|
|
|
|
-- Egyptian multiplication - progressively doubling a list, appending
|
|
-- stages of doubling to an accumulator where needed for binary
|
|
-- assembly of a target length
|
|
-- replicate :: Int -> a -> [a]
|
|
on replicate(n, a)
|
|
set out to {}
|
|
if n < 1 then return out
|
|
set dbl to {a}
|
|
|
|
repeat while (n > 1)
|
|
if (n mod 2) > 0 then set out to out & dbl
|
|
set n to (n div 2)
|
|
set dbl to (dbl & dbl)
|
|
end repeat
|
|
return out & dbl
|
|
end replicate
|
|
|
|
|
|
-- splitAt :: Int -> [a] -> ([a],[a])
|
|
on splitAt(n, xs)
|
|
if n > 0 and n < length of xs then
|
|
if class of xs is text then
|
|
Tuple(items 1 thru n of xs as text, items (n + 1) thru -1 of xs as text)
|
|
else
|
|
Tuple(items 1 thru n of xs, items (n + 1) thru -1 of xs)
|
|
end if
|
|
else
|
|
if n < 1 then
|
|
Tuple({}, xs)
|
|
else
|
|
Tuple(xs, {})
|
|
end if
|
|
end if
|
|
end splitAt
|
|
|
|
|
|
-- Tuple (,) :: a -> b -> (a, b)
|
|
on Tuple(a, b)
|
|
{type:"Tuple", |1|:a, |2|:b, length:2}
|
|
end Tuple
|
|
|
|
|
|
-- Simplified version - assuming rows of unvarying length.
|
|
-- transpose :: [[a]] -> [[a]]
|
|
on transpose(rows)
|
|
script cols
|
|
on |λ|(_, iCol)
|
|
script cell
|
|
on |λ|(row)
|
|
item iCol of row
|
|
end |λ|
|
|
end script
|
|
concatMap(cell, rows)
|
|
end |λ|
|
|
end script
|
|
map(cols, item 1 of rows)
|
|
end transpose
|
|
|
|
|
|
-- unlines :: [String] -> String
|
|
on unlines(xs)
|
|
set {dlm, my text item delimiters} to ¬
|
|
{my text item delimiters, linefeed}
|
|
set str to xs as text
|
|
set my text item delimiters to dlm
|
|
str
|
|
end unlines
|