Skip to content
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

It's possible to use a single underscore as an enum value identifier (0.17.3) #7171

Closed
dawkot opened this issue Feb 1, 2018 · 14 comments
Closed

Comments

@dawkot
Copy link

dawkot commented Feb 1, 2018

type E = enum _

let x = _

is valid code

@Araq
Copy link
Member

Araq commented Feb 1, 2018

Why not? A single underscore can be an identifier.

@dawkot
Copy link
Author

dawkot commented Feb 1, 2018

Just reported it in case it wasn't intended

@GULPF
Copy link
Member

GULPF commented Feb 1, 2018

I thought _ as an identifier was just meant for destructuring assignments where a value should be discarded? There are special rules for _ so I don't think it should be allowed as an identifier in general. Example:

let (x, _, _) = (1, 1, 1) # Would complain about redefinition if any other identifier was used
let _ = 1
let _ = 2 # Again, the compiler doesn't complain about redefinition
echo _    # Error: undeclared identifier: '_'

@Araq
Copy link
Member

Araq commented Feb 4, 2018

Arraymancer depends on _ being a valid identifier.

@GULPF
Copy link
Member

GULPF commented Feb 4, 2018

From what I can tell Arraymancer uses _ as a special identifier in templates/macros, which isn't a problem. In fact, I would argue that such usage of _ as a magic identifier is a good reason to disallow it in other contexts (since treating _ as magic is dangerous if it might actually refer to something in the scope).

What should be disallowed is using _ for routines/enums, since it's already impossible to use it for variables. Basically as long as no _ symbol is introduced to the scope it would be OK.

Additionally, I think let _ = 1 should be disallowed, as it introduces a symbol that can't be referred to. Delaying the error message until the variable is refereed to is confusing.

@mratsim
Copy link
Collaborator

mratsim commented Mar 21, 2018

I tried to have a go again to remove _ but unfortunately failed. The history of this is here: #6387

When using generic return type in proc, identifier resolution happens before macro replacement which prevents from replacing _ before Nim checks if it's valid.

@andreaferretti
Copy link
Collaborator

Why not just use a different symbol in ArrayMancer? I used All in neo for slicing, not much longer and without any special connotation.

@dom96
Copy link
Contributor

dom96 commented Mar 21, 2018

Yeah, _ shouldn't be allowed as an identifier. It's a special character used for discarding when deconstructing tuples, and it should only be used in that context.

@Araq
Copy link
Member

Araq commented Mar 21, 2018

I don't see the problem. Who accidentically uses _ as an enum name?

@GULPF
Copy link
Member

GULPF commented Mar 21, 2018

I don't see the problem. Who accidentically uses _ as an enum name?

That reasoning can be applied to a lot of semchecking though... Disallowing _ makes the rules of the language easier. Some silly edge cases:

block:
  const _ = 1
  echo _ # Fine

block:
  let _ = 1
  echo _ # Error

block:
    const _ = 1
    block:
        let _ = 2
        echo _ # Prints 1

block: # My favorite
    var i: int
    var foo: int

    template _(): var int = i
    (_, foo) = (10, 10)
    echo _ # Prints 10

@Araq
Copy link
Member

Araq commented Mar 22, 2018

That reasoning can be applied to a lot of semchecking though...

How so? "Let's forbit the identifier brkkkk because it is ugly and could be used accidentically".

@GULPF
Copy link
Member

GULPF commented Mar 22, 2018

The reasoning "who does that anyway", which is how I interpreted your remark, is overly optimistic. People do lots of things that might be bad in hindsight, although usually not accidentally.

Also, the issue with _ isn't that it's ugly. The issue is that _ is an identifier with special rules in some contexts, which means that allowing it for symbols causes some strange behaviors. I would rather see that the usage of _ as a "don't care" identifier was extended. E.g:

x == (1, 2, _) # Only compare first two tuple elements
(_, foo) = (1, 2) # Destructuring assignment to already declared variable
const (_, foo) = (1, 2) # Destructuring assignment to const variable

Extending the "magic" behavior of _ becomes hard when it's a valid symbol name. At least without making breaking language changes.

@dom96
Copy link
Contributor

dom96 commented Mar 22, 2018

Extending the "magic" behavior of _ becomes hard when it's a valid symbol name. At least without making breaking language changes.

Indeed. By not forbidding it we are just begging for a can of worms to be opened at some point in the future.

If it's possible then somebody will do it. People have often surprising habits.

@Araq
Copy link
Member

Araq commented Dec 30, 2018

10 months later and it still hasn't caused us any real trouble. Closing.

@Araq Araq closed this as completed Dec 30, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants