consider the example where I came across this. I needed 8 char fixed hex representation of a given integer, so for input 16, output should be "00000010". This is my basic version for that
defp to_fix8_hex(num) do
"0x" <> num_hex = inspect(num, base: :hex)
rem = 8 - byte_size(num_hex)
prefix = 1..rem |> Enum.map(fn _ -> "0" end) |> Enum.join("")
prefix <> num_hex
end
The above doesn't work, when rem becomes 0. From my background in C style for loop, where increments or decrements are explicit, the loop itearation doesn't happen, when start and end constraints are beyond limit. here the confusion happens, because I'm expecting 1..rem to always count forward and whenever rem becomes less than 1, the counting should stop. The present .. behaviour is that it automatically changes direction from counting forward to counting reverse depending on the start and end values. This is not a problem when constants are used, like 1..10000 or 10000..1 where intent is very clear and never confusing. The confusion comes when one of the (either start or end) limit is variable.
The solution in this case was to treat rem < 1, as separate case and all was fine. Just that it took me some time to figure that out because I was used in writing this kind of logic in C in a particular way.
I see your point of iterators being lazy and why Enum.reverse will not meet the requirement. So probably a different syntax for decrements? But unless the confusion is common enough, I don't see any point in changing the present behavior.
thanks
miwee
On Sunday, December 25, 2016 at 4:26:09 PM UTC+5:30, Eric Meadows-Jönsson wrote:
Personally I like the behaviour of ranges when the end of range is smaller than the first. Can you elaborate on why it's confusing?
The problem with Enum.reverse is that it returns a list instead of a range so Enum.reverse(1..1000000) would return a list allocated with a million elements.
You are correct that it would be a backwards incompatible change so if we do decide to change it it can only be finalized in Elixir 2.0.
TLDR: it's a nit picking and may introduce breaking changes without possibly any significant gain, except conceptual clarity and explicitness.
iex(27)> n = 4
4
iex(28)> 1..n |> Enum.into([])
[1, 2, 3, 4]
iex(29)> n = 1
1
iex(30)> 1..n |> Enum.into([])
[1]
iex(31)> n = 0
0
iex(32)> 1..n |> Enum.into([])
[1, 0]
The result for n = 0, is little bit magical, as I was expecting it to return [], but instead it auto-magically detected that end is less than start and hence it counted decrementally. I think it creates confusion, particularly when both start and end are not constants like the above case given.
So does it make sense to restrict the behavior of .. operator to always count incrementally. For the case of decremental counting Enum.reverse can be used. In that sense 1..4 |> Enum.reverse() is identical to present behaviour of 4..1
--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.