Changeset 3495

Show
Ignore:
Timestamp:
05/20/05 12:01:14 (4 years ago)
Author:
iblech
svk:copy_cache_prev:
5078
Message:

Implemented min() and max() (work with and without a userspecified comparision
sub) and added more (successful! :)) tests for them.

Files:
3 modified

Legend:

Unmodified
Added
Removed
  • src/Pugs/Prim.hs

    r3494 r3495  
    460460op1 "pick"  = op1Pick 
    461461op1 "sum"   = op1Sum 
     462op1 "min"   = op1Min 
     463op1 "max"   = op1Max 
    462464op1 "chr"   = op1Cast (VStr . (:[]) . chr) 
    463465op1 "ord"   = op1Cast $ \str -> if null str then undef else (castV . ord . head) str 
     
    10791081\\n   Scalar    pre     pop     (rw!Array)\ 
    10801082\\n   Scalar    pre     shift   (rw!Array)\ 
    1081 \\n   Num       pre     sum     (List)\ 
     1083\\n   Scalar    pre     sum     (List)\ 
     1084\\n   Scalar    pre     min     (List)\ 
     1085\\n   Scalar    pre     max     (List)\ 
    10821086\\n   Str       pre     join    (Array: Str)\ 
    10831087\\n   Str       pre     join    (Str, List)\ 
  • src/Pugs/Prim/List.hs

    r3477 r3495  
    11module Pugs.Prim.List ( 
    22    op0Zip, op1Pick, op1Sum, 
     3    op1Min, op1Max, 
    34    op2FoldL, op2Fold, op2Grep, op2Map, op2Join, 
    45    sortByM, 
     
    1011 
    1112import Pugs.Prim.Numeric 
     13import Pugs.Prim.Lifts 
    1214 
    1315op0Zip :: [Val] -> Eval Val 
     
    4749    vals <- fromVal list 
    4850    foldM (op2Numeric (+)) undef vals 
     51 
     52op1Min :: Val -> Eval Val 
     53op1Min v = op1MinMax (== False) v 
     54 
     55op1Max :: Val -> Eval Val 
     56op1Max v = op1MinMax (== True) v 
     57 
     58-- min_or_max is a function which negates truth/falsehood. 
     59-- This is necessary as op1MinMax should cope with min() as well as max(). 
     60op1MinMax :: (Bool -> Bool) -> Val -> Eval Val 
     61op1MinMax min_or_max v = do 
     62    -- We want to have a real Haskell list 
     63    args    <- fromVal v 
     64    -- Extract our comparator sub, or Nothing if none was specified 
     65    (valList, cmp) <- case args of 
     66        (v:vs) -> do 
     67            ifValTypeIsa v "Code" 
     68                (return (vs, Just v)) 
     69                (ifValTypeIsa (last args) "Code" 
     70                    (return (init args, Just $ last args)) 
     71                    (return (args, Nothing))) 
     72        _  -> return (args, Nothing) 
     73    -- Now let our helper function do the rest 
     74    op1MinMax' min_or_max cmp valList 
     75    where 
     76    op1MinMax' :: (Bool -> Bool) -> (Maybe Val) -> [Val] -> Eval Val 
     77    -- The min or max of an empty list is undef. 
     78    op1MinMax' _ _ [] = return undef 
     79    -- We have to supply our own comparator... 
     80    op1MinMax' _ Nothing valList = foldM default_compare (head valList) valList 
     81    -- or use the one of the user 
     82    op1MinMax' min_or_max (Just subVal) valList = do 
     83          sub <- fromVal subVal 
     84          evl <- asks envEval 
     85          -- Here we execute the user's sub 
     86          foldM (\a b -> do 
     87              rv  <- local (\e -> e{ envContext = cxtItem "Int" }) $ do 
     88                  evl (App (Val sub) [Val a, Val b] []) 
     89              int <- fromVal rv 
     90              -- If the return value from the sub was 
     91              --   -1 ==> a < b 
     92              --    0 ==> a == b 
     93              --   +1 ==> a > b 
     94              -- We call min_or_max so we can work for both min() and max(). 
     95              return $ if min_or_max (int > (0::VInt)) then a else b) (head valList) valList 
     96    -- This is the default comparision function, which will be used if the user 
     97    -- hasn't specified a own comparision function. 
     98    default_compare a b = do 
     99        a' <- vCastRat a 
     100        b' <- vCastRat b 
     101        let cmp = if a' < b' then (-1) else if a' == b' then 0 else 1 
     102        return $ if min_or_max (cmp > (0::VInt)) then a else b 
    49103 
    50104op2FoldL :: Val -> Val -> Eval Val 
  • t/builtins/lists/minmax.t

    r2406 r3495  
    44use v6; 
    55 
    6 plan 6; 
     6plan 8; 
    77 
    88=head1 DESCRIPTION 
     
    1818 
    1919# Tests for C<min>: 
    20 eval_is '@array.min', -9, "basic method form of min works", :todo; 
    21 eval_is 'min @array', -9, "basic subroutine form of min works", :todo; 
    22 eval_is '@array.min:{ abs $^a <=> abs $^b }', 0, 
    23   "method form of min taking a comparision block works", :todo; 
     20is @array.min,  -9, "basic method form of min works"; 
     21is min(@array), -9, "basic subroutine form of min works"; 
     22is @array.min:{ abs $^a <=> abs $^b }, 0, 
     23  "method form of min taking a comparision block works"; 
     24is min({ abs $^a <=> abs $^b }, @array), 0, 
     25  "subroutine form of min taking a comparision block works"; 
    2426 
    2527# Tests for C<max>: 
    26 eval_is '@array.max',  7, "basic method form of max works", :todo; 
    27 eval_is 'max @array',  7, "basic subroutine form of max works", :todo; 
    28 eval_is '@array.max:{ abs $^a <=> abs $^b }', 9, 
    29   "method form of max taking a comparision block works", :todo; 
     28is @array.max,  7, "basic method form of max works"; 
     29is max(@array), 7, "basic subroutine form of max works"; 
     30is @array.max:{ abs $^a <=> abs $^b }, -9, 
     31  "method form of max taking a comparision block works"; 
     32is max({ abs $^a <=> abs $^b }, @array), -9, 
     33  "subroutine form of max taking a comparision block works";