2015年8月8日土曜日

[Golang] Two modest propositions for the next Go

Written with StackEdit.
Addition: Receiving several replies, I understood that the following memorandum has several problems and the ideas are not matured.  I'd just hold the contents for some time, but please ignore them.

Foreword

Release day of Go 1.5 is approaching. Apart from this, I’d just like to leave here a memorandum of what I want for the next Go (Go2?). The two small propositions are relevant to Go specification and cannot be resolved by additional packages or libraries.
I request for your comments. Ignore if you just don’t like them.

1: iferr

Introduction

Most lines in your code, including Go, are filled with error-handling. Go’s error-handling is simple, clear and concise, with straight-ahead flow of process, and much readable comparing to ‘exception-handling’ in Java. I love it.
But the volume of error-handling code is not small. The following code spends at least four lines:
variable, err := returnSomeError()
if err != nil {
    // write error handling
}
Such patterns repeat and repeat again in Go’s code. What I just want to write is one line for error-handling.
In addition, you can freely use any variable names for error-handling other than err. The usage of the variable can vary:
variable, ok := returnSomeError()
if ok == false {
    // write error handling
}
*Using ok for error handling looks weird to me. Sorry.
Thus error-handling acquires biological diversities across developers and projects.

new keyword iferr

First I imagined that ‘post positioned if’ like Ruby and Perl would be good and would resolve the issue. Then I got an idea that a new keyword iferr, just a kind of syntax-sugar of
if err == false || err != nil
would be much better for solution:
variable, err := returnSomeError()
    iferr // write error-handling here
Much simpler, more compact, less lines, more readable.
Note that the line that begins with iferr must be indented with gofmt as above, to clarify that the line is for error-handling and to comply the Go policy.

Addition

iferr can take a block {}, or can take a statement.
variable, err := returnSomeError()
    iferr {
        // write error-handling here
    }
Still simpler.
iferr cannot take else clause. Normal flow should not be indented (Indent Error Flow).
variable, err := returnSomeError()
    iferr {
        ...
    }else { // should be inhibited
        // normal flow
    }
No lines can be inserted between assigmnent to err and iferr. They should be continuous
variable, err := returnSomeError()
variable.doSomething() // cannot add lines here
    iferr ...
I’m still wondering if permitting that one comment line exceptionally inserted between them is good or not.
Also wondering if permitting block {} within one line like the following is good or not:
variable, err := returnSomeError()
    iferr {// write error-handling here}

Pros and cons of iferr

  • Makes error-handling much simpler (+)
  • Reduces lines of code (+)
  • Moderately standardizes error-handling (+)
  • No affection to any existing codes (+)
  • Optional (+)
  • You don’t need to use iferr if you don’t like it (+)
  • the local error variable err should be reserved as well as iferr (-)
  • gofmt should take care of iferr and err (-)

2: Eliminating pointer operator *

Introduction

Go’s improvement in pointer operation is much more sophisticated to C language. Eliminating dangerous pointer arithmetic is one of the greatest achievements in Go.
Once I noticed that Go still uses * and & signs to handle pointers. It might still be redundant while Go always performs pass-by-value when assigning variables with no * and & signs.

Pointer operation in current Go

I’d review current GO.
Current Go is based on the ‘pass-by-value’ principle in all the cases.
a := "hello"
b := ""
b = a // normal pass-by-value
Current Go can use pointer operator * and address operator & for ‘pass-by-reference’ if needed.
func sample(i *int) {
  *i++
  fmt.Println("inc2: i =  " + strconv.Itoa(*i))
}

num := 10
sample(&num)
You can find three * in the sample function, and one & can be found in the argument of the caller.

New “implicit pointer”

What if all the variables in Go are actually pointers, and Go automatically dereference all the variables when compiling?
var a string = "hello"// a is actually a pointer
var b string          // b is actually a pointer
b = a                 // but works as same as current Go
The declaration var a string is internally equivalent to var a *string. var b string is the same.
But the Go I imagine finally treats them as if they are normal variables, by dereferencing them when compiling. Thus the code works fine.

No changes in address pointer

No behavior changes needed in address pointer &. It just stop dereferencing the hidden pointer in the variable.

Eliminating *

Then change the first sample above as follows:
func sample(i int) {
  i++
  fmt.Println("inc2: i =  " + strconv.Itoa(i))
}

num := 10
sample(&num)
The only difference is that all * signs went away. Very simple.
Please note that you don’t need to be conscious if the argument i is a pointer or not when writing the function.
If you just change sample(&num) to sample(num), the function still works. You just focus on & and forget about *.
Instead, type-check cannot determine if the variable is a pointer or not. The final type beyond the pointer will be checked as usual. It might be that a built-in function, which determine if a variable is a pointer, is needed.

In other places

Is the "implicit pointer" works everywhere? Let me check the cases such as array or slice.
In current Go:
func add(a *[]int) {
    *a = append(*a, 2)
    log.Println(*a)   
}

func main() {
    a := []int{1, 2, 3} 
    add(&a)
    log.Println(a) // [1 2 3 4]
}
In my Go:
func add(a []int) {
    a = append(a, 2)
    log.Println(a)   
}

func main() {
    a := []int{1, 2, 3} 
    add(&a)
    log.Println(a) // [1 2 3 4]
}
It looks like it works fine (remember there's no implementation so far).

Pros and cons

The proposition 2 might be more controversial than 1, or less attractive for someone.
  • Makes the specification and Go parser simpler (+)
  • Allows your code more symmetric and transparent (+)
    • see no changes needed in the function whether using & or not
  • Makes Go more kind for beginners (+)
    • (remember how many developers once tripped over codes for pointer operations)
  • Minimum or no affection to performance in executing the build (+)
    • All pointers will be dereferenced on build, except referred by &
    • Time for compilation would not be affected by the change (I believe so)
  • Update in Go specification is required (-)
  • Implementation on Go compiler is required (-)
  • Unable to check if the variable is a pointer or not.
  • Compatibility will be lost (-)
    • but conversion is very easy: removing the pointers*
  • Might confuse experienced developers (-)
  • Might just be disliked (-)

Addition

  • Of course the sign * still can/should be used as a multiplier.
  • I think any constants and ‘channels’ should not be “implicit-pointer”ed.
  • What else?

Quiz

  • Doesn’t the “implicit pointer” cause any issues when applying to interfaces/types/structs?
  • Could the inability of “checking if the variable is a pointer or not” be an issue?
  • Are there any potential vulnerabilities in the “implicit pointer”?

Postscript

I think the ideas above can only be possible on Go because it is the Go language:
  • Error-handling in Go is simple and ‘exception handling’ has been eliminated
  • ‘Pass-by-value’ principle dominates Go
  • Issues in conventional pointer operations has been resolved in Go
Doing that in other existing languages might just be impossible or challenging.

Reference

http://blog.golang.org/error-handling-and-go

2013年5月11日土曜日

AirPlay via Ethernet disabled

Recent months AirPlay on my AppleTV has been disabled with no reason.
Until now I connected AppleTV to my home network via Ethernet cable.

Just now I found that AirPlay-Ethernet feature on AppleTV has been discontinued. To resolve the issue, I changed the network connection from Ethernet to Wi-Fi connection.
Though I don't want to make Wi-Fi bandwidth crowded, I have no other choice than Wi-Fi.
--------------
The route cause was the Wi-Fi router itself: after that the same issue appeared again. Rebooting the Wi-Fi router resolved the issue.

2013年5月7日火曜日

[Rails4] named route with helper in routes.rb

http://ruby.railstutorial.org/chapters/filling-in-the-layout?version=4.0#sec-rails_routes

In rails4, the notation of routes.rb has been changed:

Rails3:

SampleApp::Application.routes.draw do
  root to: 'static_pages#home'
  match '/help',    to: 'static_pages#help',    via: 'get'
  match '/about',   to: 'static_pages#about',   via: 'get'
  match '/contact', to: 'static_pages#contact', via: 'get'  
  .
  .
  .
end

Rails4:

SampleApp::Application.routes.draw do
  root to: 'static_pages#home'
  get 'help' => "static_pages", as: 'help'
  get 'about' => "static_pages", as: 'about'
  get 'contact' => "static_pages", as: 'contact'

Enjoy!

2013年5月3日金曜日

[ruby] rvm vs rbenv

Today I found that  i installed rvm and rbenv simultaneously. OMG.

I had to remove rbenv and rvm, then chose rvm.

2013年4月28日日曜日

[ruby] pry

Awesome.

http://labs.timedia.co.jp/2011/12/rubyist-should-use-pry.html

How happy modern ruby beginners are.

Sublime Text 2

Eeeeexcellent!

http://dev.classmethod.jp/tool/html-corder-sublime-text-2-customize/

I immediately cast off emacs. emacs shouldn't have equipped filer and shell.
The only legacy of emacs is key bindings that are common with Evernote and are my hands remember.

2013年4月18日木曜日

Ruby on Rails on Mac OS X

http://mj-wave.com/post-731/

Homebrew is excellent. But unable to install Rails 4.0.0-beta1. It seems that the permission of rdoc directory is inappropreate. Knowing it is rough and rude, performed chmod -R 777 * and cleared.