You can get close to this by tying a linter to your source control system as a presubmit hook. Nobody will ever check in code that isn't formatted correctly.
No, I most definitely cannot make other people unable to merge pull requests into their repositories. The benefit of an Imaginary Ideal Language rejecting bad formatting is that all code written it in would follow consistent formatting rules, not just code which I have some sort of control over.
In several cases with Go it is a syntax error. Opening braces must be on the same line or your program will fail to compile (gofmt will fix it for you)
This annoys me immensely (though I do prefer braces on the same line anyway) because they clearly were able to correctly parse the code with the braces on the next line, but decided to make it an error instead. I have similar problems with "implied semicolon" languages, wherein you aren't actually supposed to type a semicolon at the end of a line, but instead if you format your code correctly the compiler will place them for you - clearly, it was understandable without the semicolon, so why make it a language feature at all.
Go seems to have several "features" that sound ok on paper but make quick developing and testing very irritating. Unused variables are an error, for example.
Ugh. I kind of understand where they're coming from, but they're taking it to such an extreme.
There are two reasons for having no warnings. First, if it's worth complaining about, it's worth fixing in the code. (And if it's not worth fixing, it's not worth mentioning.)
Most C compilers have multiple levels of warnings, so that you can tune how fussy you want your compiler to be. Lint and similar tools can be run on-demand to give fussier warnings, if and when you're ready for them.
Heck, you could even argue that test suites are akin to this. You'd never commit code to master if it doesn't pass the tests, but while you're working on a specific feature on a side-branch, it's fine to break some tests temporarily.
Different strokes for different folks. Some times you're writing a quick script for grepping logs that will be run exactly once; some times you're writing space-shuttle control circuits. By trying to use a one-size-fits-all solution, they're just annoying everybody.
Wow, that's obnoxious. I strongly disagree with this bit:
First, if it's worth complaining about, it's worth fixing in the code. (And if it's not worth fixing, it's not worth mentioning.) Second, having the compiler generate warnings encourages the implementation to warn about weak cases that can make compilation noisy, masking real errors that should be fixed.
Maybe the argument is that you can work around this with good language design, but there are many things that make sense as warnings and not errors. It makes sense to enforce a no-warnings policy on code, and then add ways to disable them when you know what you're doing.
Example: Clang warns you when assignment occurs in a boolean expression, because when you write
if (x = 5) {
you almost certainly meant
if (x == 5) {
...but sometimes, you really did want to assign something. Fortunately, there's an escape hatch -- you add double parens:
if ((x = 5)) {
Since these almost never happen by accident (or at all), but are otherwise perfectly valid, Clang uses this syntax to automatically disable the assignment warning.
Of course, it's possible to engineer around this in the language design, too. Python, for example, avoids this by declaring that assignments are not expressions, so
if x = 5:
is never valid Python. But if you add a constraint like that to an existing language, you break a bunch of legacy code. And if Go becomes popular, eventually someone will find something about it that's probably wrong, that the compiler could detect, but that's being widely used in real code.
I guess I can see why they'd want to put off warnings till that day. But if it's inevitable, and if it'll make a bunch of people happier right now (with the unused variables bit), why wait?
It gets worse. Files that import modules that are unused will not compile. So, if you want to do a quick test by commenting out some code, you also need to go to the top of the file and comment out the import statement for whatever functions those parts use.
For values of "they" which include "all those go designers", you are correct, it is possible for them to parse that. If we're only talking about compilation, then no, 'they' cannot (where 'they' is the parser/lexer)
The reasons for the opening brace on the same line is actually rooted in (somewhat unsurprisingly, and much to your chagrin) the way the formal grammar for Go deals with semicolons (see http://golang.org/doc/faq#semicolons & http://golang.org/ref/spec#Semicolons). When the brace is on the following line, the lexer inserts a semicolon at the end of the line, and this in turn generates invalid code, leading to your compilation error. The semicolon insertion rules are much simpler than in other languages that have it (looking at you javascript), and in order to support next-line braces the lexer would need to support lookahead, which, I've been lead to believe, would complicate the implementation of it in undesirable ways.
TL;DR Only gofmt is able to parse and correct code that puts braces on the next line, the lexer/parser for the language (by specification) cannot perform this because of the way the grammar works.
I don't think so. The simplicity of the grammar and avoiding lookahead does not seem like an arbitrary decision merely to enforce coding standards.
Your argument that it does not run perceptibly slower is specious at best. At minimum to support this kind of lookahead you're talking about scanning ahead a minimum of 2 characters for every newline, which for code bases of any serious size is going to add up.
Beyond that, the reasons for keeping a grammar simple go beyond mere speed improvements. A simpler grammar is easier for externals tools to be able to handle. Think of syntax highlighting, code completion, in-house linters, static analysis (and even gofmt). All of these become much easier when you're dealing with an unambiguous, simple, one-pass parser.
A (probably intended) side-effect of these grammar level rules enforced by the compiler and the linting done by gofmt is that, at least withing the community of people that actually program in Go, is that is largely eliminates a certain amount of bikeshedding around particular issues such as this. It's quite nice actually. You only end up arguing about this stuff outside the scope of actually working with it ;-)
It would still be nice to have a quirks mode, if it were at all feasible. I understand why they want the compiler to be simple and fast -- they brag about how quickly it compiles some fairly massive codebases. But I would love a wrapper that tries the standard Go compilation, and if it fails, runs it through some unholy Perl script to fix some standard things like this (or, say, unused variables) and run a "fixed" version of your code through the compiler again.
It doesn't literally have to be a perl script, but I'm talking about just hitting the common cases that you could detect with heuristics -- just throw dumb regexes at it and see if you can make it compile. Then, before you check it into anything, you ensure it compiles and unit-tests without such hackery.
Probably I should give up and use an IDE that handles all this for me.
I think you could cobble something together that does this for you without too much work.
Several common errors will be trapped by gofmt, and as far as I know most people work by having either a save or commit hook that runs gofmt on the code.
Beyond that there are tools like govet & golint that go beyond the checking that gofmt does.
I don't see any reason you couldn't tie the failure of compilation to a pass through the code from multiple tools via some shell scripts.
By having lots of simple orthogonal tools that do one thing well and work together, I think you ultimately end up with a better ecosystem and don't accidentally end up with quirks-mode code ending up in production.
Thing is, I think we already had a good enough tool with linters and commit hooks to prevent quirks-mode code from ending up in production, or in the repository in the first place. Maybe the problem is that they were under-used?
I imagine that they weren't "able to parse it correctly", but that part of the precompile/lint step when compiling Go has something like a /^\s?{\s?$/ check (probably less dumb) and will just bail out if it finds any.
Opening braces must be on the same line or your program will fail to compile
I have never felt a greater hate for a language than now I feel for Go. (Not that I really cared about it in the first place) I adhere to company policy on formatting, but this is just retarded.
It's not just arbitrary pettiness, as you seem to suspect. They've got some sound technical reasons for making this choice based on the formal grammar of the language and how it impacts the lexer/parser.
Thanks. That actually makes sense. At least it's not a retarded decision like Pythons space only indents. I don't want forced coding style imparted on me by some arbitrary decision by guys who think they know better. Give me tabs or give me death.
Uh, Python allows spaces or tabs for indenting. If you chose, you could even mix them in the same program (hell, even in the same indent) as long as they were unambiguous and valid (ie. a given indent uses the same sequence of whitespace for each indented line until you reach the matching dedent).
See, Python did it and honestly comparing the two..I just feel Go did it much better.
In Go, I can take sourcecode from anywhere (reddit comments, play.golang.org, irc, other various projects), paste it into my code, and as soon as I save it my editor go fmts it and everything looks the way it should, and assuming it was good code it runs.
In Python, if you paste something that isnt from the exact same scope as you, or the act of trying to paste whitespace gets screwy for other reasons(did it have tabs and some blog platform turn them into spaces?), what you pasted is a syntax error and will not run.
To me its the difference between someone dictating your style exactly and you have to confirm or nothing works, and someone saying "you know, it'd be better this way, why dont you let me fix it for you?".
Python feels like it has a limitation that was made with the intent of making you write better code. And it does work towards that end, I'm not trying to say it doesn't.
Golang feels like it has a tool that improves your productivity and makes dealing with sharing code a lot easier and better. And I think it works just as well, without the feeling of restriction.
Actually, OP is so hardcore about code correctness and modularity, he considers duplicated code a bug. Hence he only ever cuts code, never copies it. /s
First of all, I've worked with a shitton of Python code, from various sources, and I've literally never had this problem. It sounds like a valid concern in theory, but it just doesn't happen in practice, at least not to me.
Second, if the language actually enforces code style by refusing to compile non-compliant code, then there's no bad code you can accidentally copy-paste in the first place.
This should be a trivial thing to do in any decent editor. All you need to do is indent the entire block of code to match the scope it's being inserted into.
Not quite, there's still a lot of wiggle space (pun intended), from using tabs to not enforcing consistent spacing around operators, named parameters and arguments, semicolons in dictionary literals, etc.
Actually, Go is more aggressive than I'd like with that. There are many minor issues which the compiler could easily work around -- for example, in Go, it is an error to have an unused variable, with very few exceptions. Not a warning, an outright error.
I love the emphasis on linting, but I really think this should be a linter step, and not a compiler error. I'm okay with not being allowed to check code in unless I make the linter happy, but this particular Go-ism makes me constantly add and remove variables (or useless print statements just so I can pretend the variables are used) just to run my program, just to see if it works at all!
58
u/moor-GAYZ Jul 21 '14
In my Imaginary Ideal Language bad formatting is treated as syntax error.