content: -- permutations :: [a] -> [[a]]
  on permutations(xs)
      script go
          on |λ|(x, a)
              script
                  on |λ|(ys)
                      script infix
                          on |λ|(n)
                              if ys ≠ {} then
                                  take(n, ys) & {x} & drop(n, ys)
                              else
                                  {x}
                              end if
                          end |λ|
                      end script
                      map(infix, enumFromTo(0, (length of ys)))
                  end |λ|
              end script
              concatMap(result, a)
          end |λ|
      end script
      foldr(go, {{}}, xs)
  end permutations
  
  
  -- TEST ---------------------------------------------------
  on run
  
      permutations({1, 2, 3})
  
      --> {{1, 2, 3}, {2, 1, 3}, {2, 3, 1}, {1, 3, 2}, {3, 1, 2}, {3, 2, 1}}
  end run
  
  
  -- GENERIC ------------------------------------------------
  
  -- concatMap :: (a -> [b]) -> [a] -> [b]
  on concatMap(f, xs)
      set lng to length of xs
      set acc to {}
      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
  
  -- drop :: Int -> [a] -> [a]
  on drop(n, xs)
      if n < length of xs then
          items (1 + n) thru -1 of xs
      else
          {}
      end if
  end drop
  
  -- 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
  
  -- foldr :: (a -> b -> b) -> b -> [a] -> b
  on foldr(f, startValue, xs)
      tell mReturn(f)
          set v to startValue
          set lng to length of xs
          repeat with i from lng to 1 by -1
              set v to |λ|(item i of xs, v, i, xs)
          end repeat
          return v
      end tell
  end foldr
  
  -- 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
  
  -- 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
  
  -- min :: Ord a => a -> a -> a
  on min(x, y)
      if y < x then
          y
      else
          x
      end if
  end min
  
  -- take :: Int -> [a] -> [a]
  -- take :: Int -> String -> String
  on take(n, xs)
      if 0 < n then
          items 1 thru min(n, length of xs) of xs
      else
          {}
      end if
  end take
  