Path: csiph.com!usenet.pasdenom.info!aioe.org!.POSTED!not-for-mail From: Ivan Shmakov Newsgroups: comp.lang.misc,comp.lang.c,comp.lang.perl.misc Subject: should we Go now? Followup-To: comp.lang.misc Date: Sun, 24 Feb 2013 10:47:56 +0000 Organization: Aioe.org NNTP Server Lines: 223 Message-ID: <87hal29eeb.fsf@violet.siamics.net> NNTP-Posting-Host: 41vvMPMLxfEjizuK6lSUHw.user.speranza.aioe.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Complaints-To: abuse@aioe.org User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.4 (gnu/linux) X-Notice: Filtered by postfilter v. 0.8.2 Cancel-Lock: sha1:OonvUCo+p/SqNsCeTqKRg4TeQwU= Xref: csiph.com comp.lang.misc:1486 comp.lang.c:31468 comp.lang.perl.misc:7567 [Cross-posting also to news:comp.lang.perl.misc and news:comp.lang.c, as Go seem to be positioned as a successor to both the "system programming languages" (C) and the "Web programming languages," of which Perl is one I'm familiar with. Setting Followup-To: news:comp.lang.misc only, though.] Introduction Becoming interested in this relatively new "Go" programming language [1] (now that I've found that its libraries' collection may even outshine CPAN, depending on the task at hand; I'm yet to check the quality of the code, though), I've decided to check its FAQ [2], and some of the related documents. There, I've found a few design choices described which I'd like to comment on. Certainly, there may be some misunderstanding on my part, hopefully to be resolved in the discussion. TIA. [1] https://en.wikipedia.org/wiki/Go_(programming_language) [2] http://golang.org/doc/faq An unusual control flow feature For me, one of the most notable features of Go seems to be its "defer" statement. To quote [3]: > A defer statement pushes a function call onto a list. The list of > saved calls is executed after the surrounding function returns. > Defer is commonly used to simplify functions that perform various > clean-up actions. And the code example follows: > func CopyFile(dstName, srcName string) (written int64, err error) { > src, err := os.Open(srcName) > if err != nil { > return > } > defer src.Close() > dst, err := os.Create(dstName) > if err != nil { > return > } > defer dst.Close() Certainly, this feature could simplify such clean-ups in the code; the only other way for such simplification I know of is to introduce additional functions all along the way. Somehow, "defer" looks quite Perl-ish to me! (Such nice control features are characteristic of the Scheme programming language, too, but there "defer" would be too "imperative" to implement.) I wonder if there's a clever way to bring "defer" to, say, Perl? [3] http://golang.org/doc/articles/defer_panic_recover.html Exceptions and assertions The stance of the language designers on exceptions does (for the most part) match my experience with them: which is little. To quote the FAQ [2]: > Why does Go not have exceptions? > We believe that coupling exceptions to a control structure, as in the > try-catch-finally idiom, results in convoluted code. It also tends > to encourage programmers to label too many ordinary errors, such as > failing to open a file, as exceptional. And then [3]: > The convention in the Go libraries is that even when a package uses > panic internally, its external API still presents explicit error > return values. Also per my experience with CPAN packages, exceptions are rarely used there, with most of the code I've seen returning "undef" instead (which is known in Go as "nil", AIUI.) The assertions go next: > Why does Go not have assertions? > Go doesn't provide assertions. They are undeniably convenient, but > our experience has been that programmers use them as a crutch to > avoid thinking about proper error handling and reporting. Proper > error handling means that servers continue operation after non-fatal > errors instead of crashing. Which is contrary to my experience, which says that for a prototype (which may or may not become a "real" project later), it's far better to have an "assert ()"-, or "or die"-ridden, code, than to waste time thinking about "proper" error reporting. The latter may even be impossible at a given stage of development, "thanks" to the relative unfamiliarity of the coder with the new libraries, protocols, file formats, etc. Unfortunately, C-style assertions in Go would likely require a separate syntactic construct. Perhaps a simple panic () may fit the majority of cases, however. Expressions and statements Being familiar with the languages of the Lisp family (mostly Scheme and Emacs Lisp), I don't believe in the necessity of firm separation of the "statement" and "expression" contexts. C and Perl are rather close to Lisp in this respect, given that, for instance, the assignment operator forms an "expression" in both (while in other languages it may be a "statement" instead.) At least one modern C implementation (GCC) goes a bit further and allows statements almost anywhere in expressions. Also, both C and Perl provide three conditional operators for use within expressions: binary &&, ||, and the ternary ? :. (Perl provides a few more, but it isn't all that relevant here.) Unfortunately, Go seem to take a step back there. Consider [2]: > Does Go have the ?: operator? > There is no ternary form in Go. You may use the following to achieve > the same result: > if expr { > n = trueVal > } else { > n = falseVal > } In my opinion, this latter form is more error-prone, just as the "a = a + b" form is more error-prone than "a += b", -- thanks to the duplication of the identifier. Also, with several choices being handled, this can easily expand the code quite a bit. Consider, e. g.: a = (foo_p ? foo : bar_p ? bar : baz_p ? baz : qux); which has to be transformed to, say: switch { case foo_p: a = foo; case bar_p: a = bar; case baz_p: a = baz; case true: a = qux; } There's one more notable difference in having two particular operators form statements, and not expressions. > Why are ++ and -- statements and not expressions? And why postfix, > not prefix? > Without pointer arithmetic, the convenience value of pre- and postfix > increment operators drops. By removing them from the expression > hierarchy altogether, expression syntax is simplified and the messy > issues around order of evaluation of ++ and -- (consider f(i++) and > p[i] = q[++i]) are eliminated as well. The simplification is > significant. I have some doubt regarding whether this decision is justified or not. For instance, even though the pointer arithmetic is gone (the inconveniece of which is partly remedied by an easier to use "slicing" feature), wouldn't it still be convenient to write, say, a[i++] = b[j++]? Go doesn't allow for that. The matters of style One more notable decision made for Go is that it allows for a newline to end a statement (unless it leads to an error), thus eliminating most of the semicolons one'd find in a similar C code, and is (AIUI) similar to the AWK approach. The price to pay for that is that there can't be a newline before the function definition's opening brace: func () foo() { // ... } ... Frankly, I don't seem to recall for a major programming language designer /not/ to advocate for a particular coding style. (And so for the major users.) The all-time low record in this respect is probably set by the Python language, which goes as far as to hardwire a particular coding style into the language syntax itself (which made Python a no-go for me.) Go seem to take a gentler approach here [2]: > Since Go code is meant to be formatted automatically by gofmt, some > style must be chosen. That style may differ from what you've used in > C or Java, but Go is a new language and gofmt's style is as good as > any other. More important -- much more important -- the advantages of a > single, programmatically mandated format for all Go programs greatly > outweigh any perceived disadvantages of the particular style. Instantly, I began to think if there could be a person brave enough to fork gofmt (or write a similar tool anew) to provide for a set of parameters to adjust comparable to that of GNU Indent [4]! A particular point is that there's an old typographic convention of spacing the parenthesis from the outside (as in "a (b) c"), which Go seem to forgo at times, and which I'd like to get back. [4] http://www.gnu.org/software/indent/manual/ -- FSF associate member #7257 np. The Clairvoyant -- Iron Maiden