Nim: Space required in str[1.. ^1]

Created on 9 Aug 2017  路  15Comments  路  Source: nim-lang/Nim

It would be less confusing if str[1..^1] worked the same way as str[1.. ^1]. i.e. if that space weren't required in there.

That will also be consistent with str[1..str.high] and str[1..<str.high], where that space after .. is not needed.

Most helpful comment

@Araq IMO we should remove all shortcuts. Why were they added anyway?

All 15 comments

I believe str[1..<str.high] only works because the operator ..< is defined. I guess we could define ..^ as well?

Huh, now that I looked into it. The ..^ is also defined here: https://nim-lang.org/docs/system.html#..%5E.t,untyped,untyped. Strange that it doesn't work.

In fact, it does work for me in devel (are you using 0.17.0?).

Closing.

You are right. Sorry about that, I had momentarily switch backed to 0.17.0 and that's where I had documented this "space after .. requirement". I then forgot to check if that was still true on the devel version.

@dom96 Actually, can you please reopen this issue. I finally realized why I was confused..

var str = "abcd"
str[0..^2]  # This works (with starting index 0 and no space after dots)
str[0.. ^2] # This works (with starting index 0 and with space after dots)
str[.. ^2]  # This works (no starting index and with space after dots)
str[..^2]   # This **doesn't** work (*no* starting index and *no* space after dots)
# Gives this error:
# nim_src_30025WLw.nim(7, 10) Error: type mismatch: got (int literal(2))
# but expected one of: 
# template `..^`(a, b: untyped): untyped

There is no unary '..^', there is no bug here. The compiler gives a precise error message.

To prevent confusion, should that unary operator be added? I don't know the inner workings of Nim; I just started reading Nim In Action this week. So apologies for a dumb question.

Is adding that unary operator too difficult? Or would that introduce a backward incompatibility with other parts in the language? Would it be bad to assume the starting index as 0 if ..^ operator were added?

Also, is treating ..^ as an unary operator the only way to make this work?

It makes me wonder why a special character ^ is used here and not the convention to use negative indices to count from the right of an iterable. If str[..-2] were allowed, then may be the corner case operators like ..^ didn't have to be defined. Again, these are some of the naive thoughts that come to my mind as a new Nim user. Hope none of those are taken to be offensive. And hopefully some of those can help resolve this issue.

I have seen whitespace sensitivity only in Bash (like, do a=1, etc to prevent difficult to debug errors in Bash script) and other shell script variants so far. So I couldn't resist filing this issue.. hopefully to get this corner case whitespace sensitivity fixed before the final release.

Is adding that unary operator too difficult?

No, it would be a single line in system.nim but these shortcuts are just that: shortcuts. You still have to understand how the language works and shortcuts should be applied for the common cases, not for consistency so that you can come further without understanding the rules.

It makes me wonder why a special character ^ is used here and not the convention to use negative indices to count from the right of an iterable. If str[..-2] were allowed, then may be the corner case operators like ..^ didn't have to be defined. Again, these are some of the naive thoughts that come to my mind as a new Nim user. Hope none of those are taken to be offensive. And hopefully some of those can help resolve this issue.

'^' has lots of advantages over '-' and '..-' is also parsed as a single operator.

I have seen whitespace sensitivity only in Bash (like, do a=1, etc to prevent difficult to debug errors in Bash script) and other shell script variants so far. So I couldn't resist filing this issue.. hopefully to get this corner case whitespace sensitivity fixed before the final release.

Whitespace sensitivity is everywhere, 'a + +' is different from 'a++' in C based languages.

No, it would be a single line in system.nim but these shortcuts are just that: shortcuts.

I understand that these are just shortcuts based on the link that @dom96 posted earlier. So I understand that ..^ expects two arguments. But it would be nice to have consistency. If the shortcut for ..^ as binary operator is added, then it would be nice to have one for ..^ as unary operator too, else it causes surprises like this. For consistency, the opposite would also be fine.. have neither the binary ..^ shortcut not the unary.

You still have to understand how the language works and shortcuts should be applied for the common cases, not for consistency so that you can come further without understanding the rules.

Consistency plays a big role in making a language feel robust and not Bash-like. People should not have to remember stuff like:

"If I want to do [1.. ^-2], it is OK to remove the space after the ..."

"But if I want to do [.. ^-2], it is not OK to remove the space after the ..."

"If I want to do [1.. <str.high], it is OK to remove the space after the ..."

"But if I want to do [.. <str.high], it is not OK to remove the space after the ..."

Please consider applying the consistency factor.. either make ..^ (and ..<) both binary and unary, or none.

^' has lots of advantages over '-' and '..-' is also parsed as a single operator.

OK. I will learn about the advantages as I am gradually learning the language.

Whitespace sensitivity is everywhere, 'a + +' is different from 'a++' in C based languages.

This case is different, because it is easy for anyone not knowing the Nim internals to interpret [..^2] as [:-2] from Python (I know that it actually is equivalent to [:-1]). So one might think that just as [: -2] vs [:-2] don't matter, it would be the same with [..^2] and [.. ^2]. But it is not, and so I opened this issue.

Another issue about dots and spaces: https://github.com/nim-lang/Nim/issues/6215

Consistency plays a big role in making a language feel robust and not Bash-like.

On the lexing level the rule is: "Special ascii chars like % . & $ are collected into a single operator token". It's simple and works and nobody has "to remember stuff like ..." because it means using spaces around the '..' always works.

There is no Bash-like design here, in fact Python's rule of "+= is a single token, :: are two colon tokens" feels more Bash-like.

And once '..^' works in more cases, you can come up with '..^-' that fails and then you can argue to add template '..^-' for "consistency". Good design is not an endless whack-a-mole game, good design is simple rules that are then explained well to the users as in "chars like % . & $ are collected into a single operator token".

This case is different, because it is easy for anyone not knowing the Nim internals to interpret [..^2] as [:-2] from Python (I know that it actually is equivalent to [:-1]). So one might think that just as [: -2] vs [:-2] don't matter, it would be the same with [..^2] and [.. ^2]. But it is not, and so I opened this issue.

Yes I know where you're coming from, but you can hardly blame us we picked a different syntax for different things.

"Special ascii chars like % . & $ are collected into a single operator token"

That's useful to remember.

using spaces around the '..' always works.

I will stick with that rule for my code. Thanks! It should also be put in the documentation/tutorial to always using space after around ... That is what I meant by ".. or none." when I said earlier:

Please consider applying the consistency factor.. either make ..^ (and ..<) both binary and unary, or none.

.. So it might be better to remove the shortcuts put for ..^ and ..< as binary operators to prevent confusion for future new users.

I'll now update my Nim vs Python post adding a suggestion to always using space after around ...

Update: Done

@Araq IMO we should remove all shortcuts. Why were they added anyway?

Uhh, because they are very convenient? Not gonna happen that I remove them just because a newbie got "confused" (no offense). That cannot be a serious criterion for yet another pointless bikeshedding breaking change.

By that logic a unary ..^ would also be convenient and thus should be included, no?

If not then why are the other operators convenient but this one isn't? :)

Well. I would never have introduced the unary .. in the first place. But it does exist and therefore an inclusion of an unary ..^ is to me a requirement for consistency.

Was this page helpful?
0 / 5 - 0 ratings