This is arguably a bug. You can also pass -parse-as-library
to parse a single file without going into single-file mode.
The top-level variable behavior was a language design decision at one point. It's a bug now and conveniently all of the forms of this bug seem to be assigned to me. It is on my queue, I'm aware of it, and I do intend to fix it some day since people seem to poke me about it at least once a week.
It gets really weird once you bring classes into the mix because the variable gets default-initialized to a nullptr
under the hood, so you segfault if you use it before the declaration/initialization. There are a ton of foot-guns here though because, like you showed, you can defined a function somewhere in the module that uses the global symbol. But unlike globals, which are lazily initialized, these things are sequentially initialized like locals, so if you call that function holding it like a global before the variable gets initialized, you'll have all sorts of fundefined behavior. It's great how the front door of the language is literally where the easiest memory safety issue shows up. 
The @main
was sort of geared toward libraries implementing a main function, then you being able to use protocol to select a variant based on what your MainType
conforms to. In the end, we end up with something that smells frighteningly similar to Java's public class Main { public static void main(String[] args) { } }
.
If you're working with an editor that has snippets/templates, I highly recommend setting something up where you can type @main
, hit tab or expand or whatever you select and have it fill out the full entry point. I also have an @maina
and @maint
for the async and throwing variants.
@ksluder
It would be nice to be able to simply wrap my top level code in @main func main() -> Int
when I decide my script needs to exit with a status code.
So in the response, I posted Doug's suggestion. We could totally have it so that you just throw a return #
in your top-level code and we could deduce that you want the returning variant. Then you don't have to say anything, just return. 
if blarpy() > 10 {
return 10
}
return 0
Now it gets weird with single-expressions. 42
becomes a whole program that returns 42
. 
(Edit, added @ksluder comment as a quote at the top of my response)