kotlin PR that generated this x-common issueThe current canonical data for list-ops includes the following non-degenerate cases for the foldl and foldr functions:
{
"description": "division of integers",
"property": "foldl",
"list": [1, 2, 3, 4],
"initial": 24,
"function": "value / accumulator",
"expected": 64
}
and
{
"description": "division of integers",
"property": "foldr",
"list": [1, 2, 3, 4],
"initial": 24,
"function": "value / accumulator",
"expected": 9
}
The folding captured by these tests is quite tricky to reason about due to
Since folding is one of the more complex operations we're asking implementors to build in this exercise, I propose (h/t @sdavids13) that we insert _at least one_ simpler test right before each of the division-based tests captured above. In particular, we could follow the example of xpython (which is currently not compliant with the canonical data), and have implementors first pass a test that uses a simpler operation (addition, subtraction, multiplication, or all of the above) whose expected result is easier to validate and whose implementation can be integer-only. Examples for foldl:
{
"description": "addition of integers",
"property": "foldl",
"list": [1, 2, 3, 4],
"initial": 5,
"function": "accumulator + value",
"expected": 15
}
and/or
{
"description": "subtraction of integers",
"property": "foldl",
"list": [1, 2, 3, 4],
"initial": 5,
"function": "accumulator - value",
"expected": -5
}
and/or
{
"description": "multiplication of integers",
"property": "foldl",
"list": [1, 2, 3, 4],
"initial": 5,
"function": "accumulator * value",
"expected": 120
}
Inviting feedback on this idea; happy to handle any changes resulting from discussion :)
Why is division even necessary to test? This is list-ops not complex-expression-parsing
There is no expression parsing involved from the students point of view. Just a passed in function f. And this function f shall be passed in as \value acc -> accumulator / value or whatever representation the implementing language uses for lambdas, closures, procs or just function references.
Personally, I think it is important to find a way to test if foldl/foldr are folding in the right direction. In the domain of integral numbers, I do only see the integral division as a function which we can use to check for the direction of the fold. Only using this, we can construct a function that will yield different results for the same list and initial when swapping foldl with foldr.
@NobbZ is correct regarding how the division is expressed in this exercise. However, I'm struggling to find an example using integer division that uses the same initial value and list to differentiate between foldl and foldr. @NobbZ are you able to provide one?
Quick play in the Haskell-REPL:
Prelude> foldr div 5 [2, 5]
2
Prelude> foldl div 5 [2, 5]
0
Ah, right, I forgot we were using value / accumulator rather than accumulator / value. Thanks! So we may want to add this sort of test too to verify directionality is handled properly 馃憤
Ah, right, I forgot we were using
value / accumulatorrather thanaccumulator / value.
Just to clarify; actually, we're using both. If you look at the type signatures for foldl and foldr you'll note that we have to use value / accumulator or accumulator / value depending upon whether we're folding from the left or folding from the right.
I'll post tomorrow regarding the changes I made to xkotlin to see whether they would be acceptable in x-common.
Here's what I ended up with in xkotlin (pseudo-canonical entries):
{
"description": "multiplication with empty list",
"property": "foldl",
"list": [],
"initial": 2,
"function": "(x, y) -> x * y",
"expected": 2
},
{
"description": "addition of integers",
"property": "foldl",
"list": [1, 2, 3, 4],
"initial": 5,
"function": "(x, y) -> x + y",
"expected": 15
},
{
"description": "division of integers",
"property": "foldl",
"list": [2, 5],
"initial": 5,
"function": "(x, y) -> x / y",
"expected": 0
}
{
"description": "multiplication with empty list",
"property": "foldr",
"list": [],
"initial": 2,
"function": "(x, y) -> x * y",
"expected": 2
},
{
"description": "addition of integers",
"property": "foldr",
"list": [1, 2, 3, 4],
"initial": 5,
"function": "(x, y) -> x + y",
"expected": 15
},
{
"description": "division of integers",
"property": "foldr",
"list": [2, 5],
"initial": 5,
"function": "(x, y) -> x / y",
"expected": 2
}
Feedback welcome on these specific suggestions.
Super @stkent.
As someone who has not done this exercise but is interested in tests, I have a few questions:
Do there need to be 6 tests?
Is there a way to make one of these tests pass that would not also cause the others to pass?
What needs to be tested?
foldr works correctly.foldl works correctly.What are the important properties of these functions?
What are these tests testing? The descriptions seem to suggest that it has something to do with the function, but that seems to me like it is a bit of a red herring, as what the function is should not be important to the folding.
Is the function used relevant to the tests?
Great questions!
Int::div) is that when they are used to fold, the end result depends on the direction in which you traverse the list.Does the above breakdown sufficiently address your questions, @Insti?
I really like the idea of introducing more tests for the foldl/foldr cases.
Does the above breakdown sufficiently address your questions, @Insti?
Yes, thankyou.
Perhaps the test descriptions could be enhanced by including some of this information that describes what the test is for rather than what it does.
Definitely agree; these are the names I used in Kotlin tests:
testFoldLeftWithDirectionIndependentOperationOnNonEmptyList
testFoldLeftWithDirectionDependentOperationOnNonEmptyList
testFoldRightOnEmptyList
testFoldRightWithDirectionIndependentOperationOnNonEmptyList
testFoldRightWithDirectionDependentOperationOnNonEmptyList
Do those capture enough of the details, do you think? If so, I'll turn them back into English language descriptions and open up a PR (I think we're ready for that?)
Yes, they look like more helpful names.
Awesome! I'll open a PR to resolve this issue this evening.