Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.misc > #1486
| From | Ivan Shmakov <oneingray@gmail.com> |
|---|---|
| Newsgroups | comp.lang.misc, comp.lang.c, comp.lang.perl.misc |
| Subject | should we Go now? |
| Followup-To | comp.lang.misc |
| Date | 2013-02-24 10:47 +0000 |
| Organization | Aioe.org NNTP Server |
| Message-ID | <87hal29eeb.fsf@violet.siamics.net> (permalink) |
Cross-posted to 3 groups.
Followups directed to: comp.lang.misc
[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
Back to comp.lang.misc | Previous | Next — Next in thread | Find similar
should we Go now? Ivan Shmakov <oneingray@gmail.com> - 2013-02-24 10:47 +0000
Re: should we Go now? Ben Morrow <ben@morrow.me.uk> - 2013-02-24 13:40 +0000
Re: should we Go now? Rainer Weikusat <rweikusat@mssgmbh.com> - 2013-02-24 16:37 +0000
Re: should we Go now? Ivan Shmakov <oneingray@gmail.com> - 2013-02-24 17:02 +0000
Re: should we Go now? Rainer Weikusat <rweikusat@mssgmbh.com> - 2013-02-24 19:38 +0000
Re: should we Go now? Nils M Holm <news2009@t3x.org> - 2013-02-25 07:23 +0000
Re: should we Go now? Rainer Weikusat <rweikusat@mssgmbh.com> - 2013-02-25 17:30 +0000
Re: should we Go now? Ben Morrow <ben@morrow.me.uk> - 2013-02-24 21:42 +0000
Re: should we Go now? Rainer Weikusat <rweikusat@mssgmbh.com> - 2013-02-24 22:26 +0000
Re: should we Go now? Rainer Weikusat <rweikusat@mssgmbh.com> - 2013-02-25 01:04 +0000
Re: should we Go now? Ivan Shmakov <oneingray@gmail.com> - 2013-02-25 13:32 +0000
Re: should we Go now? Ben Morrow <ben@morrow.me.uk> - 2013-02-25 15:28 +0000
Re: should we Go now? Rainer Weikusat <rweikusat@mssgmbh.com> - 2013-02-25 17:54 +0000
Re: should we Go now? "BartC" <bc@freeuk.com> - 2013-02-25 01:29 +0000
Re: should we Go now? Ivan Shmakov <oneingray@gmail.com> - 2013-02-25 13:12 +0000
Re: should we Go now? Ivan Shmakov <oneingray@gmail.com> - 2013-02-24 17:04 +0000
Re: should we Go now? Bjoern Hoehrmann <bjoern@hoehrmann.de> - 2013-02-24 18:24 +0100
Re: should we Go now? Keith Thompson <kst-u@mib.org> - 2013-02-25 17:01 -0800
csiph-web