FAQ
Thank you everyone for the interesting replies to this thread. I come away
with a few thoughts:

t1. A new syntax doesn't promote unhelpful error messages. Go already
permits a worse alternative:

db, _ := sql.Open(driver, connectionString)

A new syntax _discourages_ the worse alternative, because it makes a
better alternative easier.

t2. The ^ proposal provides something more functional than a shorthand for
`if nil!=err { return err }`. An example:

func RequestHandler(w http.ResponseWriter, r *http.Request) {

errHandler := func(err error) {
log.Println(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
}

db, ^errHandler := sql.Open( ... )
rows, ^errHandler := db.Query("select name from ...")
for rows.Next() {
var name string
^errHandler = rows.Scan(&name)
...
}
temp, ^errHandler := templates.ParseFiles("test.html")
^errHandler := temp.Execute(w, ...)
}

This is a situation where the value of the ^ proposal shines.

t3. The ^ syntax is (slightly smart) syntactic sugar. It's not introducing
any new or radical ideas to the language, and no changes are required to
the runtime.
It is slightly smarter than syntactic sugar:

x, ^h := f()

Needs to 'expand' to:

// iff _h_param not previously defined for ^h, where _h_param is
scope-unique,
// and HP is the parameter type of h
var _h_param HP
x, _h_param = f()
if nil!=_h_param {
h(_h_param)
}

On the other hand:

x, ^h = f()

Needs to include `var _h_param HP` only if _h_param hasn't yet been
defined for ^h. Of course, in a naive implementation one could simply
always define a unique new HP var for each ^ call.

It needs to be slightly 'context aware' syntactic sugar.

t4. There is a suggestion to use `panic` instead of `return err`. I don't
like this because:

t4.1 Library functions seldom panic, so I can only use such an approach
in my own code, for which I again need `if nil!=err { panic(err) }`

t4.2 This is exceptions by workaround. I defer to the opinion of the Go
designers, and the 'deal with the error at the point of error' approach.
Using `panic()` subverts that ethos.

t5. The tryCatch(func, func) approach (http://play.golang.org/p/plIr3nkYsE)
provides a short hand but doesn't permit returning values from functions. I
can't write:

db := tryCatch(sql.Open(...), func())

The solution is very limited (unless I've misunderstood it).

I also think it suffers from separating the point where the error
occurs and the point where it is handled (in the 'catch' function).

t6. Any solution should be idiomatic. In particular, it should support := .
This is my big 'issue' with a tryCatch() function, and an issue I have as
well with if ... {} format.

One might like to write:

if db, err := sql.Open(..); nil!=err { ... }

That doesn't work, since the scope of db is inside the if clause.

Idiomatic must be:

db, err := sql.Open(...)
if nil!=err { ... }

On the other hand, the ^ syntax becomes, very naturally:

db, ^errFn := sql.Open(...)

t7. Dr Volker points out this has been discussed in endless threads.

It is an itch that needs scratching.

====

In conclusion, consider this code from
http://golang.org/src/pkg/net/http/request.go, starting line 338:

338 // Process Body,ContentLength,Close,Trailer
339 tw, err := newTransferWriter(req)
340 if err != nil {
341 return err
342 }
343 err = tw.WriteHeader(bw)
344 if err != nil {
345 return err
346 }
347
348 // TODO: split long values? (If so, should share code with
Conn.Write)
349 err = req.Header.WriteSubset(bw, reqWriteExcludeHeader)
350 if err != nil {
351 return err
352 }
353
354 if extraHeaders != nil {
355 err = extraHeaders.Write(bw)
356 if err != nil {
357 return err
358 }
359 }
360
361 io.WriteString(bw, "\r\n")
362
363 // Write body and trailer
364 err = tw.WriteBody(bw)
365 if err != nil {
366 return err
367 }

Rewritten with ^:

338 errF := func(e error) error { // ^ only called if param != nil
339 return e
340 }
341
342 // Process Body,ContentLength,Close,Trailer
343 tw, ^errF := newTransferWriter(req)
344 ^errF = tw.WriteHeader(bw)
345
346 // TODO: split long values? (If so, should share code with
Conn.Write)
347 ^errF = req.Header.WriteSubset(bw, reqWriteExcludeHeader)
348
349 if extraHeaders != nil {
350 ^errF = extraHeaders.Write(bw)
351 }
352
353 _, ^errF = io.WriteString(bw, "\r\n")
354
355 // Write body and trailer
356 ^errF = tw.WriteBody(bw)

I'm catching one error more than the original code (io.WriteString on
361 in original code, 355 in ^ code), and have reduced 30 lines to 19 (ok,
I cherry-picked the example, but I cherry-picked it from the Go source).

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Search Discussions

Discussion Posts

Previous

Follow ups

Related Discussions

Discussion Navigation
viewthread | post
posts ‹ prev | 8 of 19 | next ›
Discussion Overview
groupgolang-nuts @
categoriesgo
postedApr 5, '13 at 7:31a
activeApr 12, '13 at 6:37a
posts19
users11
websitegolang.org

People

Translate

site design / logo © 2021 Grokbase