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 }
```
评论
发表评论