Giter Club home page Giter Club logo

trygo's Introduction

TryGo: Go with 'try' operator

This is a translator of 'TryGo' as my experiment to see what happens if Go were having try() function. Basic idea of try() came from Rust's try! macro (or ? operator). try() handles if err != nil check implicitly.

This package provides a code translator from TryGo (Go with try()) to Go.

Go:

func CreateFileInSubdir(subdir, filename string, content []byte) error {
    cwd, err := os.Getwd()
    if err != nil {
        return err
    }

    if err := os.Mkdir(filepath.Join(cwd, subdir)); err != nil {
        return err
    }

    p := filepath.Join(cwd, subdir, filename)
    f, err := os.Create(p)
    if err != nil {
        return err
    }
    defer f.Close()

    if _, err := f.Write(content); err != nil {
        return err
    }

    fmt.Println("Created:", p)
    return nil
}

TryGo:

func CreateFileInSubdir(subdir, filename string, content []byte) error {
    cwd := try(os.Getwd())

    try(os.Mkdir(filepath.Join(cwd, subdir)))

    p := filepath.Join(cwd, subdir, filename)
    f := try(os.Create(p))
    defer f.Close()

    try(f.Write(content))

    fmt.Println("Created:", p)
    return nil
}

There is only one difference between Go and TryGo. Special magic function try() is provided in TryGo.

Spec

try looks function, but actually it is a special operator. It has variadic parameters and variadic return values. In terms of Go, try looks like:

func try(ret... interface{}, err error) (... interface{})

Actually try() is a set of macros which takes one function call and expands it to a code with error check. It takes one function call as argument since Go only allows multiple values as return values of function call.

In following subsections, $zerovals is expanded to zero-values of return values of the function. For example, when try() is used in func () (int, error), $zerovals will be 0. When it is used in func () (*SomeStruct, SomeInterface, SomeStruct, error), $zerovals will be nil, nil, SomeStruct{}.

Implementation:

  • Definition statement
  • Assignment statement
  • Call statement
  • Call Expression

Definition statement

$Vars := try($CallExpr)

var $Vars = try($CallExpr)

Expanded to:

$Vars, err := $CallExpr
if err != nil {
    return $zerovals, err
}

var $Vars, err = $CallExpr
if err != nil {
    return $zerovals, err
}

Assignment statement

$Assignee = try($CallExpr)

Expanded to:

var err error
$Assignee, err = $CallExpr
if err != nil {
    return $zerovals, err
}

Assignment operation x op= y (e.g. x += y) is supported.

$Assignee op= try($CallExpr)

Expanded to:

$tmp, err := $CallExpr
if err != nil {
    return $zerovals, err
}
$Assignee op= $tmp

Call statement

try($CallExpr)

Expanded to:

if $underscores, err := $CallExpr; err != nil {
    return err
}

$underscores, is a set of _s which ignores all return values from $CallExpr. For example, when calling func() (int, error), it is expanded to _. When calling func() (A, B, error) in try(), it is expanded to _, _. When calling func() error in try(), it is expanded to an empty.

Call Expression

try() call except for toplevel in block

1 + try($CallExpr)

Expanded to:

$tmp, err := $CallExpr
if err != nil {
    return $zerovals, err
}
1 + $tmp

This should allow nest. For example,

1 + try(Foo(try($CallExpr), arg))
$tmp1, err := $CallExpr
if err != nil {
    return $zerovals, err
}
$tmp2, err := Foo($tmp1, arg)
if err != nil {
    return $zerovals, err
}
1 + $tmp2

The order of evaluation must be preserved. For example, when try() is used in a slice literal element, elements before the element must be calculated before the if err != nil check of the try().

For example,

ss := []string{"aaa", s1 + "x", try(f()), s2[:n]}

will be translated to

tmp1 := "aaa"
tmp2 := s1 + "x"
tmp3, err := f()
if err != nil {
    return $zerovals, err
}
ss := []string{tmp1, tmp2, tmp3, s2[:n]}

Ill-formed cases

  • try() cannot take other than function call. For example, try(42) is ill-formed.
  • try() is expanded to code including return. Using it outside functions is ill-formed.
  • When function called in try() invocation does not return error as last of return values, it is ill-formed.

These ill-formed code should be detected by translator and it will raise an error.

Why try() 'function'? Why not ? operator?

Following code may look even better. At least I think so.

func CreateFile(subdir, filename string, content []byte) error {
    cwd := os.Getwd()?
    os.Mkdir(filepath.Join(cwd, subdir))?
    f := os.Create(filepath.Join(cwd, subdir, filename))?
    defer f.Close()
    f.Write(content)?
    return nil
}

The reason why I adopted try() function is that ...TODO

Installation

Download an executable binary from release page (NOT YET).

To build from source:

$ go get -u github.com/rhysd/trygo/cmd/trygo

Usage

$ trygo -o {outpath} {inpaths}

{inpaths} is a list of directory paths of Go packages you want to translate. The directories are translated recursively. For example, when dir is passed and there are 2 packages dir and dir/nested, both packages will be translated.

{outpath} is a directory path where translated Go packages are put. For example, when dir is specified as {inpaths} and out is specified as {outpath}, dir/** packages are translated as out/dir/**.

License

MIT License

trygo's People

Contributors

rhysd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

pjebs

trygo's Issues

go get -u github.com/rhysd/trygo/cmd/trygo failed

$ go get -u github.com/rhysd/trygo/cmd/trygo
# github.com/rhysd/trygo/cmd/trygo
rhysd/trygo/cmd/trygo/main.go:22:2: check redeclared in this block
	previous declaration at rhysd/trygo/cmd/trygo/main.go:20:2

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.