Let's say I want to fork a thread within a do
-notation block, but I don't care about the thread id. If I write
forkIO action
GHC issues warning
Warning: A
do
-notation statement discarded a result of typeThreadId
. Suppress this warning by saying_ <- forkOS action
This is a good idea as I want to show that the program is discarding some result. However, this way it won't be apparent what's being discarded. I could write
threadId <- forkIO action
but then we're hiding the fact that we won't use threadId
anywhere, and GHC correctly warns
Warning: Defined but not used:
threadId
It seems that prepending underscore solves both problems:
_threadId <- forkIO action
My questions are: Is using variables starting with underscores legal according to Haskell's language specification? How portable is it? Is it documented somewhere? Is it encouraged for cases like this - to document that a result is being ignored?
If an identifier starts with an underscore (_), it's private to its library.
@BenW: TTBOMK, the C++ standard simply says that global identifiers starting with an underscore are not allowed, without making any distinction between syntax and semantic. (Also any identifiers starting with an underscore followed by a capital letter, and an identifiers with two consecutive underscores.)
Yes. In section 2.4 of the 2010 specification, it says
Underscore,
_
, is treated as a lowercase letter, and can occur wherever a lowercase letter can.
...so _threadId
is a legal identifier according to the language spec which should be utterly portable.
However,
_
all by itself is a reserved identifier, used as wild card in patterns.
...so you can't use _
alone outside patterns, thus can't use that value.
Compilers that offer warnings for unused identifiers are encouraged to suppress such warnings for identifiers beginning with underscore. This allows programmers to use
_foo
for a parameter that they expect to be unused.
So _threadId
is an ordinary identifier which you could use elsewhere, but you shouldn't be warned if you throw it away.
(Exactly the same text is in the Haskell 98 report.)
Examples:
main = do
_two <- return 2
print _two -- works
compiles and prints 2 according to the spec and
main = do
_two <- return 2
print 3 -- no warnings, but oops, didn't use _two
compiles without warning according to the spec, and
main = do
_ <- return 2
print _ -- syntax error: _ used as identifier
is a syntax error according to the spec.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With