Bootstraping languages

Long time I don't write here.

And, as a matter to learn other languages I'm going to share here some notes while in this path, giving the appropriate (or not) comments for each the steps taken in the journey.

As a good start let's grab two modern interesting languages,

The summary bellow came from wikipedia an works as a good introduction about both:

Summary

Golang

A statically typed, compiled programming language designed at Google by Robert Griesemer, Rob Pike, and Ken Thompson. Go is syntactically similar to C, but with memory safety, garbage collection, structural typing, and CSP-style concurrency. The language has 9 years. Filename extensions are .go.

Rust

Rust is a multi-paradigm system programming language focused on safety, especially safe concurrency. Rust is syntactically similar to C++, but is designed to provide better memory safety while maintaining high performance. Created at Mozilla Research, and has 8 years ago, the extension file is .rs and .lib.

Installing

Golang

For MacOS X you can install directly by Darwin or fetch the archive and uncompress it:

$ tar -C /usr/local/ -xzf go$VERSION.$OS-$ARCH.tar.gz

You can access the binaries at /usr/local/go/bin, add the PATH and check the installation running:

$ export PATH=${PATH}:/usr/local/go/bin
$ go version
go version go1.12.4 darwin/amd64

Rust

For MacOS X, just type this on shell.

$ curl https://sh.rustup.rs -sSf | sh
info: syncing channel updates for 'stable-x86_64-apple-darwin'
Looks like 
info: installing component 'rustc'
info: installing component 'rust-std'
info: installing component 'cargo'
info: installing component 'rust-docs'
info: default toolchain set to 'stable'

Source the binaries PATH and test the version:

$ source $HOME/.cargo/env
$ rustc --version
rustc 1.35.0 (3c235d560 2019-05-20)

Initial running

Golang

Github can be used to host and fetch projects/packages directly so the folder you are going to store your project can be $GOPATH/src/github.com/knabben/project

Create a file called main.go with the following content on your projects home:

package main
import fmt
func main() {
     fmt.Println("Hello, World!")
}

Now run:

$ go run main.go
Hello, world!

# Formatting the source code in go can be made with:
$ go fmt main.go

The first line package main, informs this is the main package and is the entry point of your project. The second line import dependencies, built-in or external.

Third line starts a function with the keyword func followed by main without arguments, inside the function we use fmt.Println() to print out the string passed as argument.

Rust

Create a project $HOME/project

fn main() {
    println!("Hello, world!");
}

Now run:

$ rustc main.rs
$ ./main
Hello, world!

# The same formatting can be made with:
$ rustup component add rustfmt --toolchain stable-x86_64-apple-darwin
$ rustfmt main.rs

The fn main defines the main function being used as entrypoint and the second line prints out the string passed as arguments.

Building

The size difference between both binaries are significant. Both are ahead-of-time compiled languages.

Golang

To build a binary (for the OS and ARCH you are on) just type:

$ go build main.go
$ ls -lah main
-rwxr-xr-x  1 knabben staff   2.0M May 27 15:55 main

It's possible to cross-compile by default on Golang, you can use the following:

$ GOOS=linux GOARCH=amd64 go build main.go
$ file main
main: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped

Rust

Rust comes with cargo, it is a build system and package manager. Lets move our project to cargo (and start to use it) before building for another architecture.

$ rustc main.rs
$ ls -lah main
rwxr-xr-x  1 amimknabben  staff   275K May 27 17:41 main

# Using cargo
$ cargo new project
$  project tree project
project
├── Cargo.toml
└── src
    └── main.rs

You need to make some hacks and bring an external linker I would say docker can be a good alternative solutions for cross-compilation in Rust (MacOS -> n), you can read more about here.

Packaging

Golang

Go lang comes with the "go get" interface, since the version 1.11, Golang comes with a new dependency management system, that makes dependency version information explicit and easier to manage. A module is a collection of Go packages stored in a file tree with a go.mod file at its root. The go.mod file defined the module's module path, which is also the import path used for the root directory.

Make the current directory the root of a module by using:

go mod init github.com/knabben/proj

# A new go.mod file is created, you can run your program and see the dependencies being automatically downloaded:
$ go run main.go
go: finding rsc.io/quote v1.5.2
go: downloading rsc.io/quote v1.5.2
go: extracting rsc.io/quote v1.5.2
go: finding rsc.io/sampler v1.3.0
go: finding golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
go: downloading rsc.io/sampler v1.3.0
go: extracting rsc.io/sampler v1.3.0
go: downloading golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
go: extracting golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c

# cat go.sum go.mod

golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZOaTkIIMiVjBQcw93ERBE4m30iBm00nkL0i8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
rsc.io/quote v1.5.2 h1:w5fcysjrx7yqtD/aO+QwRjYZOKnaM9Uh2b40tElTs3Y=
rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

module github.com/knabben/proj

go 1.12

require rsc.io/quote v1.5.2 // indirect

As you can see we are holding dependencies versioned through SemVer on these files, lets say we want a new version v3.0.0 from the rsc.io/quote installed (actual v1.5.2). All you need to do is install the new tag

$ go get rsc.io/quote@v3.1.0
go: finding rsc.io/quote v3.1.0
go: downloading rsc.io/quote v0.0.0-20190312145912-0406d7298882
go: extracting rsc.io/quote v0.0.0-20190312145912-0406d7298882

# Clean up the not used deps and run again
$ go run main.go
go: finding rsc.io/quote/v3 v3.1.0
go: downloading rsc.io/quote/v3 v3.1.0
go: extracting rsc.io/quote/v3 v3.1.0
$ cat go.mod
module github.com/knabben/proj

go 1.12

require rsc.io/quote/v3 v3.1.0 

This is a great improvement in the past tried package management systems.

Rust

After you create a new project using cargo and check the Cargo.toml file:

$ cargo new project
project$ cat Cargo.toml
[package]
name = "project"
version = "0.1.0"
authors = ["AK <ak>"]
edition = "2019"

[dependencies]
rand = "0.3.23"

You can run your program

$ cargo build
    Updating crates.io index
  Downloaded rand v0.3.23

# Lets suppose we need the version 0.4.0, and after changing this on Cargo.toml
# it's possible to fetch the new dependency.

$ cargo update
  Updating crates.io index
  Removing rand v0.3.23
$ cargo build 
   Compiling project v0.1.0 (/Users/amimknabben/.projects/proj)
    Finished dev [unoptimized + debuginfo] target(s) in 1.97s

Conclusion

The Rust ecosystem and their toolchain is very mature now, the language is being used by cool projects like Sawtooth Blockchain. I am excited enough to bring next posts comparing the languages in a view of basics data structures and data flows, concurrency and sample projects while the research continues.