///// <summary> Performs a left fold on the array: +, 0, [1, 2, 3] => (((0 + 1) + 2) + 3) </summary> private static Val FoldLeft(Func <Val, Val, Val> fn, Val baseElement, VarArgs args) { var result = baseElement; var elements = args.ToNativeList(); for (int i = 0, len = elements.Count; i < len; i++) { result = fn(result, elements[i]); } return(result); }
///// <summary> Performs a right fold on the array: +, 0, [1, 2, 3] => (1 + (2 + (3 + 0))) </summary> private static Val FoldRight(Func <Val, Val, Val> fn, Val baseElement, VarArgs args) { var result = baseElement; var elements = args.ToNativeList(); for (int i = elements.Count - 1; i >= 0; i--) { result = fn(elements[i], result); } return(result); }
// // // dotnet interop public static Val DotDot(Context _, VarArgs args) { var arglist = args.ToNativeList().SelectMany(SplitSymbol).ToList(); var gotone = arglist.Count > 0; if (!gotone) { return(Val.NIL); } int i = 0; var current = arglist[i++]; do { var nextSymbol = TakeNextSymbolOrNull(); var nonSymbols = TakeNonSymbols().ToList(); current = TryReflectionStep(current, nextSymbol, nonSymbols); } while (i < arglist.Count); return(current); Symbol TakeNextSymbolOrNull() { var results = TakeSymbols(true).Take(1); return(results.FirstOrDefault().AsSymbolOrNull); } IEnumerable <Val> TakeNonSymbols() { return(TakeSymbols(false)); } IEnumerable <Val> TakeSymbols(bool expected) { while (i < arglist.Count) { var next = arglist[i]; if (next.IsSymbol == expected) { i++; yield return(next); } else { break; } } } }