Changeset 3827

Show
Ignore:
Timestamp:
05/24/05 20:25:41 (4 years ago)
Author:
iblech
svk:copy_cache_prev:
5385
Message:

Oops, forgot to checkin the modified Prim/List.hs.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • src/Pugs/Prim/List.hs

    r3816 r3827  
    163163    code <- fromVal sub 
    164164    args <- fromVal list 
     165    let arity = length $ subParams code 
     166    if arity < 2 then fail "Cannot reduce() using a unary or nullary function." else do 
     167    -- n is the number of *additional* arguments to be passed to the sub. 
     168    -- Ex.: reduce { $^a + $^b       }, ...   # n = 1 
     169    -- Ex.: reduce { $^a + $^b + $^c }, ...   # n = 2 
     170    let n = arity - 1 
     171    -- Break on empty list. 
    165172    if null args then return undef else do 
    166     let doFold x y = do 
     173    let doFold xs = do 
    167174        evl <- asks envEval 
    168175        local (\e -> e{ envContext = cxtItemAny }) $ do 
    169             evl (App (Val sub) [Val x, Val y] []) 
     176            evl (App (Val sub) (map Val xs) []) 
    170177    case subAssoc code of 
    171178        "right" -> do 
    172179            let args' = reverse args 
    173             foldM (flip doFold) (head args') (tail args') 
    174         "chain" -> callCC $ \esc -> do 
    175             let doFold' x y = do 
    176                 val <- doFold x y 
    177                 case val of 
    178                     VBool False -> esc val 
    179                     _           -> return y 
    180             foldM doFold' (head args) (tail args) 
    181             return $ VBool True 
     180            foldMn args' n (doFold . reverse) 
     181        "chain" -> if arity /= 2 
     182            then fail 
     183                "When reducing using a chain-associative sub,\nthe sub must take exactly two arguments." 
     184            else callCC $ \esc -> do 
     185                let doFold' x y = do 
     186                    val <- doFold [x, y] 
     187                    case val of 
     188                        VBool False -> esc val 
     189                        _           -> return y 
     190                foldM doFold' (head args) (tail args) 
     191                return $ VBool True 
    182192        "non"   -> fail $ "Cannot reduce over non-associativity" 
    183         _       -> foldM doFold (head args) (tail args) -- "left", "pre" 
     193        _       -> foldMn args n doFold -- "left", "pre" 
     194    where 
     195    -- This is a generalized foldM. 
     196    -- It takes an input list (from which the first elem will be used as start 
     197    -- value), the number of additional arguments, and a reducing function. 
     198    foldMn :: [Val] -> Int -> ([Val] -> Eval Val) -> Eval Val 
     199    foldMn list n f = foldM (\a b -> f (a:b)) (head list) $ list2LoL n $ drop 1 list 
    184200 
    185201op2Grep :: Val -> Val -> Eval Val 
     
    209225    where 
    210226    -- Takes a list, an arity, and a function. 
    211     mapMn  :: [Val] -> Int -> ([Val] -> Eval [Val]) -> Eval [Val] 
    212     mapMn list n f = mapMn' (l2lol n list) f 
     227    mapMn           :: [Val] -> Int -> ([Val] -> Eval [Val]) -> Eval [Val] 
     228    mapMn list n f   = mapMn' (list2LoL n list) f 
    213229    -- Takes a LoL and a function and applies the function to the inputlist. 
    214     mapMn' :: [[Val]] -> ([Val] -> Eval [Val]) -> Eval [Val] 
    215     mapMn' (x:xs) f = liftM2 (++) (f x) (mapMn' xs f) 
    216     mapMn' []     _ = return [] 
    217     -- Takes a list and returns a LoL. 
    218     -- Ex.: l2lol 3 [1,2,3,4,5] = [[1,2,3],[4,5,undef]] 
    219     l2lol n list 
    220         | n == 0           = fail "Cannot map() using a nullary function." 
    221         -- If the list has exactly n elements, we've finished our work. 
    222         | length list == n = [list] 
    223         -- If the list is empty, we're done, too. 
    224         | length list == 0 = [] 
    225         -- But if the list contains more elems than we need, we process the 
    226         -- first n ones and the rest separately. 
    227         | length list  > n = (l2lol n $ take n list) ++ (l2lol n $ drop n list) 
    228         -- And if the list contains less elems than we need, we pad with undefs. 
    229         | length list  < n = l2lol n $ list ++ [undef :: Val] 
    230         | otherwise        = fail "Invalid arguments to internal function l2lol passed." 
     230    mapMn'          :: [[Val]] -> ([Val] -> Eval [Val]) -> Eval [Val] 
     231    mapMn' (x:xs) f  = liftM2 (++) (f x) (mapMn' xs f) 
     232    mapMn' []     _  = return [] 
     233 
     234-- | Takes an int and a list and returns a LoL. 
     235--   Ex.: 
     236--   > list2LoL 3 [1,2,3,4,5] = [[1,2,3],[4,5,undef]] 
     237list2LoL :: Int -> [Val] -> [[Val]] 
     238list2LoL n list 
     239    | n == 0           = fail "Cannot map() using a nullary function." 
     240    -- If the list has exactly n elements, we've finished our work. 
     241    | length list == n = [list] 
     242    -- If the list is empty, we're done, too. 
     243    | length list == 0 = [] 
     244    -- But if the list contains more elems than we need, we process the 
     245    -- first n ones and the rest separately. 
     246    | length list  > n = (list2LoL n $ take n list) ++ (list2LoL n $ drop n list) 
     247    -- And if the list contains less elems than we need, we pad with undefs. 
     248    | length list  < n = list2LoL n $ list ++ [undef :: Val] 
     249    | otherwise        = fail "Invalid arguments to internal function list2LoL passed." 
    231250 
    232251op2Join :: Val -> Val -> Eval Val