I think one of the reasons for developing Go were some hard-to-find bugs with the indentation of python code. AFAIR, the Go authors specifically didn't want this.
"As a simple, self-contained example, consider the representation of program structure. Some observers objected to Go's C-like block structure with braces, preferring the use of spaces for indentation, in the style of Python or Haskell. However, we have had extensive experience tracking down build and test failures caused by cross-language builds where a Python snippet embedded in another language, for instance through a SWIG invocation, is subtly and invisibly broken by a change in the indentation of the surrounding code. Our position is therefore that, although spaces for indentation is nice for small programs, it doesn't scale well, and the bigger and more heterogeneous the code base, the more trouble it can cause. It is better to forgo convenience for safety and dependability, so Go has brace-bounded blocks. "
No. Go is beautifully straightforward and blatantly obvious as to what is going on. Don't start hiding scopes behind tabs or magically creating variables referencing structs.
Plus, with all these changes, this syntax saved 5 lines of code, most of which were simply closing braces, and brought no greater clarity. In fact, I'd argue it's probably pretty easy to mess up scope in the iGo example and never know it.
Go is beautifully straightforward and blatantly obvious as to what is going on.
I agree.
I've argued similarly on the Lua mailing list when someone wanted to change the comment characters used in the source code to be C-style instead of Lua style (double minus).
If you're going to change the language, really change it, and give enough benefit to make a break with existing code. If you are going to tweak something like comments (or in this case use significant whitespace), there isn't enough benefit (other than programmer preference) to justify the switch.
If nearly every gopher thought thought this was great and switched their code, then that's OK. But if you start using iGo, you're still going to be spending most of your time looking at regular Go source. So you need to learn the rules for Go and iGo, for negligible long term benefit.
One of the best parts of Go is that the grammar is (almost) entirely context-free - it is one of only two languages I know of in this regard - Lisp is the other[0].
This comes in handy because it is very easy to parse Go and make syntactic transformations while preserving semantic meaning. The "go fix" tool (which was used to port pre-1.0 code to Go 1.0) meant that Go never had a "py3k" moment[1]. This is not like python's "2to3" tool, which is reasonably good, but still doesn't handle every edge case.
My favorite part about writing Go is the "go fmt" tool. Because all code in the standard lib (and most third-party code by convention) is formatted using the exact same tool, it is very easy to read any Go source code I find online. I don't need to worry about stylistic differences or bikeshedding. And the "go fmt" tool exists (and is so simple to implement) in part because Go's grammar is so simple.
Go is emphatically not a Lisp (it's not even a functional language[2]). However, this one trait - the ability to make deterministic and reliable syntactic transformations - are at the core of what make Lisp's macro's powerful[3].
Like Lisp, Go's beauty lies not in the syntax but in the semantics. While I would appreciate a Go (or a Lisp) that had both more beautiful syntax and beautiful semantics, I would not want to compromise one bit on the latter.
[0] (EDIT) For the PLT nerds & pedants among us, I think mehrdada is right - in actuality, the grammar (IIRC) is fully context free, but in other languages, many of the rules which define a valid program cannot be encapsulated by the language grammar (whereas a higher proportion can). So it's less that the grammar is "(almost) entirely context-free" and more that the language is "(almost) entirely described by its grammar". That said, it has zero impact on the rest of my comment. :)
[1] Or, in the case of Python, not so much a "moment" as 5+ years and counting.
[2] It supports first-class functions, but that's about it.
[3] It does not mean that Go has macros, or even that Go can provide the same things that Lisp macros provide. It simply means that Go derives some of its power from the same place that Lisp macros derive their power.
It'd certainly be possible to have a tool -- let's say "go edit" -- which would read a set of user preferences, and apply transformations (e.g. setting spaces or tabs, variables-in-camel-case, comment-styles , etc.) to Go code. It'd be fine as long as each transformation was bijective in a way "go fmt" could revert.
Interestingly, the code existing between the "go edit" and "go fmt" steps wouldn't necessarily need to be executable as plain Go. If the Go compiler's parser+lexer shared their canonicalization logic with "go fmt", then feeding "go edit"-munged Go to the compiler would implicitly re-canonicalize it before compiling it. So you could have transformations involving things like significant whitespace.
In fact, the pair of filters "go edit" and "go fmt" could even be made into a read/write filter-pair for a FUSE filesystem: in effect, the code on-disk would always be represented in the canonical "go fmt"ed manner, while the code you'd see in your editor would always be in your own personal "go edit" style.
And then, 56 years after McCarthy's LISP, we'd finally have our M-expressions. ;)
(And the serialized representation could finally be stored as a binary AST tree, and we could embrace visual-symbolic hybrid languages, and entertain divergent syntaxes with unified AST-level semantics, and have one universal runtime library, and...)
> Almost all programming language grammars are context-free.
Er no, almost no programming language grammar is actually context-free (in the sense that they can be parsed unambiguously according to a context-free grammar)
Unambiguous parsing is not a requirement for a language to be context-free. Your use of "actually context-free" is a stretch of the definition by a huge margin. In fact, the definition of a context-free language does not depend on a specific grammar at all. You can have a context-free grammar that parses a language unambiguously and another grammar that ambiguously defines the same language.
It is true, however, that most formal grammars for programming languages define a strict superset of the actual language and then restrict it according to semantic rules (e.g. type checking, definite assignment rules). That is why in my original comment, I was careful to use the phrase "programming language grammars", instead of "programming languages".
Pretty sure he means 'almost' context free (as opposed to 'very' context sensitive. C is context sensitive. A language like C++ is heavily context sensitive (actually, C++'s templates make it recursively enumerable iirc, so even worse..)).
Being regular would mean that you could decide it with regular expressions. Regular expressions are insufficiently powerful for matched parentheses of arbitrary depth, which is a good hint that Lisp and Go are not regular (or 'near' regular).
> Being regular would mean that you could decide it with regular expressions.
Hence almost regular. Of course, there is no concrete definition for "almost regular", but what I mean by it (Rob Pike himself also characterizes it as such too[1]), is that you get to decide which way to parse a construct quite definitely early in the token stream and you don't have to read arbitrary following tokens to figure out how to construct a parse tree branch.
C++ is the exception here. Most other block oriented high level programming language (at the syntax level) are indeed fully context-free, so just being context-free does not deserve a high prize.
Do you have the timestamp of when in this talk Rob Pike mentions this? If he says that it is "almost regular", then that settles it in my book, but I am pretty certain that you are wrong about most block oriented high level languages being context free.
In that video mentions regularity around minute 51. I have seen him using that term in person too.
The blog post you mentioned is misinformed. YACC does not parse all context-free grammars. It generates LALR parsers, that parse a strict subset of context-free languages (called deterministic context free languages). Not parseable with YACC does not imply not context free.
It is important to distinguish the programming language and its syntax. In most real compilers, the parser accepts a superset of the programming language and then other components of the compiler restrict it with semantic rules like type checking. What I am talking about here is the syntax only. In that sense, things like C, Java, and C# are most definitely context-free. The language specification usually comes with a context-free grammar describing the syntax. Whether you can use it to parse programs efficiently (in O(n)) and meaningfully is another matter.
You are meaning that it is an LL(k) parser. Rust is an example of an LL(1) parser. Various things that might be convenient to have in the language in certain circumstances have been rejected because they would cause ambiguity in the parser which would require arbitrary lookahead.
What I have in mind is more loosely defined than LL(k) and in a way more restrictive than a general LL(k) grammar, but LL(k) is probably a good way to formally capture something close to what I had in mind. I try to avoid using the term "almost regular" as it is imprecise. I only used it since it was relevant to the context and I'd heard Rob Pike describe Go as having almost regular syntax several times.
> One of the best parts of Go is that the grammar is (almost) entirely context-free
If the threshold is almost-context-free there's a host of matching languages: C (IIRC it's context-free if you remove typedefs), Rust, Pascal and descendants (Oberon), Python, java, …
If the threshold is actual context-freedom, I don't recall anything outside lisps.
Go should be in an excellent position to have Refactoring Editors. Smalltalk had a Refactoring Browser that worked well enough that it changed the economics/trade offs around refactoring. (Literally an order of magnitude easier refactoring combined with immediate/really fast responsiveness.)
Such tools, positioned such that they are defacto standards can cause qualitative changes in how programming happens in a language.
The isomorphism between the sources could be tweaked. For instance, around line 26 on the iGo side, there's a newline that doesn't appear on the other side, and the closing brace is right next to func main. On line 48 in iGo, note the comment ends up after the braces of something that should have already been closed out. In general, braces seem to end up with an extra line on the end too often.
I do not like the do syntax; for a very dubious improvement in syntax, you turn an N-parameter function into an N-1 parameter function visually. This is a net loss. (Go is not curried.) It's not even a huge character win, given that you've already disposed of the braces. I'm not convinced those stack very composably either, though I'll admit I'm not taking the time to prove that.
In fact, in general be wary of that issue in syntax, real code will encounter all the corner cases that can possibly exist as the elements are composed together. Can I call a
with your do syntax being used twice? If not, or if it's not easy, that's a bad sign. Vanilla Go I can type that correctly the first time... it may be a lot of braces but it's unambiguous. It may be wise to avoid trying to sugar function applications like that, if you can possibly avoid it.
I can write code in iGo and save it as .go. You'll never know if the code was written using Go syntax or iGo syntax, whether the person used tabs of width 4, 8, or 2 (it'll be a '\t' character in the file), or if they used Sublime Text or vim or emacs.
Oh really? So the igo code won't be checked into your repo? The comments you've made will be preserved and in the right place in the resulting code? And you'll be writing go code that other go programmers will find idiomatic and easy to read?
Also, if you use igo won't you have to adjust to read other peoples non-igo code? Or will you use a converter tool whenever you read any go code?
Yes, that's the idea. The current implementation may not be finished/perfect.
> Also, if you use igo won't you have to adjust to read other peoples non-igo code? Or will you use a converter tool whenever you read any go code?
"Converter tool" makes it sound like you find it unreasonable. Do people use "converter tools" to view .html files in a rendered format? No, they use a browser. Or to display '\t' characters with different widths? Use a text editor: http://img534.imageshack.us/img534/1627/zo3w.png
If you're gonna write Go code using iGo syntax, you're probably going to be using a code editor that supports iGo (I don't think one exists yet, this is just a prototype).
You're not gonna be converting from .go to .igo manually, that'd be like running gofmt manually. I don't run gofmt manually, it happens on save (and in fact, I use goimports instead of gofmt).
I believe his point is that iGo is just a way of editing .go files. It's not as though you would be saving .igo files to disk or anything. So, it's totally unrelated to any kind of version control or file management, much less to Github.
No, it's not. Because if you're used to reading igo code and then you're browsing normal Go code in GitHub or watching a talk or reading a tutorial, you're going to have to mentally translate that code to igo. It's needless mental acrobatics.
Most presentations don't use pure go-fmt'd code, they usually do some vertical space compression to get the code to fit on the slides better. So technically you already have to do this anyways.
Um no. Apart from being pretty coffee-script makes you stick with good object definition conventions, hides away unsafe comparisons (== vs ===), and is generally much more easily understood. This is one of coffeescript's main focus points : hide away the not so nice features of js, and highlight the good parts.
Yeah, but the language is what it is. It's out there, it's in all the browsers, it's not going away.
Rather than just learn to idiomatically write code that uses the nice features of js while avoiding the bad parts; we have two totally different notations to learn. That only causes further fragmentation.
I am usually wary of new languages, because they come at a great cost. All the code I've written, libraries I've discovered, standard library I'm used to and take for granted are suddenly gone, and I have to start from scratch. On the plus side, the new language may have desirable aspects that are improved.
However, this is not that. Despite looking like a different language, in reality, it's just a different _interface_ to writing/reading Go. It's completely compatible with all the libraries, tools that work on Go code because it _is_ Go code, simply expressed via a different representation of the Go AST.
I think that is a really nice way to experiment with the positive aspects of new languages/syntaxes. Nicely done!
It might be interesting to hook up different AST representations directly into an editor, in this case iGo would never exist on disk. Really all he has done is push what would be an editor completion into a new sytnax.
I really respect the way this was posted. A simple side by side. Most of the times stuff like this is posted, it is a horrifically convoluted example to try to show the massive code savings, this one is just -- honest. You save a few lines of code.
That all said, the syntax is godawful. It brings back so many horrors from Python, whitespace, self, ugh. The next step to make it truly awful would be have those minor whitespace errors only show themselves at runtime so writing complex applications becomes a nightmare.
Why is significant-whitespace vs. braces a significant issue for people? I've coded in both and while I suppose I would have to say that I'm "most" comfortable with braces, I don't find SW that different.
The semantics of the code haven't changed at all. It's not like we're going from C to O'Caml here. This doesn't enable a different way of thinking about the code.
I guess I just feel that, if I could run a set of very simple regexes over Code A to get Code B, then I haven't really gained anything [1]. Maybe that's a sign of the times. Maybe we live in an era in which the various programming languages have evolved to share so many features that a trivial translation exists for the majority of scenarios.
Perhaps I'm over-thinking it. Maybe OP was proud of his/her presentation. It's pretty neat, how the two halves of the screen are presented.
[1] an opinion born from having spent time running simple regexes over Code A to get Code B and realizing I hadn't really gotten anything out of it.
Personally, it's not a significant issue, but it is a preference. Do you indent code when coding with braces? How anal are you about keeping your code formatted consistently (i.e. spaces after operators)?
Sometimes, not always. I'm likely to put a one-line getter/setter on one line.
I use formatter tools to do most of the formatting. It's nice to have formatted code, but I'm not fastidious about it. It's bound to Ctrl+K, Ctrl+D in Visual Studio. I prefix it to Ctrl+S out of habit. But if the automatic formatter can't take care of it, I don't bother changing anything. Simplicity and consistency are more important than "having my way".
Code should be readable, which is a human issue. As such, I think it's always going to have edge cases where "breaking the rules" is appropriate.
EDIT: Come to think of it, I often use the formatting as a pre-check before compiling. If the formatter doesn't format the code as I expect it to, it means I've screwed up a block somewhere. That's pretty much it for me.
I dig the syntax on receivers, and the short body declaration syntax. the whitespace—meh. I'm less offended than i used to be by whitespace languages like python, but i've also been bitten many times by incorrect indentation that took me a few minutes to track down. annoying, but not catastrophic, and certainly more readable.
My biggest concern in using it would be that its a tool that saves me some keystrokes (perhaps not insubstantial advantage—i'm tired enough of faking partial application in JS that I'm almost ready to start using coffeescript if only for the -> operator) but it doesn't really offer many other advantages, and will probably complicate my life at some point (i.e. i'm grumpy and suspicious of new things. shrug)
Even so, looks fun, and options are good. nice work—hope it gets some traction and evolves.
A lot of programmers seem to think that (the more code they can jam on the screen at a time the better, and thus any unnecessary newlines are superfluous), but I also don't understand why many are so rabid about it.
We generally don't code on 80x25 character terminals anymore, super high res monitors are cheap, vertical lines in code aren't a scarce commodity.
Personally I tend to like a fair amount of vertical whitespace (either in pure whitespace form or comments) in my code to split things up logically, even within the same function and when the newlines aren't required, eg:
x = 10
y = 20
z = 0
speed = 80
Variables assignments/func calls, etc that are closely coupled kept together, but some whitespace as things become less directly linked. I'd rather be able to quickly scan code in 10-40 line chunks than fit more code on the screen at once.
Many things are valuable. Conciseness per se is valuable (I don't think you will argue in favor of unnecessary verbosity in programming). However, of course this is just one of many factors, and any programming language will have to find a balance between these many factors, depending on how important each is, and so on.
If you think you are getting conciseness by decreasing readability then you probably have a balancing issue, but if you can get more concise code without decreasing readability then that's good news.
So what's the intended workflow here? You write your code in IGo syntax. Now, you can't compile that code until it's been converted to real Go.
And you need to commit the Go source, not just the IGo source, because other people don't want to see your Python-esque Go.
And once you compile your code, now any error messages are going to have the wrong line number associated with them if you look at the IGo source. So when it comes time to debug, I guess you have to switch to reading the auto-generated Go and making changes in your IGo from there.
This seems like an awful lot of hassle in order to achieve what is arguably the worst part of Python syntax: significant whitespace.
I'd like to explain one thing, right now the `go build` etc... isn't implemented.
There is a good reason for that.
You may not want to distribute `igo` files, this `syntax` should work in the very same way of `go fmt`.
The idea is allowing you to write as you like (for me indenting) then distribute your files as you always did with `go fmt`, so the `code` will be always `.go` files formatted in the standard way, with comments as well.
The experiment's upvote-worthy and I applaud the effort, but there's no chance I'll ever use this personally. In practice, I don't think I've ever been annoyed by the syntax of Go. Perhaps the one iffy behaviour has been the way multi-valued := wriggles around mixed declaration/assignment dependant on what's already in scope.
I'd agree. I think the biggest thing for me is that I had to think about what was being expressed on the left hand side while the right hand side seems more explicit and straight forward. Provided that and the fact that only a handful of lines were actually saved, I don't see much advantage.
I can't say that I find it less readable... but it is only marginally better for me. I'd rather just use a decent editor which takes care of the braces for me.
Maybe it is because I've been programming in for something like 24 years, but I don't find them annoying to type at all; Also, maybe I'm just slow, but my typing speed is hardly the bottleneck for me in writing code; I doubt it would be even if I typed at like 20 wpm (about 95 wpm for me, and I don't touchtype). And then lastly, you can always remap your keyboard to make {} non-shift characters and/or use a language parsing IDE/editor that auto-inserts braces.
The common user don't really uses them, therefore they aren't even mapped in eu keyboards. Clearly the solution is to change the mapping, but as you can imagine, many people still need to look at the keyboard when typing... So how do you fix that?
I can teach my wife to code python, but if she has to type alt-gr 123 for every curly brace in JS, she will be tired quite soon.
I would agree if not having to type curly characters is a major benefit of IGo syntax. As a CoffeeScript user, primary benefit of IGo I see is in readability, not saving keystrokes which I think TextMate/Sublime Text macros are better at.
They almost went to python but then added weird inconsistencies with how colon works. Why is it omitted in the else clause? Why isn't it used in all blocks like with python?
Nimrod solved that... The solution in a nutshell: If a statement list contains a 'return', it enforces a 'void' context for the statement list, otherwise the statement list has the type of the tailing expression e in (s; s; e).
the cost in making the code harder to parse (both for compilers and, IMO, humans) isn't worth it. Using short assignment mixed with if makes the Go error handling branch code not so bad, eg instead of:
err = doSomething
if err != nil {
return err
}
do:
if err = doSomething(); err != nil {
return err
}
Also if your function only returns err, I'd use a named return to save even more typing. I know they are seen as a bit of a red-headed stepchild by much of the Go community these days, but I still like them if used carefully:
In this case, buf will not be available outside of the if statement. Go fmt can already leave your insignificant whitespace as is, I just wish it could also leave the if error != nil statement say in one line instead of formatting it to take three.
As an F# and Go developer, I reckon you should say, "IGo syntax looks very familiar to [any language which uses significant whitespace]". However, I'd still disagree with that statement.
Agreed. I spent a lot of time worrying about syntax in my first year or two of programming. Then, I gradually opened my mind and discovered a whole world of amazing languages with syntax I had found distasteful and previously avoided.
It's an opinion, so just stating "useless" and moving on doesn't actually help in any way. Describing why he thinks it's useless, or upvoting comments that he agrees with, might actually help.
Found it: (http://talks.golang.org/2012/splash.article)
"As a simple, self-contained example, consider the representation of program structure. Some observers objected to Go's C-like block structure with braces, preferring the use of spaces for indentation, in the style of Python or Haskell. However, we have had extensive experience tracking down build and test failures caused by cross-language builds where a Python snippet embedded in another language, for instance through a SWIG invocation, is subtly and invisibly broken by a change in the indentation of the surrounding code. Our position is therefore that, although spaces for indentation is nice for small programs, it doesn't scale well, and the bigger and more heterogeneous the code base, the more trouble it can cause. It is better to forgo convenience for safety and dependability, so Go has brace-bounded blocks. "