make 1..num syntax always count incrementally and never count decrementally

66 views
Skip to first unread message

miwee

unread,
Dec 25, 2016, 5:28:03 AM12/25/16
to elixir-lang-core
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

Eric Meadows-Jönsson

unread,
Dec 25, 2016, 5:56:09 AM12/25/16
to elixir-l...@googlegroups.com
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.

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-core+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/da1cd897-1410-4237-b95f-04e61ec7bcfe%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Eric Meadows-Jönsson

miwee

unread,
Dec 25, 2016, 6:39:11 AM12/25/16
to elixir-lang-core
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.
On Sun, Dec 25, 2016 at 11:28 AM, miwee <me.m...@gmail.com> wrote:
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.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.



--
Eric Meadows-Jönsson

miwee

unread,
Dec 25, 2016, 6:52:29 AM12/25/16
to elixir-lang-core
One option is to introduce a Kernel.range function, which works similar to https://docs.python.org/3.5/library/functions.html#func-range
It is explicit, and it gives more power as steps (other than 1) for increment or decrements also can be defined. And this will not have any backward compatibly issues.

thanks
miwee

José Valim

unread,
Dec 25, 2016, 7:50:55 AM12/25/16
to elixir-l...@googlegroups.com
It is a known and documented behaviour. Even though it could be surprising for some, we would need a very strong reason to remove it from the language, and I don't think we have one here.



José Valim
Skype: jv.ptec
Founder and Director of R&D

On Sun, Dec 25, 2016 at 11:28 AM, miwee <me.m...@gmail.com> wrote:

--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-core+unsubscribe@googlegroups.com.

miwee

unread,
Dec 25, 2016, 7:58:34 PM12/25/16
to elixir-lang-core, jose....@plataformatec.com.br
agreed.
Few fixes may help
1. The documentation https://hexdocs.pm/elixir/Kernel.html#../2 can mention about backward counting behavior, when end is less than start
2. probably iex has a bug,
iex(41)> h Kernel.../2
** (SyntaxError) iex:41: syntax error before: '...'

   

On Sunday, December 25, 2016 at 6:20:55 PM UTC+5:30, José Valim wrote:
It is a known and documented behaviour. Even though it could be surprising for some, we would need a very strong reason to remove it from the language, and I don't think we have one here.



José Valim
Skype: jv.ptec
Founder and Director of R&D

On Sun, Dec 25, 2016 at 11:28 AM, miwee <me.m...@gmail.com> wrote:
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.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.

José Valim

unread,
Dec 26, 2016, 4:45:20 AM12/26/16
to miwee, elixir-lang-core
Good points, I will improve the docs.

Btw, h ../2 works for now.

I will investigate if it is possible to fix "Kernel...2" but it may not be as it is being parsed as Kernel .../2 and not as Kernel. .. /2.



José Valim
Skype: jv.ptec
Founder and Director of R&D

Reply all
Reply to author
Forward
0 new messages