Language Comparision


Language Comparision
# Compiled Concurrent Language
https://en.wikipedia.org/wiki/List_of_programming_languages_by_type
*Not fully listed for all languages.*
 

|NAME       |CONCURRENT|GARBAGE|OBJ|MULTIPARADIGM|
|-----------|-|---------|-|-|
|Ada        |v|manual   |v|v|
|C++        | |         |v|v|
|C#         |v|auto     |v|v|
|Cilk       |v|         | | |
|Crystal    |v|auto     |v|v|
|D          |v|auto     |v|v|
|Eiffel     |v|         |v|v|
|Erlang     |v|auto     | | |
|Fortran    |v|manual   |v| |
|Go         |v|auto     |v|v|
|Java       |v|auto     |v| |
|Nim        |v|auto     |v|v|
|P          |v|         | | |
|ParaSail   |v|x. region|v| |
|Pascal     |v|manual   |v|v|
|Rust       |v|manual   |v|v|
|Scala      |v|         |v|v|
|SequenceL  |v|         | | |
|Swift      |v|x. ARC   |v|v|



------

# Indentation Coding Style
Indentation (Off-side rule) is the future of readable code. Even though it's hard to make an indentation parser using YACC. 
That's why `Python` is easy to use and widely used. It is more humanity than machinity.

```
ISWIM
ABC
Python
Cobra
Boo
Genie
Miranda
Orwell
Haskell
Curry
Elixir
F#
Nim
Occam
SPIN
XL
```



# EFFICIENCY

Pick languages which runtime is less than one magnitude (~10X) of the minimum runtime. Data from: 
https://github.com/kostya/benchmarks. 
https://kokizzu.blogspot.kr/2015/04/crystal-internal-benchmark.html. 

```python
# python
ranking = dict(
    Halvak = ['Crystal', 'Nim', 'C++', 'Scala', 'D', 'Go', 'Python', 'C#'],
    Matrix = ['Julia', 'C', 'Java', 'Nim', 'D', 'Rust', 'Crystal', 'Go', 'Javascript', 'Python', 'Scala', 'Ruby'],
    Json = ['D', 'Rust', 'C++', 'Java', 'Crystal', 'Perl', 'Javascript', 'Python', 'Nim', 'Go', 'Q', 'Clojure', 'C#', 'Php', 'Haskell', 'Ruby', 'Julia', 'JQ', 'Scala'],
    Base64 = ['C', 'D', 'Rust', 'Crystal', 'Ruby', 'Perl', 'Nim', 'Julia', 'C++', 'Javascript', 'Php', 'C#', 'Tcl', 'Go', 'Python', 'Java', 'Kotlin', 'Scala'],
    bench = ['Kotlin', 'C++', 'Rust', 'Nim', 'D', 'ML', 'Crystal', 'Scala', 'C#', 'Java', 'OCaml', 'Felix', 'Go', 'Javascript', 'F#', 'Haskell', 'LuaJIT', 'Python', 'Racket', 'Ruby'],
    mandel = ['C++', 'Crystal', 'Rust', 'D', 'Nim', 'ML', 'C#', 'Go', 'Felix', 'Kotlin', 'OCaml', 'Scala', 'Java', 'Javascript', 'Haskell', 'Python', 'Ruby', 'LuaJIT', 'F#']
)

from collections import Counter
c = Counter()
for list in ranking.values():
    new_list = [x.lower() for x in list]
    c += Counter(new_list)

for i in c.most_common():
    print('%-12s: %2d' % (i[0], i[1]))

```
Output:
```
scala       :  6
nim         :  6
go          :  6
crystal     :  6
python      :  6
d           :  6
c#          :  5
ruby        :  5
javascript  :  5
java        :  5
rust        :  5
c++         :  5
haskell     :  3
julia       :  3
kotlin      :  3
ml          :  2
php         :  2
c           :  2
f#          :  2
felix       :  2
luajit      :  2
ocaml       :  2
perl        :  2
jq          :  1
racket      :  1
tcl         :  1
clojure     :  1
q           :  1
```
Among which off-side rule langs are:
`nim, python, haskell, f#` 
Crystal looks like `off-side rule` but does not force indentation for reasons explained [here](https://github.com/crystal-lang/crystal/wiki/FAQ#why-isnt-the-language-indentation-based).

# Code Example

## python      :  6  5min
Actually it's Python run on PyPy that's competitive. Here I use Python code for simpilicity demonstration. 
[Run online](https://www.python.org/shell/)
```python
# hello world:
print('Hello world!')
```

```python
# function:
def add(a, b):
    return a + b

print(add(1, 1))
```

```python
# class:
class Man:
    def __init__(self):
        self.stomach = []
    def feed(self, food):
        self.stomach.append(food)
    def fart(self):
        print('You fart!')

bob = Man()
bob.feed('pizza')
print(bob.stomach)
bob.fart()
```

## nim         :  6  2hours
Good: 
- Nim indents.
- Nim hates tabs. Cause length of tab is viriable. Yet tabs can expand dynamically.
- Nim handles `Exception` like `Python` not `Go`.
- `for i in 1..10` includes open and end in Nim. That's more human nature and you don't need to worry about edge condition. Yet array still counts from 0.

Bad: 
- Coding style is not intuitive as Python. You should read the whole official tutorials before writing something.
- [Non-thread-safe](https://news.ycombinator.com/item?id=10950414) garbage collector. (Under development?)

[Run online](https://play.nim-lang.org/)
```nim
# hello world:
echo "Hello world!"
```

```nim
# function:
proc add(a, b: int): int =
    return a + b

echo add(1, 1)
```

```nim
# class:
# Now Nim turns annoying. Nothing is natual, you can't
# get it right unless you follow the entire tutorial.
# It took me 2 hours to write this class.
type Man = ref object of RootObj
      stomach: seq[string]

proc newMan(): Man =
    new result
    result.stomach = @[]

method fart(this: Man): bool {.base, gcsafe.} =
    echo "You fart!"
    return false

method feed(this: Man, food: string): seq[string] {.base, gcsafe.} =
    this.stomach.add(food)
    return this.stomach

var bob = newMan()
echo bob.feed("pizza")
discard bob.fart()
```

Update: After learning Nim tutorial1 and tutorial2 a whole day, I can say that I've grasp Nim. Yeah! 
Update: 
1. Nim is underdeveloped. Many things changed rapidly. Clone an repo and it won't run. 
2. Package usage is not straight forward. Installed a NimYaml and I still have to write a yaml structure and a iterator. 
3. Lack of method and doc on Socket programming. Writing a MITM socket seems impossible and time consuming. 
4. String concat: You should overload operators in order to use  `+` and `+=`.
Finished in 13mins:
```nim
echo "Hello world! 19:27-19:40"
proc add*(x, y: int): int =
    x + y
echo add(1, 1)
type
    Man* =  ref object of RootObj
        stomach*: seq[string]
method feed*(self: Man, food: string) =
    self.stomach.add(food)
method fart*(self: Man) =
    echo "You fart!"
proc newMan*(): Man =
    result = new Man
    result.stomach = @[]
var bob = newMan()
bob.feed("pizza")
echo bob.stomach
bob.fart()
```

## crystal     :  6  20mins
Genius is one who creates human language that codes like `Python` and executes like `C`. Crystal is on that list. 

It's easy to get started and take off! It make me fells better than Python. Coding in other languages (except `Python`, `Crystal`, `Ruby`, `D`) always make me angry.   
One bad thing is that Crystal [may blocking](https://github.com/crystal-lang/crystal/issues/1967) on concurrency. 
Update: It's easy to guess what to use at the beginning. As I walk through the offical tutorial, I found that the syntax is too complex for newbie. It's more like Ruby for a Pythoner. 
[Run online](https://play.crystal-lang.org/) 
```crystal
# hello world:
puts "Hello world!"
```

```crystal
# function:
def add(x, y)
    return x + y
end

puts add(1, 1)
```

```crystal
# class:
# It took me 30 min to figure out
# how to write a class in Crystal.
# Except for the installation:
# 1. Windows need to install Ubuntu;
# 2. Linux may need to key-add manually.
class Man
    def initialize()
        @stomach = [] of String
    end
    def feed(food : String) : Nil
        @stomach += [food]
        return Nil
    end
    def get_stomach()
        @stomach
    end
    def fart()
        puts "You fart!"
    end
end

bob = Man.new
bob.feed("pizza")
puts bob.get_stomach()
bob.fart()
```


## go          :  6  3hours
Go has got a point about why they declare type after variable like`x int`, explained [here](https://blog.golang.org/gos-declaration-syntax). 
[Run online](https://play.golang.org/)
```go
// hello world:
package main
import (
    "fmt"
)
func main() {
    fmt.Println("Hello world!")
}
```

```go
// function:
package main
import "fmt"

func add(x int, y int) int {
    return x + y
}

func main() {
    fmt.Println(add(1, 1))
}
```

```go
// class:
// Finished in 3 hours. Keyboard smashed.
// How the fuck can I init an variable array?
package main
import "fmt"

type Man struct {
    stomach []string
}

func NewMan() *Man {
    return &Man{}
}

func (m *Man) Feed(food string) (bool) {
    m.stomach = append(m.stomach, food)
    return true
}

func (m Man) Fart() () {
    fmt.Println("You fart!")
}

func main() {
    bob := NewMan()
    bob.Feed("pizza")
    fmt.Println(bob.stomach)
    bob.Fart()
}
```
Capacity of Slice in Go is un-predictable. Give up learning it. Example code:
```go
package main
import "fmt"
func main() {
 b := make([]int, 0, 5)
 printSlice("'b := make([]int, 0, 5)'", b)

 c := b[:2]
 printSlice("'c := b[:2]'", c)

 d := c[2:]
 printSlice("'d := c[2:]'", d)
}
func printSlice(s string, x []int) {
 fmt.Printf("%-25s:  %v len=%d cap=%d\n",
  s, x, len(x), cap(x))
}
```
Outputs:
```
'b := make([]int, 0, 5)' :  [] len=0 cap=5
'c := b[:2]'             :  [0 0] len=2 cap=5
'd := c[2:]'             :  [] len=0 cap=3
```




## java        :  5  30mins
Java may not as slow as we may think. See [benchmark](https://benchmarksgame.alioth.debian.org/u64q/java.html) (on debian.org?) 
[Run online](https://www.tutorialspoint.com/java/try_java.php)
```java
// hello world:
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello world!");
    }
}
```

```java
// function is defined in class.
// class:
import java.util.ArrayList; // use elastic length of array.

public class Man {
    public ArrayList<String> stomach; // instance variable.

    // initiator, do someting once you create a new Man.
    public Man() {
        this.stomach = new ArrayList<String>();
    }

    public void Feed(String food) {
        this.stomach.add(food);
    }
    public void Fart() {
        System.out.println("You fart!");
    }
    // public: anyone can use my function.
    // static: can use me without creating any human.
    public static void main(String[] args) {
        Man bob = new Man();

        bob.Feed("pizza");
        System.out.println(bob.stomach);

        bob.Fart();
    }
}
```
## ruby        :  5  20mins
[Run online](https://www.tutorialspoint.com/execute_ruby_online.php)
```ruby
# hello world:
puts "Hello World!";
```

```ruby
# function:
def add(a, b)
    a + b
end
puts add(1, 1)
```

```ruby
class Man

  def initialize
    @stomach = []
  end

  def stomach
    @stomach
  end

  def feed(food)
    @stomach += [food]
  end

  def fart
    puts "You fart!"
  end
end

bob = Man.new
bob.feed("pizza")
puts bob.stomach
bob.fart()
```

## d           :  6 20mins
[Run online](https://run.dlang.io/)
```d
# hello world:
import std.stdio;
void main()
{
    writeln("Hello world!");
}
```

```d
// function:
import std.stdio;
void main(string[] args)
{
    writeln(add(1, 1));
}

int add(int x, int y)
{
    return x + y;
}
```

```d
// class:
import std.stdio;
class Man
{
    protected string[] stomach;


    void feed(string food)
    {
        this.stomach ~= food;
    }
    void fart()
    {
        writeln("You fart!");
    }
}

void main()
{
    Man bob = new Man;
    bob.feed("pizza");
    writeln(bob.stomach);
    bob.fart();
}

```

## Scala       :  6
> [If you're interested in Scala, learn Haskell.](https://news.ycombinator.com/item?id=7388670)

### scala       40mins
[Run online](https://scalafiddle.io/)
```scala
// hello world:
println("Hello, world!")
```

```scala
// function:
def add(a: Int, b: Int) = a + b
println(add(1, 1))
```

```scala
// class:
// List[] or Array[] hard for inplace addition.
import scala.collection.mutable.ListBuffer

class Man() {
  var stomach = new ListBuffer[String]()
  def feed(food: String) {
    this.stomach += food
  }
  def fart() {
    println("You fart!")
  }
}

val bob = new Man()
bob.feed("pizza")
println(bob.stomach)
bob.fart()
```

### Haskell       1hour
[Run online](https://www.tutorialspoint.com/compile_haskell_online.php)
```haskell
-- hello world:
main = putStrLn "hello world"
```

```haskell
{- function:
// function call is a nightmare:
// Parse error: naked expression at top level -}
add x y =          x + y
main = print(add 1 1)
```

```haskell
{- class:
    Haskell is a functional programming language.
1 hour later and I still can't figure out how to
turn function into class.
And there's no way to append string into list.
-}

```
## rust        :  5 1hour
Open issues ranked second. No. 1 is C++ From [GitHut](http://githut.info) 
[Run online](https://play.rust-lang.org/)
```rust
// hello world:
fn main()
{
    println!("Hello, world!");
}
```

```rust
// function:
fn add(x: i32, y: i32) -> i32
{
    return x + y;
}
fn main()
{
    println!("{}", add(1, 1));
}
```

```rust
// class:
// mission impossible. gave up after 1 hour.
struct Man
{
    stomach: Vec<String>,
}

impl Man
{
    fn new() -> Self
    {
        Man {stomach: Vec::new()}
    }
    pub fn feed(&self, food: String)
    {
        let _food = vec![food];
        self.stomach.extend(_food)
    }
    pub fn fart(self)
    {
        println!("You fart!");
    }
}
fn main()
{
    let bob = Man::new();
    bob.feed("pizza".to_owned());
    println!("{:?}", bob.stomach);
    bob.fart();
}
```
## c#          :  5 30mins
[Run online](https://www.tutorialspoint.com/compile_csharp_online.php)
```c#
// hello world:
using System;

class Hello
{
    static void Main()
    {
        Console.WriteLine("Hello World!");
    }
}

```

```c#
// function:
using System;

class Hello
{
    static void Main()
    {
        Console.WriteLine(add(1, 1));
    }

    static int add(int x, int y)
    {
        return x + y;
    }
}

```

```c#
// class:
using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        var bob = new Man();
        bob.feed("pizza");
        Console.WriteLine("[{0}]", String.Join(", ", bob.stomach));
        bob.fart();
    }
}

public class Man
{
    public List<string> stomach;
    public Man()
    {
        stomach = new List<string> {};
    }
    public void feed(string food)
    {
        stomach.Add(food);
    }
    public void fart()
    {
        Console.WriteLine("You fart!");
    }
}
```


## c++         :  5  2hours
C++ is the only one here that needs free memory manually. But don't be afraid of pointers. On modern OS [You won't disrupt other programs](https://stackoverflow.com/questions/4705550/dangers-of-pointers). So turn your home upside down until you get it right. 
[Run online](https://www.tutorialspoint.com/compile_cpp_online.php)
```c++
// hello world:
#include <iostream>

using namespace std;

int main()
{
    // string flow to c output, then append newline.
    cout << "Hello World" << endl;
    return 0;
}
```

```c++
// function:
#include <iostream>
using namespace std;
// we have add(), so don't complain to me.
int add(int, int);
int main()
{
    cout << add(1, 1) << endl;
    return 0;
}
// see? here it is.
int add(int x, int y)
{
    return x + y;
}
```

```c++
// class:
#include <iostream>
#include <vector>
using namespace std;
const int STOMACH_LENGTH = 64;
class Man
{
    public:
        vector<string> stomach;

        Man() { };
        void feed(string food)
        {
            this->stomach.push_back(food);
        }
        void fart()
        {
            cout << "You fart!" << endl;
        }
};

int main()
{
    Man* bob = new Man;
    // don't directly pass string to function.
    string food = "pizza";
    string food2 = "another pizza";
    bob->feed(food);
    bob->feed(food2);
    for (auto i = bob->stomach.begin();i != bob->stomach.end(); ++i)
        std::cout << *i << endl;
    bob->fart();
    delete bob;
    return 0;
}

```
## javascript  :  5  10mins
Actually it's Javascript `Node.js` that's fast enough. 
[Run online](https://www.tutorialspoint.com/execute_nodejs_online.php)
```js
// hello world:
console.log("Hello world!");
```

```js
// function:
function add(x, y) {
   return x + y;
}
console.log(add(1, 1));
```

```js
// class:
class Man {
    constructor () {
        this.stomach = [];
    }
    feed (food) {
        this.stomach += food;
    }
    fart () {
        console.log("You fart!")
    }
}

var bob = new Man();
bob.feed("pizza");
console.log(bob.stomach);
bob.fart();

```

Another [benchmark](https://github.com/trizen/language-benchmarks) (not used in this post). 
P.S. There's an experimental language called [Delight](http://delight.sourceforge.net/index.html), which is D language dressed in Python syntax. FYI.
And [RPython](https://rpython.readthedocs.io/), and [Trylon](https://github.com/stevefolta/trylon). [Mypy](https://github.com/python/mypy). [Alore](https://github.com/JukkaL/alore)


----------------------
More:
### swift
Fast. 
```swift
let appleSummary = "I have \(apples) apples." // \r\n\(
if let name = optionalName { // why not just initialize name with optional value instead, one more line won't kill you.
case let x where x.hasSuffix("pepper"): // let x = where ...
let sortedNumbers = numbers.sorted { $0 > $1 } // (func(x, y)->bool{x > y}) Why hide so much? Human likes consistency.
```

### elixir
```elixir
"hello" <> " world" // Why not `><` collide together?
`client |> Socket.Web.send!(client |> Socket.Web.recv!) // !!!!||||>>>>
```

### chapel
Focusd on multi core multi machine. 3x memory usage. 
Fast for [fibonacci](https://safx-dev.blogspot.com/2015/11/20-rust-go-crystal-nim-swift.html). Simple syntax. 
Not avaliable on windows. 
[chapel-for-python-programmers](https://chapel-for-python-programmers.readthedocs.io/basics.html) 
```
# Nim: Naive recursive Fibonacci(45):
nim c -d:release
debian@doili:~/chapel-1.15.0$ command time -v ./fib.nim.exe
1134903170
        Command being timed: "./fib.nim.exe"
        User time (seconds): 8.50
        System time (seconds): 0.08
        Percent of CPU this job got: 94%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 0:09.05
        Maximum resident set size (kbytes): 1864
        Minor (reclaiming a frame) page faults: 106
        Voluntary context switches: 1
        Involuntary context switches: 2915

# Chapel: Naive Fib(45):
chpl -O
debian@doili:~/chapel-1.15.0$ command time -v ./fib.chpl.exe
1134903170
        Command being timed: "./fib.chpl.exe"
        User time (seconds): 8.68
        System time (seconds): 0.03
        Percent of CPU this job got: 96%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 0:09.06
        Maximum resident set size (kbytes): 4408
        Minor (reclaiming a frame) page faults: 273
        Voluntary context switches: 2
        Involuntary context switches: 1927
```
```
-rwxr-xr-x 1 debian debian  98K Sep 23 13:48 fib.nim.exe
-rwxr-xr-x 1 debian debian 3.2M Sep 23 14:23 fib.chpl.exe
```
### pony
Compiled. Actor model. Too many keywords to remember.

### dart
```dart
Stream<double> computePi({int batch: 1000000}) async* {
```

### ocaml
```ocaml
let average a b =
  (a +. b) /. 2.0;;
```

### racket
```racket
(define f (new frame% [label "Guess"]))
```
Lisp style(((((((()))))))).

### clojure
Lisp.

### groovy
Java.

### scheme
Lisp.

### F#
```F#
 seq { for b in 0 .. 25 do
           if b < 15 then
               yield b*b }
```

评论

此博客中的热门博文

Windows下ShadowSocks客户端安装和配置 顺带KCP

How to Install KeePass on M1 Mac

How User Friendly is a MacOS