Skip to content

list-ops: division operator is ambiguous #1467

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
juhlig opened this issue Feb 25, 2019 · 7 comments
Closed

list-ops: division operator is ambiguous #1467

juhlig opened this issue Feb 25, 2019 · 7 comments

Comments

@juhlig
Copy link
Contributor

juhlig commented Feb 25, 2019

{
"description": "direction dependent function applied to non-empty list",
"property": "foldl",
"input": {
"list": [2, 5],
"initial": 5,
"function": "(x, y) -> x / y"
},
"expected": 0
}

{
"description": "direction dependent function applied to non-empty list",
"property": "foldr",
"input": {
"list": [2, 5],
"initial": 5,
"function": "(x, y) -> x / y"
},
"expected": 2
}

The two cases instruct the test implementation to apply the division operator / to the two arguments of the function used for folding.

This operator is ambiguous, depending on language and circumstances. There are languages which always do floating-point division with / and have a separate operator for integer division (eg div in Erlang), others do integer division if both operands are integers and float division only if at least one operand is a float, etc.

The current test cases in question assume integer division, but this is not obvious, only if you (as a human) read the test arguments and expected outcome carefully. For a test generator on the other hand, it is quite difficult.

As finding a language-agnostic way to explicitly specify integer division would pose rather difficult, I suggest to alter the test cases to use another direction-dependent but unambiguous operation instead, like -.

@NobbZ
Copy link
Member

NobbZ commented Feb 26, 2019

I've always read this pretty much in the C-sense…

We get 2 integers in, so we get an integer out.

I never thought of reading it the erlang or elixir way… As long as we get numbers in, we get a float out.

If though we try it the erlang (x div y), elixir (div(x, y)) or haskell (x `div` y) way, I fear it would not be understood by other maintainers on the first glance, as its not what they are used to.

We also might meet some esotherical language, that does not even allow for division directly.

In my opinion we should make the tests self contained:

 { 
   "description": "direction dependent function applied to non-empty list", 
   "property": "foldl", 
   "input": { 
     "list": [2, 5], 
     "initial": [], 
     "function": "(x, y) -> cons(x, y)" 
   }, 
   "expected": [5, 2]
 },
 { 
   "description": "direction dependent function applied to non-empty list", 
   "property": "foldr", 
   "input": { 
     "list": [2, 5], 
     "initial": [], 
     "function": "(x, y) -> cons(x, y)" 
   }, 
   "expected": [2, 5] 
 }

Where cons/2 is the list constructor. Haskell knows it as (:), erlang/elixir as [_|_], other languages will probably just call a function. And the nice thing is, the function stays in the actual domain of the testsuite.

@juhlig
Copy link
Contributor Author

juhlig commented Feb 26, 2019

I never thought of reading it the erlang or elixir way… As long as we get numbers in, we get a float out.

Python appears to have an explicit integer-division operator as well, //, and the / operator seems to work differently among python versions and even among same versions in different environments (I'm not a python person, so can only go from what I have read).

If though we try it the erlang (x div y), elixir (div(x, y)) or haskell (x `div` y) way, I fear it would not be understood by other maintainers on the first glance, as its not what they are used to.

That's basically what I said, finding a way to express integer division that is understood easily among all languages is probably impossible. Subtraction would be a better choice, since it is also direction-dependent in the sense that 2-5 is different from 5-2 (which is what the test cases in question are pretty much all about), but not type-dependent (at least not in any language I know of).

In my opinion we should make the tests self contained:
[...]
Where cons/2 is the list constructor. Haskell knows it as (:), erlang/elixir as [_|_], other languages will probably just call a function. And the nice thing is, the function stays in the actual domain of the testsuite.

I'm not sure if cons would be better understood than div by languages that don't employ lists as heavily as Haskell/Erlang/Elixir etc do. But other than with div or /, comparing the input and expected output pretty much explains what it does.

@NobbZ
Copy link
Member

NobbZ commented Feb 26, 2019

[- is ] not type-dependent (at least not in any language I know of).

The first that comes to my mind is C… If one argument is float-y, the result is as well.

@juhlig
Copy link
Contributor Author

juhlig commented Feb 26, 2019

Yes, but that's not the point. The test cases provide only integers, never floats. The result, however, is determined by how a language uses the division operator, ie if it does an integer or float division and under which circumstances. So this is a rather language dependent part. With -, the outcome is always the same value no matter what the language (type may differ), but with / the outcome depends on the implementing language. And the result the test expects is bound to how a language handles the / operator, you know what I mean?

@NobbZ
Copy link
Member

NobbZ commented Feb 26, 2019

Yes, I think I do.

@juhlig
Copy link
Contributor Author

juhlig commented Feb 26, 2019

:)

Anyway, I think making the tests self-contained the way you suggested is a good (better) way, too. What cons is supposed to do could be explained in comments. I'm just not sure what it'd mean for existing test generators. Those that already do a translation of (x, y) -> x / y to the respective tracks language can reasonably be assumed to do just the same with - instead of / without changes, but with an artificial construct like cons it is probably a different story that needs some interaction.

@petertseng
Copy link
Member

#1746 makes unambiguous:

  • What sort of division is expected (integer or rational)
  • which argument is the accumulated value and which is an element from the list

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants