#lang shplait // Design `remove` // `remove([1,2,3], 2) = [1,3] // removes first occurrence of 2nd arg from list // List drives the design fun remove(lst::Listof(Int), rmv::Int):: Listof(Int): match lst: | []: [] | cons(val,rst_lst): if val == rmv: | rst_lst | cons(val,remove(rst_lst, rmv)) check: remove([1,2,3],2) ~is [1,3] check: remove([1,2,3],5) ~is [1,2,3] check: remove([],1) ~is [] check: remove([1,2,2,3],2) ~is [1,2,3] // removeAll(lst, rmv_lst) removes all numbers in 2nd arg from 1st arg // rmv_list drives the design // lst is an accumulator (but it grows smaller instead of larger) fun removeAll(lst::Listof(Int), rmv_lst::Listof(Int)):: Listof(Int): match rmv_lst: | []: lst | cons(val,rst_rmv_lst): block: def new_lst = remove(lst, val) removeAll(new_lst, rst_rmv_lst) check: removeAll([1,2,3],[2]) ~is [1,3] check: removeAll([1,2,3],[2,3]) ~is [1] // pairUp(as, bs) = walk through two lists in parallel and pair their elements // both Lists drive the design, so we need two layers of `match` // // alternatives: // - ask the caller to send two equal-length lists // - check for equal length first thing in pairUp, then call a helper // with either alternative, `pairUp` can use one match and call `first`,`rest` on the second list fun pairUp(lst_1::Listof(Int),lst_2::Listof(Int)):: Listof(Listof(Int)): match lst_1: | []: match lst_2: | []: [] | cons(val, rst_lst_2): error(#'pairUp,"List length mismatch") | cons(val_1,rst_lst_1): match lst_2: | []: error(#'pairUp,"List length mismatch") | cons(val_2, rst_lst_2): block: def paired = [val_1,val_2] cons(paired, pairUp(rst_lst_1,rst_lst_2)) check: pairUp([1,2,3],[1,2,3]) ~is [[1,1],[2,2],[3,3]] check: pairUp([1,2,3],[3,2,1]) ~is [[1,3],[2,2],[3,1]] check: pairUp([1,2,3],[3,2]) ~raises "List length mismatch" check: pairUp([1,2],[3,2,1]) ~raises "List length mismatch"