Go Lang: Comments Are Not Directives
Go 1.4 starts to use comments as directives. I think that is a realy bad path to go on the long run. You see its beginnings in following 3 examples:
# used to set a canonical import path for a package: //import "foo"
# used to generate code: //go:generate bar
# used to document the result of a example function: //Output: foo
Comments should not be directives. Comments are free form, they do not have a syntax (as demonstrated in the examples). Comments are for humans - programms should ignore them or threat them as - comments!
It is my optinion that if Go needs some kind of annotation, than there should be a new syntax for it.
I would propose that directives to the tool chain will be marked with
#TAG: DIRECTIVE
a tool would be able to register the TAG with the go build environment. If a TAG is found in the code - the tool is called to do what ever needs to be done.
221 comments
[ 3.7 ms ] story [ 337 ms ] thread.
That's absolutely a mischaracterisation, and a hurtful one at that because we absolutely care about our developer experience.
"go generate" is a mechanism for invoking code generation tools; tools that people were already using in a variety of ad hoc ways. That's all. Macros are another thing entirely.
Our conservatism should be a testament to how much we care about quality. We don't want to do anything by half measures, as that serves no one's interests.
Offering code generation as a solution to code reuse is not caring about quality, it's laziness.
Saying "it's open source so you can just add feature X or change feature B" only works if you are part of some core team or are respected via other means. Github is littered with projects that have lots of Pull Requests that never get pulled.
There are many cases where project forks become more popular than the original project itself.
Or d) that I have any time in my life to undertake such work.
As long as it aligns 100% with the bizarro ideas of the core team regarding comment pragmas, code generation, vendoring, generics, etc.
I actually don't think this was an unfair phrasing. I had actually felt insulted when `go generate` was announced. "You're sweeping [generics et al] under the rug using comment-bound directives and telling me it's an elegant solution to problems? Do you think I'm an idiot?" Was, in fact, very close to what went on in my head when I read that initial post/slideshow.
I don't like to be degrading when it comes to differing opinions on coding practices - if generated code and comment-bound directives are good for you, well, okay - but being told that I should like it and stop questioning? That's insulting.
I think the deeper complaint that's coming through is not that the Go team are bad language designers who don't care about the developer experience, but that they are condescending towards the community. Even if you really, really don't mean to be.
If the language is so conservative as people claim, it should have neither macros/generics nor any of these pseudo-macro-generic-y half-measures.
We made the decision that "//go:" is the syntax for comment directives. The old ones stay around for compatibility reasons.
Previous discussion: https://groups.google.com/forum/#!searchin/golang-dev/commen...
For an example of what this looks like in actual use, see the very popular go-sqlite3 library: https://github.com/mattn/go-sqlite3/blob/dee1a37fe11067e9797...
I personally think that large block-comments of code that actually do something, but only if above a certain import really strange and unexpected; it means re-ordering imports can break things, changing around spacing can break things, and tons of other things.
All of these of course are minor things. Go does a lot of things very right like easy of concurrency, scope and quality of the standard library and easy of deployment. Looking forward to the GC improvements in the near future as well as a day when we get generics. I'll be a happy camper then.
/// <reference path="../typings/tsd.d.ts" />
//todo: bar
to do stuff with the code, and makes the program fail because it's not done, because you don't know about it. with a #todo: bar the go tool chain would catch this error
> I think this was a bad decision. I think you would agree as soon [as] a tool ... uses
(i.e., that the `//todo:` syntax would unambiguously demonstrate the bad-ness of the decision).They could use the same convention as typescript and use a triple slash instead. That wouldn't change much of the language and impact IDEs, but at least distinguish between human comments and tooling instructions.
the main problem is not technologie but semantic. If you agree with me that the meaning of a comments is communication between humans, than you must also agree - in my opinion - that comments can not be directives to a tool chain.
It is ambiguous. It is error prone. It is easily solved using an other token.
And in the long run it may lead to madness like Java testing and documenting frameworks.
as for technical problems - I think some really bad ones are mentioned in this very discussion!
But the complaint is about //foobar: and that is just confusing.
In go 1.4, save the following to a file and run 'go generate' on it: https://play.golang.org/p/9WJtxClRXr (I'd make it run in the playground, but you can't 'fork exec', so exec.Command($GOBIN, generate) won't work sadly)
Even though that code has no comments (only a multi-line string), go generate will run and print out a '\'.
I also used that generate command to point out that with generate, as it exists in 1.4, there's actually NO WAY to print out a dollar sign.
The dollar-sign part of this is fixed in master (so go1.5), but it was fixed not by allowing '\$', but by the bizarre $DOLLAR environment variable. See https://go-review.googlesource.com/#/c/8091/
These "features" make the use of comments as directives even worse, because it's NOT comments being used as directives in the case of go generate, but simple string matching. It literally just loops through lines of text and checks if it startswith the correct substring.
This was, of course, done due to lazyness (same as $DOLLAR and many other 'features' of go), and the lazyness is starting to show through the cracks here and there.
Go often prefers pain for the programmer for the compiler developer's life being simpler by about 5 minutes.
I think the reason why people are so upset/surprised is because they expect better from the Go team. Sometimes it really feels like they take the lazy route without putting enough thought and polish into things. Which is amplified by the previous statements regarding for example generics where they said they wont introduce them until they find a really good way to do it but then crank out half baked stuff like this.
I think that was the case with Go from the start. Can you think of some aspect that was especially well thought-out?
And some aspects of the Go SKD are horrible in practical use. Case in point, most things math related.
Also, Java has a head start of nearly 15 years on Go, and the Java community is (or used to be, at least) pretty huge.
Not that this invalidates your point.
It's a crapshoot what will be an interface and what will be a struct, which is one of the fundamental features of the language.
Returned error values are sometimes errors.New (e.g. io.EOF) and sometimes random fmt.Errorf strings that couldn't possibly be handled (e.g. all of tls.go basically), sometimes actual structs (e.g. PathError), and sometimes panics.
If you can't even get error handling right and consistent, what claim do you have to consistency? At least in java it's pretty much all exceptions.
The math library, as mentioned above, is pretty darn iffy.
The existence of both 'path' and 'filepath' is possibly a mistake.
The 'heap' and 'list' in collections both seem like they should be similar, but 'heap' operates on a thing that fulfills its interface and list operates directly on arbitrary objects without some interface needed.
Due to the lack of 'protected', the std library is littered with exported fields you shouldn't use (e.g. gob.CommonType and template.Template.*parse.Tree and so on).
Sure, the library is consistent in many places because the language is so small there's little else it can do but be consistent, but the fact that it falls flat in error handling and has visible warts makes me feel that it's a very broad std library, but far less consistent than, say, Rust's (where everything returns consistent Optional error types) or Java's or Smalltalks. Sure, it's more consistent than the clusterfuck that is ruby and/or python or javascript or (heaven forbid) c/c++, but by no means is being better than any of those an achievement in this category.
My biggest problem with the math library was, IIRC, everything only takes float64s, which makes dealing with any of the other number types more difficult than it should be (I shouldn't need to cast an int to a float and back in order to get the max of two numbers).
This is the advantage of having errors be interfaces rather than concrete values. Once you learn how to use it, it's a strength. The usage of structs that satisfy the interface (as in PathError) is clearly documented and completely predictable. If your concern is that a certain package could use a struct satisfying the interface and does not, well, one advantage of errors as interfaces is that you could propose this change without breaking the backwards compatibility guarantee.
It's really important to keep in mind that errors are adopted from error values in C, which means that their idioms and usage is inspired by that rather than by exception handling. Many new Go programmers (including me, when I started) were more familiar with exception handling in higher-level languages than error handling in idiomatic C, so it does take some getting used to.
> and sometimes panics.
Do you have any examples of the standard library using panics to signal handle-able errors (not counting cases in which the panic is recovered at the top-level in the library and never visible to the caller)?
> The math library, as mentioned above, is pretty darn iffy.
The only complaint I have had about package "math" is that all operations are defined on float64s, which can be annoying, but is far better than any alternative. That's an annoyance, but it's certainly not an inconsistency in the library.
Do you have any other examples of inconsistencies in the math package?
Are those 79 handle-able errors, or are they programming mistakes?
Speaking of reflection, there's a metric TON of runtime panics in the reflect package. Hell, I'm not sure there's a method in there that can't panic.
No doubt, however, you'll say that's cheating and the expected behavior of that package, so how about NewTimer (playground https://play.golang.org/p/jDKniK3aqa ). It does not give me an opportunity to recover from bad input by passing an error out, it just panics. It is also not documented that it panics afaik and other functions in time (time.Sleep) take negative durations and handle them just fine. This is definitely inconsistent with other std library functions that can take bad input and return errors.
I also think it's disingenuous to say "Keep in mind errors are from C and at least they're better than C"... the comment I'm responding to is a comment regarding go std library being one of the most consistent (implicit compared to ANY LANGUAGE) so I may bring in anything I wish, and sure Go's errors are a step up from C, but they're awful compared to other languages. They're basically passing around strings with no builtin way to create a trace of errors to return up the stack to maybe be printed, no default way to create an optional type with an error value, and no consistent way to determine which of N errors it was that was returned from a function without using a regexp 90% of the time because that damned fmt.Errorf / errors.New... And yes, using a Regexp in your error handling IS a problem.
> defined on float64, which can be annoying, but is far better than any alternative
Funnily enough, the 'rand' library implements everything by just having multiple functions and postfixing them with types (rand.Uint32, rand.Int, rand.Float32) and strconv does something vaguely similar.
Whether one or the other is better, that's another inconsistency in the stdlibrary; do you have many functions per type or only one function for one type? I have no clue how Go could have abused you such that you are able to conceive of not having a builtin int64 compatible 'min' function as a good thing.
Actually, perhaps your post is simply a plea for help as Go has tied you up and holds a gun to your head, in which case I suppose we should mount a rescue mission forthwith! Just let me write a quick timer to keep track of our progress... -1 you s.. err panic
(I bet you'd be unhappy at Rust irrecoverably panicking the thread for simply performing addition, if the result overflows!)
It's also important to keep in mind that people who don't like Go's approach to error handling might not be in favour of the exception-handling way, either. :)
https://news.ycombinator.com/item?id=9439948
My biggest disappointments early on was not even having a Max/Min function for ints.
I think this is a classic case of Go's need for "simplicity" hamstringing the language. When handling min/max, they had a few options:
1) Treat numbers as a special case and have a polymorphic min/max that operates on any number type. This is out of the question because it is obtuse and irregular and neither of those things are the "Go way"
2) Properly abstract over numbers somehow. This can be weakly done using Go interfaces but 1) it would require >, < etc to all be methods on the number types. But then Go would need operator overloading and that's not the "Go way" 2) using an interface is actually bad anyways because it doesn't make guarantees that input type =:= output type. To do that you need proper generics and then use a common subtype or take it further and use a Numeric typeclass. This is way too complicated and not the "Go way"
3) Write a min/max for every number type. Due to lack of overloading, each would be named accordingly (minInt64 etc). This is ugly and definitely not the "Go way"
4) Just use the most "general" number type and write min/max for that. You can just cast on the way in and out so this "works". It doesn't require API bloat or more language features, so it's the "Go way"
So much that devs end up using float64 everywhere ...
Which makes complete sense given it's webscale enough for nodejs.
I guess not so much definitely not the "Go way", just not the go way for the math library.
Have a package for each type, so you can import the one you need (e.g something like math/uint64), and eventually can rename it on import as is best fitting. Also, make it an external package in golang.org/x (like godoc&al) so as not to be bound to promises regarding language stability while at the same time offering a centralized implementation.
> 4) Just use the most "general" number type and write min/max for that
This is precisely what strconv.ParseInt does[0], with some obscure, runtime evaluated integer magic values of all things (instead of readable, type-safe, compile-time asserted enums).
[0]: http://golang.org/pkg/strconv/#ParseInt
Go is a small incredibly useful and composable set of libraries that handles a vast amount of cases with a small amount of code.
Go routines, channels and select. With very little else, it's possible to write some very useful code in a way that's concise, elegant and easy to reason about.
And Go is not quite expressive to address higher level, but common, constructs ( https://gist.github.com/kachayev/21e7fe149bc5ae0bd878 ) in a conceise and elegant way.
And if you access anything outside of channel provided stuff in Golang, you have to bring your own safety.
Maybe it's just my advancing age (for a programmer), but I find myself gravitating towards the "It's not finished when there's nothing left to add, but when there's nothing left to remove" mentality when it comes to programming languages. I find that I'm only willing to tolerate new language features when they introduce benefits that go beyond expressiveness.
Yes, "maybe it's just my experience and wisdom with regards to programming". Do you really expect anyone to fall for that crap?
If you are creating a programming language that wants to maintain backwards compatibility surely every check in you make would be as close to perfect. No ?
Perl has been around since 1987. I would expect Go (first released in 2009) to have learned valuable lessons from earlier failures. This particular set of features doesn't appear to be very thoughtful.
Interesting contrast to the philosophy of Perl 6: 'torture the implementor on behalf of the user'.
"Every language contains novel features and omits someone's favorite feature. Go was designed with an eye on felicity of programming, speed of compilation, orthogonality of concepts, and the need to support features such as concurrency and garbage collection. Your favorite feature may be missing because it doesn't fit, because it affects compilation speed or clarity of design, or because it would make the fundamental system model too difficult.
If it bothers you that Go is missing feature X, please forgive us and investigate the features that Go does have. You might find that they compensate in interesting ways for the lack of X."
[0] https://news.ycombinator.com/item?id=9523187
So what if you have a bit of code that you are half way through and you want to comment it out as well as the imports. I've done this countless times over the years.
I raised this on the golang dev forums and got nowhere: https://groups.google.com/d/msg/golang-dev/r4rdPdsH1Fg/yjOOz...
The response was basically "we disagree" and I wandered away feeling confused that so many bright people couldn't see the problem here.
http://fixunix.com/plan9/523380-%5B9fans%5D-using-acme-edito...
I thought at first that this reaction was just sour grapes ("nasty people on the intertubes didn't like my post"), but as I analysed it more I managed to pull out three elements:
1. If my sense of elegance and the Go team's sense of elegance is this divergent, then the language will probably get uglier to my eyes as it continues to evolve.
2. If this is the reaction from the team to this (relatively small and inexpensive to fix) problem, then we can expect absolutely no movement at all on the bigger and harder problems (dependency versioning, generics). I used to have faith that these very smart people will come up with an elegant solution to these issues - I still love the simplicity and elegance of the standard library - but my faith has now gone.
3. Brad's response was amazing and I'd follow him anywhere, but... I don't want to follow the rest. If I'm to commit my time and effort to learning (and to a tiny extent popularising) the language and being part of the community, I want to believe in the people building it. I don't any more.
Humans are weird.
Just say no is a good slogan for "bad" things but pretending that syntax highlighting is "bad" is senseless.
Elegant design...
meh.
I don't see why that's so hard to imagine. Just because someone is skilled/bright in some area doesn't mean that they are skilled/have good taste in another area. Even if those areas are very similar from a high-level view, like both involving programming.
There has been a lot of appeal to authority with regards to the Go designers/developers - basically that they have a long track record of making great/influential software. And though appealing to authority certainly isn't without merit, I think it was taken a bit far, namely that it was used as an argument to try to end all discussion. And secondly the things that they are famous for does not seem to be related to PL/design.
That's a rather disingenuous summary given that literally the very first response is Brad Fitzpatrick from the Go team agreeing with you, acknowledging that it's unfortunate, and admitting that it can't feasibly be changed yet due to the compatibility guarantees. And then shortly afterwards, he encourages you to bring this point up when Go 2 comes around.
EDIT: For the downvoters, quoting Rob Pike in one of his presentations, "Go's design is done".
Regardless, issues are still filed under the tag of `go2`, even by Rob Pike. There's no reason to believe that go2 won't eventually happen.
If I had a huge amount invested in Go I would consider forking it - it is one thing to have a benevolent dictator, but if he doesn't at least listen then there is no point at all.
> But I disagree that putting commands in comments at all is a good idea. Just because other languages do it doesn't make it a good idea. It's clearly a hack to get around some historical problem, and we're better than that.
A member of the Go team says:
> Where you see a hack I see an elegant design.
It's never been an elegant design, at best, it was an acceptable design in the 90s.
I am in favor of #TAG: DIRECTIVE or @TAG:DIRECTIVE
CGO, for example, expects a comment immediately before a special import statement. A blank line between that comment and the import statement means that the comment is not attached to the import statement's AST node, and so is ignored. This confused me a fair amount when I started with CGO.
Part of the problem with comment syntax is that it's intentionally lexical and uniform. This simplicity means that you can easily obliterate the content of comments at any point in the input file stream via the tokenizer. However, Go instead has to bend over backwards in it's compiler toolchain to preserve comments beyond the lexer: in the parser, AST, code generator, etc.
Compare to docstrings in SmallTalk/Python/Clojure, where they are actual parsed string literals. Also compare to C#, which has explicit and distinct syntax for comments, metadata, and compiler directives. Comments can be inserted more or less anywhere. Metadata only where it's unambiguously attached to an AST node. And directives similarly to statements, unambiguously detached from other AST nodes.
With proper syntax for metadata, the CGO case would have been a compile time error about no AST node for the metadata to be attached to.
With proper syntax for directives, the //go:generate string-scanning bug would have never happened.
These syntaxes must be disjoint from comment syntax to eliminate the problems.
At their level of prestige they can kinda work on whatever they like instead of having to live through and slog through the kind of crap code that accumulates on a project where you have people far below their level working along side people only slightly below their level.
If you only ever work with fellow top performers, you never need the language and tool features that make it less to work with idiots.
And then they do things like this comment stuff.
You don't judge a software product by the credentials of who wrote it, you judge it by whether it's a good software product or not.
The statement was asinine. I'm legitimately curious if the comment owner knows who is part of the core team.
Yes, I know. And I know perfectly well that Go at its current immature state would never have gotten the kind of attention and consideration if it had not been designed by Mr. Pike. While I believe that many of the warts of Go are by design, some are obviously not.
False dichotomy. The fact that a language is being used for big projects (or used at all) doesn't mean it has great design. Think of PHP...
I also completely fail to see what Docker's funding has to do with Go's design.
Docker is written in Go and $95m is more validation than you'll get in ten lifetimes.
Maybe it would have been easier or harder with another language? Who knows.
The valuation has everything to do with Docker's business model and nothing to do with the language they use to implement that vision.
At no point have I made a relative statement about Go being better than another language. The only claim I would ever make is that Go is well designed and effective for certain tasks, as demonstrated by use (validated by investment, which we can accept if we assume rational investors -- not going to debate that).
Now the claim that started this was that Go authors are greenfield celebrity programmers and they don't spend their time in the trenches (as indicated by certain parts of the language that some people - usually from "enterprise" languages - don't like; heavily and unapologetically paraphrased). That statement is asinine when you consider the background of the authors and the projects they've been involved in over their collectively lengthy careers.
I can imagine a design that works where only the lexer keeps track of comments (with locations) and the remaining stages do not. In fact using comments to generate code is not all that different from using comments to generate documentation (like doxygen) and that shouldn't require comments at the AST stage.
Yes. Though it's worth mentioning that they use the same AST infrastructure for `go format` and `go fix`. That means they need to track comments anyway. However, those use cases don't necessarily have the same requirements for accurately matching comments to semantically meaningful nodes.
> using comments to generate documentation (like doxygen)
1) I don't really believe in javadoc or doxygen really.
2) Even if I did, I'd prefer actually (and similarly lightweight!) metadata notation.
3) Also consider runtime documentation support. eg: https://clojuredocs.org/clojure.repl/doc and https://clojuredocs.org/clojure.repl/source
When PHP did it for Python-style decorators everyone thought it was stupid. And while the build tags in Go are okay by me, doing it for CGO especially seems like a hack.
The directives are pretty visually distinct. You could easily configure your editor to highlight them differently if you so chose.
https://golang.org/cmd/gc/#hdr-Compiler_Directives
2. I could keep adding syntax support as they come along and handle all the inconsistencies, but that is not a solution. It's a hack.
This in itself isn't bad, but the problem it causes is that the Googlers (who do not experience the pain that other users of the language do) are still the majority voice in any decision. Maybe not in numbers, but definitely in weight.
There have been a number of changes pushed through that make sense in Google's use case but not for general development use. Stuff like declaring a folder named "internal" special where it wasn't before. Perfectly understandable in Google's internal uniform codebase, where nearly every package is understood and the world is small. Not a smart change to make a few years into the 1.0 compatibility freeze though, since you can bet that a lot (I even dare say a majority) of 'regular' developers won't know about this and might run into problems because of this at one point or another.
This is just a small example that I can recall out of the top of my head but my worry is that this is happening more often with a lot of features.
Counterarguments from Googlers are usually along the line of "Go has X contributors, only Y of which are Googlers", but that is not the full truth. The top 5 contributors are still employed by Google. If you read the golang-dev mailing list, especially when it comes to discussions about tooling and ecosystem, you'll see that the Googlers have an overwhelming voice and will not shy away from flat-out rejecting criticism to proposals that might be nice for Google's use case but cause ambiguity and complexity for other developers.
Having said that, I still love the language and design. I just whished they shied away from magic comments and half-baked solutions for dependency management.
https://news.ycombinator.com/item?id=8733705
I was severely downvoted and did not get many who agreed with me.
Where can I read more about this?
* Automated refactoring that is editor agnostic? check.
* Editor agnostic built in documentation tool/server? check.
* Editor agnostic Code analyzers/oracles? check.
Go's core dev team is many things but saying they don't care about tooling and ecosystem is a gross misrepresentation. They may not care about your specific IDE or preferred language design but they most definitely care about making tooling available to everyone regardless of IDE/editor choice.
Speaking of which I do not see any official recommendation of an IDE for Go.
Learning an IDE isn't a big deal, but it isn't, say, preferable to not having to learn one. I know Eclipse, but I avoid using it in all contexts where I can---it's slow, its project model borders on filesystem hostility (and still sometimes requires a "throw up your hands and delete a bunch of dotfiles" solution to fixing breakages in it), and even after years of refactoring and improvements it will still go "out to lunch" on garbage collection and force a pause in my process that most IDEs will not. Being forced to use Eclipse would be a hindrance for me in picking up Go (and I think a similar argument can be made for being forced to use (X|X element of IDEs) across all developers).
Everything else being equal, perhaps you are right. However by blessing one as the official editor the tools can be written to work with that rather than the lowest common denominator. This will make it more difficult for alternatives which is a cost, but I do believe the upside is worth it - unfortunately I can't prove it.
You don't see an official recommendation because it's not necessary. Pretty much anything you use is going to have comparable functionality due to the work of the go team. Which is how I know that the Go team cares about tooling.
Even so you force every new developer to look around to find whatever he wants, which makes getting started more difficult.
Lets just say that I am a fan of the IntelliJ platform. Which plugin would I install to use with Go?
I've heard this explained as "everyone at Google just points their imports at Git repo HEADs", which is valid for a self-contained organization like that, but seems very closed-minded considering they want this language to be adopted universally.
On the other hand, I think that dependency management isn't really a language specific problem, and it is silly to have different incompatible language-specific solutions for it.
E.g. I work mainly with Python, that has popular python-specific packaging tools, yet those tools cannot express dependencies of python libraries upon e.g. native libraries. The python-specific tools are convenient on a pure-python project, for multi-language projects it feels more like an anti-pattern than a solution, particularly if you end up having to use many different packaging ecosystems / tools.
I think google's approach makes more sense in the context of an organisation where some kind of uniform approach can be imposed, and particularly where there are uniform approaches to code quality / test coverage / continuous integration.
To be clear -- I have never worked at google, this is my external perception.
I have worked somewhere where there are simultaneous software projects with wildly varying levels of code quality / test coverage / continuous integration, this does not seem to agree with very well with the source-control-based "import from HEAD" in one big repository. The organisation is currently transitioning from this approach to more decentralised many-repository approach linked with language specific package management. I do not think this change is a clear improvement, but it does make some things easier.
I'd say you got this exactly backwards. The language is mediocre, but the tooling and ecosystem are great.
The `go` command in particular is something I really want in other languages: no messing around with build files or monsters like `cabal`.
This is probably the only decision I disagree with the Go team to date.
For example for generating a c/c++ enum:
Or alternatively to stuff it in a comment: If anyones interested, heres the python script I use to preprocess the c/c++ files https://github.com/hartcw/cppyThey should have copied Java's annotation model which makes a lot more sense.
These problems are exactly why this is unacceptable in Go. Go has the benefit of learning from C++'s mistakes and seeing other attempts at solutions to the problem. Language designers have made these mistakes before, realized they were mistakes, and come up with better alternatives. This is just another example of the Go team either being unaware of or ignoring decades of development in programming languages.
Something like PY_CODE(<blah>), for instance. That way it won't compile unless you run it through the preprocessor.
A macro processor could be one of those tools in the chain. There could be other (and Go implements other use cases!)
I would also argue that a macro preprocessor do'snt need to "parse comments", it could parse any syntax the preprocessor wants to (and remove it from source befor the compiler sees it) In fact my point is, that parsing comments at all is a very bad idea.
But my argument is NOT about, if Go needs a macro processor, or not. (i think it dont!) My argument is about the syntax of the directive.
I argue about the syntax of declaring "Here comes something that is not Go Language!" I argue that this syntax should not be a comment - because a comment is part of the Go Language. (...among other reasons i stated in this discussion)
I have to agree that adding features into comments instead of new language blocks or frameworks is smelly.
File mode lines described language, the syntax (which Lisp dialect), the Package, the numeric base, the encoding, ...
Example:
But to implement compiler directives in Common Lisp, this is not needed. That can already be done with macros and reader macros. If you for example use a macro in source code, the compiler will need to expand it. That allows arbitrary code execution during compilation.Look at all the work done on JavaScript to generate code from macros and how incompatible the libraries became (JSX, sweet.js, TypeScript and so on). If there's no standardization, I'm afraid, go may have the same destiny.
If anyone on the Go core team is reading this, I'd like you to consider adding proper macros to the language.
In order to detect most of that you'll have to redefine the comment syntax for the core language so it's no longer free-form but anything that looks like a comment-directive now triggers a warning (or most likely an error seeing the Go philosophy).
IF has a meaning - and it always have this meaning. FUNC has a meaning - always the same. // are comments. The meaning of comments is to communicate with humans.
We know the principal of "overloading" syntax. Things can have a different meaning in a different context. One could argue using //go: is overloading the comment. BUT: Go is not a language that do's overloading - in fact its philosophy is against overloading, as it is against generics. (and I realy like this philosophy!)
I argue that directives to the tool chain should not apear in a comment - because a directive to the tool chain has a different & incompatible meaning than a comment.
I argue future: There is a need for directives to the tool chain in the Go source code. The go-team has this need, and there can be great things done with such e mechanism. The go community will do great things with directives! I see tons of use cases for godep. I see tons of use cases for debuggers, profilers and all kinds of other tools.
The go-team not only implements go, they also set an example to the usage of the language. If they misuse comments to express directives, other projects will eventualy follow.
But what will happens in the long run if we embrace that example and use //foo: bar as directives for our tool chains?
The go tool chain could not generate meaningfull errors about missing tools, or syntax errors in directives. Also: Comments would not be safe to communicate with fellow programmers - who knows that kind of tools where used in my dependencies? And what kinds of //foo: should be marked pink in my editor? All of em?
All this could be solved by using an other syntax for directives. I do not care if its # or @ or #! or whatever - as long as it is not a comment.
I also have no argument about macros, generics or whatever. I just want go to be unambiguous.
Go's backward compatible promise is hurting itself. By sticking with strict compatibility mode, ad hoc solutions for fundamental issues are added from time to time. Sooner or later, those patch works will back-fire.
For a language so young (version 1.0 in 2012), they should keep compatibility for stable release (1.x), but start adding language features in 2.x branches ASAP.
Yes, compatibility promise may help selling the Go language at the beginning, but Go authors may seem a little too confident/optimistic of the language spec. in this case. If a 2.x branch is not coming out soon enough (in about two year), we will probably face the same dilemma as Python 2 vs 3.
However, we can not easily fix the way people writing the code, or the so-called idiomatic Go norms.
Actually, it is compatibility in the ecosystem of Go packages that matters. We have lots of good Go packages on Github that are no longer compatible with Go 1.0/1.1/1.2 etc.
The abuse they suffer under various frameworks and ORMs is one of the ugliest things I've ever seen in a language. In almost every-case they either serve little to no purpose, or would be better-off just being part of the language syntax. But now you have to learn Java, and the Java-annotation meta-system.
At least they aren't written in XML.
note I actually don't mind the Java Community's habit of usingLongNames for things, and the actual language is pretty small and nice.
One "benefit" of this is that an older tool not updated to include the new syntax embedded in the comments will remain blissfully unaware of its ignorance, instead of spitting an error message. Another "benefit" is that a programmer unaware of the syntax might delete or copy & paste such comments when doing massive editing, without realizing that they aren't comments. To achieve the latter, it helps if the syntax looks like English or, better yet, if it looks like commented-out code (and, come to think of it, it's not unlikely that it will look like at least one of these things.)
#--utf8--
indicated the encoding of a source file. In most cases, this won't induce ambiguity, though it's potentially dangerous.
https://www.python.org/dev/peps/pep-0484/#id24
Which is pretty scary, IMHO.
Python is productive, but I always questioned some of the choices in the language design (broken lambdas, etc -- though the implementation of list comprehensions were great so I just learned to love them) -- but it seems to take some of the same decisions Go is taking in terms of inconsistencies now.
The Go stuff, however, seems much more worse.
The phrase "nothing but Perl can parse Perl" comes to mind :)
Remember that Python has supported function annotations since 3.0 [0]. Python 3.5 will only add the option to type check those same annotations.
Any type annotations that can be checked by Python 3.5 can also be parsed by earlier versions of Python, though without being checked.
The only wart in this master plan is specifically the one where you want to type annotate variables (as opposed to functions). Comments are the only way they could do this in a backwards compatible way.
The Python devs are well aware of the ugliness of this compromise, which is why they end the section you linked to with this:
> If type hinting proves useful in general, a syntax for typing variables may be provided in a future Python version.
I can't comment on Go, but I wouldn't call Python's choice here unreasonable.
[0] https://www.python.org/dev/peps/pep-3107/
blarg = [ foo(x) for x in y if x > 2]
I think is pretty decent. Helps if they are calling named functions, so it's more self documenting, depending on complexity.
Dict comprehensions can be a little brain-warping too :)
You can argue the Python version is clearer, but placement of the conditional always throws me off. I like to think of my transforms as a pipeline.
1: http://en.wikipedia.org/wiki/Schwartzian_transform