// Generic Iter_Map / Filter / Fold / Any / All (not just int) import Std::Io::{PrintLine, PrintInt}; import Std::Array::{ Array, Array_New, Array_Push, Array_Get, Array_Len, Array_Free }; import Std::String::{String_FromInt, String_Len, String_Eq}; import Std::Iter::{ Array_Iter, Iter, Iter_Map, Iter_Filter, Iter_Fold, Iter_Any, Iter_All, Iter_MapInt, Iter_SumInt }; import Std::Test::{ Test_AssertEqInt, Test_AssertTrue, Test_AssertFalse, Test_AssertEqString, Test_Pass }; func Double(x: int) -> int { return x * 2; } func IsEven(x: int) -> bool { return (x % 2) == 0; } func IntToString(x: int) -> String { return String_FromInt(x); } func StringLenAsInt(s: String) -> int { return String_Len(s) as int; } func AddLens(acc: int, s: String) -> int { return acc + (String_Len(s) as int); } func IsNonEmpty(s: String) -> bool { return String_Len(s) > 0; } func Main() -> int { var nums: Array = Array_New(8); Array_Push(&nums, 1); Array_Push(&nums, 2); Array_Push(&nums, 3); Array_Push(&nums, 4); Array_Push(&nums, 5); // Generic Map int → int let itA: Iter = Array_Iter(&nums); var doubled: Array = Iter_Map(&itA, Double); Test_AssertEqInt(Array_Get(&doubled, 0), 2); Test_AssertEqInt(Array_Get(&doubled, 4), 10); // Generic Map int → String let itB: Iter = Array_Iter(&nums); var asStr: Array = Iter_Map(&itB, IntToString); Test_AssertEqInt(Array_Len(&asStr) as int, 5); Test_AssertEqString(Array_Get(&asStr, 0), "1"); Test_AssertEqString(Array_Get(&asStr, 4), "5"); // Map String → int (lengths) let itC: Iter = Array_Iter(&asStr); var lens: Array = Iter_Map(&itC, StringLenAsInt); Test_AssertEqInt(Array_Get(&lens, 0), 1); Test_AssertEqInt(Array_Get(&lens, 4), 1); // Filter generic let itD: Iter = Array_Iter(&nums); var evens: Array = Iter_Filter(&itD, IsEven); Test_AssertEqInt(Array_Len(&evens) as int, 2); Test_AssertEqInt(Array_Get(&evens, 0), 2); Test_AssertEqInt(Array_Get(&evens, 1), 4); // Fold String lengths let itE: Iter = Array_Iter(&asStr); let totalChars: int = Iter_Fold(&itE, 0, AddLens); Test_AssertEqInt(totalChars, 5); // "1"+"2"+"3"+"4"+"5" // Any / All on String let itF: Iter = Array_Iter(&asStr); Test_AssertTrue(Iter_Any(&itF, IsNonEmpty)); let itG: Iter = Array_Iter(&asStr); Test_AssertTrue(Iter_All(&itG, IsNonEmpty)); // Closures with generic Map let scale: int = 100; let itH: Iter = Array_Iter(&nums); var scaled: Array = Iter_Map(&itH, |x: int| -> int { return x * scale; }); Test_AssertEqInt(Array_Get(&scaled, 0), 100); Test_AssertEqInt(Array_Get(&scaled, 2), 300); // Int aliases still work let itI: Iter = Array_Iter(&nums); var d2: Array = Iter_MapInt(&itI, Double); Test_AssertEqInt(Array_Get(&d2, 1), 4); let itJ: Iter = Array_Iter(&nums); Test_AssertEqInt(Iter_SumInt(&itJ), 15); PrintInt(totalChars); PrintLine(""); Test_Pass("iter_generic"); Array_Free(&nums); Array_Free(&doubled); Array_Free(&asStr); Array_Free(&lens); Array_Free(&evens); Array_Free(&scaled); Array_Free(&d2); return 0; }