diff --git a/packages/squiggle-lang/__tests__/Reducer/Reducer_mapReduce_test.res b/packages/squiggle-lang/__tests__/Reducer/Reducer_mapReduce_test.res index f3df0962..f89173d5 100644 --- a/packages/squiggle-lang/__tests__/Reducer/Reducer_mapReduce_test.res +++ b/packages/squiggle-lang/__tests__/Reducer/Reducer_mapReduce_test.res @@ -1,15 +1,6 @@ open Jest open Reducer_TestHelpers -describe("map reduce", () => { - testEvalToBe("double(x)=2*x; arr=[1,2,3]; map(arr, double)", "Ok([2,4,6])") - testEvalToBe("myadd(acc,x)=acc+x; arr=[1,2,3]; reduce(arr, 0, myadd)", "Ok(6)") - testEvalToBe("change(acc,x)=acc*x+x; arr=[1,2,3]; reduce(arr, 0, change)", "Ok(15)") - testEvalToBe("change(acc,x)=acc*x+x; arr=[1,2,3]; reduceReverse(arr, 0, change)", "Ok(9)") - testEvalToBe("arr=[1,2,3]; reverse(arr)", "Ok([3,2,1])") - testEvalToBe("check(x)=(x==2);arr=[1,2,3]; filter(arr,check)", "Ok([2])") -}) - Skip.describe("map reduce (sam)", () => { testEvalToBe("addone(x)=x+1; map(2, addone)", "Error???") testEvalToBe("addone(x)=x+1; map(2, {x: addone})", "Error???") diff --git a/packages/squiggle-lang/__tests__/SquiggleLibrary/SquiggleLibrary_FunctionRegistryLibrary_test.res b/packages/squiggle-lang/__tests__/SquiggleLibrary/SquiggleLibrary_FunctionRegistryLibrary_test.res index d4f52e5c..b7c7b8d0 100644 --- a/packages/squiggle-lang/__tests__/SquiggleLibrary/SquiggleLibrary_FunctionRegistryLibrary_test.res +++ b/packages/squiggle-lang/__tests__/SquiggleLibrary/SquiggleLibrary_FunctionRegistryLibrary_test.res @@ -16,6 +16,12 @@ describe("FunctionRegistry Library", () => { testEvalToBe("List.first([3,5,8])", "Ok(3)") testEvalToBe("List.last([3,5,8])", "Ok(8)") testEvalToBe("List.reverse([3,5,8])", "Ok([8,5,3])") + testEvalToBe("double(x)=2*x; arr=[1,2,3]; List.map(arr, double)", "Ok([2,4,6])") + testEvalToBe("myadd(acc,x)=acc+x; arr=[1,2,3]; List.reduce(arr, 0, myadd)", "Ok(6)") + testEvalToBe("change(acc,x)=acc*x+x; arr=[1,2,3]; List.reduce(arr, 0, change)", "Ok(15)") + testEvalToBe("change(acc,x)=acc*x+x; arr=[1,2,3]; List.reduceReverse(arr, 0, change)", "Ok(9)") + testEvalToBe("check(x)=(x==2);arr=[1,2,3]; List.filter(arr,check)", "Ok([2])") + testEvalToBe("arr=[1,2,3]; List.reverse(arr)", "Ok([3,2,1])") testEvalToBe("Dist.normal(5,2)", "Ok(Normal(5,2))") testEvalToBe("normal(5,2)", "Ok(Normal(5,2))") testEvalToBe("normal({mean:5,stdev:2})", "Ok(Normal(5,2))") diff --git a/packages/squiggle-lang/src/rescript/FunctionRegistry/Library/FR_List.res b/packages/squiggle-lang/src/rescript/FunctionRegistry/Library/FR_List.res index a181fb33..ba9918da 100644 --- a/packages/squiggle-lang/src/rescript/FunctionRegistry/Library/FR_List.res +++ b/packages/squiggle-lang/src/rescript/FunctionRegistry/Library/FR_List.res @@ -23,13 +23,67 @@ module Internals = { let reverse = (array: array): internalExpressionValue => IEvArray( Belt.Array.reverse(array), ) + + let map = (array: array, environment, eLambdaValue, reducer): result< + ReducerInterface_InternalExpressionValue.t, + Reducer_ErrorValue.errorValue, + > => { + let rMappedList = array->E.A.reduceReverse(Ok(list{}), (rAcc, elem) => + rAcc->E.R.bind(_, acc => { + let rNewElem = Reducer_Expression_Lambda.doLambdaCall( + eLambdaValue, + list{elem}, + environment, + reducer, + ) + rNewElem->E.R2.fmap(newElem => list{newElem, ...acc}) + }) + ) + rMappedList->E.R2.fmap(mappedList => mappedList->Belt.List.toArray->Wrappers.evArray) + } + + let reduce = (aValueArray, initialValue, aLambdaValue, environment, reducer) => { + aValueArray->E.A.reduce(Ok(initialValue), (rAcc, elem) => + rAcc->E.R.bind(_, acc => + Reducer_Expression_Lambda.doLambdaCall(aLambdaValue, list{acc, elem}, environment, reducer) + ) + ) + } + + let reduceReverse = (aValueArray, initialValue, aLambdaValue, environment, reducer) => { + aValueArray->Belt.Array.reduceReverse(Ok(initialValue), (rAcc, elem) => + rAcc->Belt.Result.flatMap(acc => + Reducer_Expression_Lambda.doLambdaCall(aLambdaValue, list{acc, elem}, environment, reducer) + ) + ) + } + + let filter = (aValueArray, aLambdaValue, environment, reducer) => { + let rMappedList = aValueArray->Belt.Array.reduceReverse(Ok(list{}), (rAcc, elem) => + rAcc->E.R.bind(_, acc => { + let rNewElem = Reducer_Expression_Lambda.doLambdaCall( + aLambdaValue, + list{elem}, + environment, + reducer, + ) + rNewElem->E.R2.fmap(newElem => + switch newElem { + | IEvBool(true) => list{elem, ...acc} + | _ => acc + } + ) + }) + ) + rMappedList->E.R2.fmap(mappedList => mappedList->Belt.List.toArray->Wrappers.evArray) + } } let library = [ Function.make( ~name="make", ~nameSpace, - ~requiresNamespace, + ~requiresNamespace=true, ~output=EvtArray, ~examples=[`List.make(2, "testValue")`], ~definitions=[ @@ -51,7 +105,7 @@ let library = [ Function.make( ~name="upTo", ~nameSpace, - ~requiresNamespace, + ~requiresNamespace=true, ~output=EvtArray, ~examples=[`List.upTo(1,4)`], ~definitions=[ @@ -70,7 +124,7 @@ let library = [ Function.make( ~name="first", ~nameSpace, - ~requiresNamespace, + ~requiresNamespace=true, ~examples=[`List.first([1,4,5])`], ~definitions=[ FnDefinition.make( @@ -89,7 +143,7 @@ let library = [ Function.make( ~name="last", ~nameSpace, - ~requiresNamespace, + ~requiresNamespace=true, ~examples=[`List.last([1,4,5])`], ~definitions=[ FnDefinition.make( @@ -125,4 +179,87 @@ let library = [ ], (), ), + Function.make( + ~name="map", + ~nameSpace, + ~output=EvtArray, + ~requiresNamespace=false, + ~examples=[`List.map([1,4,5], {|x| x+1})`], + ~definitions=[ + FnDefinition.make( + ~name="map", + ~inputs=[FRTypeArray(FRTypeAny), FRTypeLambda], + ~run=(inputs, _, env, reducer) => + switch inputs { + | [IEvArray(array), IEvLambda(lambda)] => + Internals.map(array, env, lambda, reducer)->E.R2.errMap(_ => "Error!") + | _ => Error(impossibleError) + }, + (), + ), + ], + (), + ), + Function.make( + ~name="reduce", + ~nameSpace, + ~requiresNamespace=false, + ~examples=[`List.reduce([1,4,5], 2, {|acc, el| acc+el})`], + ~definitions=[ + FnDefinition.make( + ~name="reduce", + ~inputs=[FRTypeArray(FRTypeAny), FRTypeAny, FRTypeLambda], + ~run=(inputs, _, env, reducer) => + switch inputs { + | [IEvArray(array), initialValue, IEvLambda(lambda)] => + Internals.reduce(array, initialValue, lambda, env, reducer)->E.R2.errMap(_ => "Error!") + | _ => Error(impossibleError) + }, + (), + ), + ], + (), + ), + Function.make( + ~name="reduceReverse", + ~nameSpace, + ~requiresNamespace=false, + ~examples=[`List.reduceReverse([1,4,5], 2, {|acc, el| acc-el})`], + ~definitions=[ + FnDefinition.make( + ~name="reduceReverse", + ~inputs=[FRTypeArray(FRTypeAny), FRTypeAny, FRTypeLambda], + ~run=(inputs, _, env, reducer) => + switch inputs { + | [IEvArray(array), initialValue, IEvLambda(lambda)] => + Internals.reduceReverse(array, initialValue, lambda, env, reducer)->E.R2.errMap(_ => + "Error!" + ) + | _ => Error(impossibleError) + }, + (), + ), + ], + (), + ), + Function.make( + ~name="filter", + ~nameSpace, + ~requiresNamespace=false, + ~examples=[`List.filter([1,4,5], {|x| x>3})`], + ~definitions=[ + FnDefinition.make( + ~name="filter", + ~inputs=[FRTypeArray(FRTypeAny), FRTypeLambda], + ~run=(inputs, _, env, reducer) => + switch inputs { + | [IEvArray(array), IEvLambda(lambda)] => + Internals.filter(array, lambda, env, reducer)->E.R2.errMap(_ => "Error!") + | _ => Error(impossibleError) + }, + (), + ), + ], + (), + ), ] diff --git a/packages/squiggle-lang/src/rescript/Reducer/Reducer_Dispatch/Reducer_Dispatch_BuiltIn.res b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Dispatch/Reducer_Dispatch_BuiltIn.res index 0cefe5ee..0f3e1e4b 100644 --- a/packages/squiggle-lang/src/rescript/Reducer/Reducer_Dispatch/Reducer_Dispatch_BuiltIn.res +++ b/packages/squiggle-lang/src/rescript/Reducer/Reducer_Dispatch/Reducer_Dispatch_BuiltIn.res @@ -95,31 +95,6 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce let doExportBindings = (bindings: nameSpace) => bindings->Bindings.toExpressionValue->Ok - let doKeepArray = (aValueArray, aLambdaValue) => { - let rMappedList = aValueArray->Belt.Array.reduceReverse(Ok(list{}), (rAcc, elem) => - rAcc->Result.flatMap(acc => { - let rNewElem = Lambda.doLambdaCall(aLambdaValue, list{elem}, environment, reducer) - rNewElem->Result.map(newElem => - switch newElem { - | IEvBool(true) => list{elem, ...acc} - | _ => acc - } - ) - }) - ) - rMappedList->Result.map(mappedList => mappedList->Belt.List.toArray->IEvArray) - } - - let doMapArray = (aValueArray, aLambdaValue) => { - let rMappedList = aValueArray->Belt.Array.reduceReverse(Ok(list{}), (rAcc, elem) => - rAcc->Result.flatMap(acc => { - let rNewElem = Lambda.doLambdaCall(aLambdaValue, list{elem}, environment, reducer) - rNewElem->Result.map(newElem => list{newElem, ...acc}) - }) - ) - rMappedList->Result.map(mappedList => mappedList->Belt.List.toArray->IEvArray) - } - module SampleMap = { type t = SampleSetDist.t let doLambdaCall = (aLambdaValue, list) => @@ -172,22 +147,6 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce } } - let doReduceArray = (aValueArray, initialValue, aLambdaValue) => { - aValueArray->Belt.Array.reduce(Ok(initialValue), (rAcc, elem) => - rAcc->Result.flatMap(acc => - Lambda.doLambdaCall(aLambdaValue, list{acc, elem}, environment, reducer) - ) - ) - } - - let doReduceReverseArray = (aValueArray, initialValue, aLambdaValue) => { - aValueArray->Belt.Array.reduceReverse(Ok(initialValue), (rAcc, elem) => - rAcc->Result.flatMap(acc => - Lambda.doLambdaCall(aLambdaValue, list{acc, elem}, environment, reducer) - ) - ) - } - switch call { | ("$_atIndex_$", [IEvArray(aValueArray), IEvNumber(fIndex)]) => arrayAtIndex(aValueArray, fIndex) | ("$_atIndex_$", [IEvBindings(dict), IEvString(sIndex)]) => moduleAtIndex(dict, sIndex) @@ -226,10 +185,6 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce doAddString(aValueString, bValueString) | ("inspect", [value, IEvString(label)]) => inspectLabel(value, label) | ("inspect", [value]) => inspect(value) - | ("filter", [IEvArray(aValueArray), IEvLambda(aLambdaValue)]) => - doKeepArray(aValueArray, aLambdaValue) - | ("map", [IEvArray(aValueArray), IEvLambda(aLambdaValue)]) => - doMapArray(aValueArray, aLambdaValue) | ("mapSamples", [IEvDistribution(SampleSet(dist)), IEvLambda(aLambdaValue)]) => SampleMap.map1(dist, aLambdaValue) | ( @@ -253,11 +208,6 @@ let callInternal = (call: functionCall, environment, reducer: ExpressionT.reduce SampleMap.map3(dist1, dist2, dist3, aLambdaValue) | ("mapSamplesN", [IEvArray(aValueArray), IEvLambda(aLambdaValue)]) => SampleMap.mapN(aValueArray, aLambdaValue) - | ("reduce", [IEvArray(aValueArray), initialValue, IEvLambda(aLambdaValue)]) => - doReduceArray(aValueArray, initialValue, aLambdaValue) - | ("reduceReverse", [IEvArray(aValueArray), initialValue, IEvLambda(aLambdaValue)]) => - doReduceReverseArray(aValueArray, initialValue, aLambdaValue) - | ("reverse", [IEvArray(aValueArray)]) => aValueArray->Belt.Array.reverse->IEvArray->Ok | (_, [IEvBool(_)]) | (_, [IEvNumber(_)]) | (_, [IEvString(_)]) diff --git a/packages/squiggle-lang/src/rescript/Utility/E.res b/packages/squiggle-lang/src/rescript/Utility/E.res index a3af26e9..50a28382 100644 --- a/packages/squiggle-lang/src/rescript/Utility/E.res +++ b/packages/squiggle-lang/src/rescript/Utility/E.res @@ -546,6 +546,7 @@ module A = { let slice = Belt.Array.slice let init = Array.init let reduce = Belt.Array.reduce + let reduceReverse = Belt.Array.reduceReverse let reducei = Belt.Array.reduceWithIndex let some = Belt.Array.some let isEmpty = r => length(r) < 1