Show
Ignore:
Timestamp:
05/09/06 16:17:14 (3 years ago)
Author:
gaal
svk:copy_cache_prev:
13387
Message:

* Reduce metaoperator in list context gives a scan. Tests included.

TimToady?++. Chained ops scanning doesn't; consulting with p6-l.

Files:
1 modified

Legend:

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

    r7591 r10246  
    44    op0Zip, op1Pick, op1Sum, 
    55    op1Min, op1Max, op1Uniq, 
    6     op2FoldL, op2Fold, op2Grep, op2Map, op2Join, 
     6    op2ReduceL, op2Reduce, op2Grep, op2Map, op2Join, 
    77    sortByM, 
    88    op1HyperPrefix, op1HyperPostfix, op2Hyper, 
     
    156156            if cond then return . VBool $ cond else elemByM eq y xs 
    157157 
    158 op2FoldL :: Val -> Val -> Eval Val 
    159 op2FoldL sub@(VCode _) list = op2FoldL list sub 
    160 op2FoldL list sub = do 
     158op2ReduceL :: Val -> Val -> Eval Val 
     159op2ReduceL sub@(VCode _) list = op2ReduceL list sub 
     160op2ReduceL list sub = do 
    161161    code <- fromVal sub 
    162     op2Fold list $ VCode code{ subAssoc = "left" } 
    163  
    164 op2Fold :: Val -> Val -> Eval Val 
    165 op2Fold sub@(VCode _) list = op2Fold list sub 
    166 op2Fold list sub = do 
     162    op2Reduce list $ VCode code{ subAssoc = "left" } 
     163 
     164op2Reduce :: Val -> Val -> Eval Val 
     165op2Reduce sub@(VCode _) list = op2Reduce list sub 
     166op2Reduce list sub = do 
    167167    code <- fromVal sub 
    168168    args <- fromVal list 
     169    cxt  <- asks envContext 
     170    let (reduceM, reduceMn) = getReduceFuncs cxt 
    169171    let arity = length $ subParams code 
    170172    if arity < 2 then fail "Cannot reduce() using a unary or nullary function." else do 
     
    182184        "right" -> do 
    183185            let args' = reverse args 
    184             foldMn args' n (doFold . reverse) 
    185         "chain" -> if arity /= 2 
     186            reduceMn args' n (doFold . reverse) 
     187        "chain" -> if arity /= 2            -- FIXME: incorrect for scans 
    186188            then fail 
    187189                "When reducing using a chain-associative sub,\nthe sub must take exactly two arguments." 
     
    192194                        VBool False -> esc val 
    193195                        _           -> return y 
    194                 foldM doFold' (head args) (tail args) 
     196                reduceM doFold' (head args) (tail args) 
    195197                return $ VBool True 
    196198        "non"   -> fail $ "Cannot reduce over non-associativity" 
    197         _       -> foldMn args n doFold -- "left", "pre" 
     199        _       -> reduceMn args n doFold -- "left", "pre" 
    198200    where 
    199201    -- This is a generalized foldM. 
     
    202204    foldMn :: [Val] -> Int -> ([Val] -> Eval Val) -> Eval Val 
    203205    foldMn list n f = foldM (\a b -> f (a:b)) (head list) $ list2LoL n $ drop 1 list 
     206    -- Scan version of foldMn. 
     207    scanMn :: [Val] -> Int -> ([Val] -> Eval Val) -> Eval Val 
     208    scanMn list n f = scanM (\a b -> f (a:b)) (head list) $ list2LoL n $ drop 1 list 
     209    -- The Prelude defines foldM but not scanM. 
     210    scanM :: (Val -> b -> Eval Val) -> Val -> [b] -> Eval Val 
     211    scanM f q ls = case ls of 
     212        []   -> return $ VList [q] 
     213        x:xs -> do 
     214            fqx  <- f q x 
     215            rest <- fromVal =<< scanM f fqx xs 
     216            return $ VList (q:rest) 
     217    getReduceFuncs cxt = case cxt of 
     218        CxtSlurpy _ -> (scanM, scanMn) 
     219        _           -> (foldM, foldMn) 
    204220 
    205221op2Grep :: Val -> Val -> Eval Val