-
Notifications
You must be signed in to change notification settings - Fork 166
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
Fix inc. ranges with start == end and negative step #2194
base: master
Are you sure you want to change the base?
Conversation
This changes behavior of inclusive ranges for the case where `start == end` and `start != second`, for compiled programs only. In this case the result is now `[start]` rather than a runtime error. Example: `1..0...1` now produces `[1]` rather than an "invalid range" runtime error. This makes behavior for compiled programs similar to that of the Futhark interpreter (and e.g. Haskell ranges), for at least this particular case (I have not looked for other discrepancies).
Do we have a good argument for why the interpreter behaviour is the right one? What are the underlying principles/rules? |
Looking at the fix, it's perhaps plausible that this was a typo in the first place. |
I thought I remembered reading Futhark (inclusive) ranges were based on Haskell ranges (ignoring those cases were the Haskell range would be empty or infinite), but I can't find any note of this so perhaps I made it up or heard it from someone who did. I then chose to conform to the interpreter since it seems to most closely mimic Haskell ranges. In case anybody not familiar is reading along: def haskell_like_range(first, second, last):
step = second - first
is_descending = step < 0
is_ascending = not is_descending
tmp = first
while (is_ascending and tmp <= last) or \
(is_descending and tmp >= last):
yield tmp
tmp += step In Futhark we for obvious reasons do not want infinite ranges, so we throw a runtime error when |
The general principle is that an error is thrown when The form |
I assume you mean throwing error when
Agree -- if I didn't know better I think I'd intuitively expect e.g. |
Alright, I'm pretty much convinced. Will you fix the compile error and add modify one of the range tests? |
Have fixed the unused variable warning (I assume you meant this), and will look at a test later when I have more time. But I am unsure of exactly how much I have convinced you of, hehe. Just the change proposed in the original commit? Or should we allow certain empty inclusive ranges, to address the inconsistency between e.g. I am also a little unsure of the current reasoning behind generating empty exclusive ranges. For example, as discussed |
The reason is that we would like the property that |
Note that more complicated ranges (such as I think everything with an explicit step), the size in the type will be a freshly generated unknown type, with no promises about what it might be, so we are at greater liberty to play games. |
This makes a lot of sense! I had not thought of this since I am not big into type theory. It also made me think that perhaps the validity of a range is more easily and concisely expressed in terms of its size -- e.g.: "a range is valid if its size is non-negative". But I'm having a hard time figuring out what the "size" of a range is in general -- the formula I'm not looking to implement, just curious. |
For conciseness, but also to better comprehend which (and where) changes need to be made.
* split step and step_zero computations. * no need to compute sign. * inline some definitions which were used only once.
Actually, after spending some time on thinking of a way to handle The problem is essentially: |
Branching logic is not by itself a problem. There's lots of it already. (In retrospect, I think having range expressions may have been a mistake - they are far too subtle compared to their merits.) |
There is a discrepancy in certain cases of inclusive ranges between the interpreter and the compiled backends. I do not know which of the two is intended, but from a quick glance I assume the interpreter has intended behavior.
So:
This changes behavior of inclusive ranges for the case where
start == end
andstart != second
start > second
, for compiled programs only. In this case the result is now[start]
rather than a runtime error.Example:
1..0...1
now produces[1]
rather than an "invalid range" runtime error.This makes behavior for compiled programs similar to that of the Futhark interpreter (and e.g. Haskell ranges), for at least this particular case (I have not looked for other discrepancies).