content: -- SYMMETRIC DIFFERENCE -------------------------------------------
  
  -- symmetricDifference :: [a] -> [a] -> [a]
  on symmetricDifference(xs, ys)
      union(difference(xs, ys), difference(ys, xs))
  end symmetricDifference
  
  -- TEST -----------------------------------------------------------
  on run
      set a to ["John", "Serena", "Bob", "Mary", "Serena"]
      set b to ["Jim", "Mary", "John", "Jim", "Bob"]
  
      symmetricDifference(a, b)
  
      -->  {"Serena", "Jim"}
  end run
  
  
  -- GENERIC FUNCTIONS ----------------------------------------------
  
  -- delete :: Eq a => a -> [a] -> [a]
  on |delete|(x, xs)
      set mbIndex to elemIndex(x, xs)
      set lng to length of xs
  
      if mbIndex is not missing value then
          if lng > 1 then
              if mbIndex = 1 then
                  items 2 thru -1 of xs
              else if mbIndex = lng then
                  items 1 thru -2 of xs
              else
                  tell xs to items 1 thru (mbIndex - 1) & ¬
                      items (mbIndex + 1) thru -1
              end if
          else
              {}
          end if
      else
          xs
      end if
  end |delete|
  
  -- difference :: [a] -> [a] -> [a]
  on difference(xs, ys)
      script
          on |λ|(a, y)
              if a contains y then
                  my |delete|(y, a)
              else
                  a
              end if
          end |λ|
      end script
  
      foldl(result, xs, ys)
  end difference
  
  -- elemIndex :: a -> [a] -> Maybe Int
  on elemIndex(x, xs)
      set lng to length of xs
      repeat with i from 1 to lng
          if x = (item i of xs) then return i
      end repeat
      return missing value
  end elemIndex
  
  -- 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
  
  -- Lift 2nd class handler function into 1st class script wrapper
  -- mReturn :: Handler -> Script
  on mReturn(f)
      if class of f is script then
          f
      else
          script
              property |λ| : f
          end script
      end if
  end mReturn
  
  -- nub :: [a] -> [a]
  on nub(xs)
      if (length of xs) > 1 then
          set x to item 1 of xs
          [x] & nub(|delete|(x, items 2 thru -1 of xs))
      else
          xs
      end if
  end nub
  
  -- union :: [a] -> [a] -> [a]
  on union(xs, ys)
      script flipDelete
          on |λ|(xs, x)
              my |delete|(x, xs)
          end |λ|
      end script
  
      set sx to nub(xs)
      sx & foldl(flipDelete, nub(ys), sx)
  end union
  