100 Languages Speedrun (102 Part Series)
1 100 Languages Speedrun: Episode 01: Python
2 100 Languages Speedrun: Episode 02: Emojicode
… 98 more parts…
3 100 Languages Speedrun: Episode 03: CSS
4 100 Languages Speedrun: Episode 04: Lua
5 100 Languages Speedrun: Episode 05: Kotlin
6 100 Languages Speedrun: Episode 06: Tcl/Tk
7 100 Languages Speedrun: Episode 07: Sed and Regular Expression FizzBuzz
8 100 Languages Speedrun: Episode 08: Reverse Polish Notation Calculator
9 100 Languages Speedrun: Episode 09: Ada
10 100 Languages Speedrun: Episode 10: Befunge
11 100 Languages Speedrun: Episode 11: Tcsh
12 100 Languages Speedrun: Episode 12: D
13 100 Languages Speedrun: Episode 13: Arc
14 100 Languages Speedrun: Episode 14: Recursive Descent Parser
15 100 Languages Speedrun: Episode 15: Awk
16 100 Languages Speedrun: Episode 16: Octave
17 100 Languages Speedrun: Episode 17: Rake
18 100 Languages Speedrun: Episode 18: PLY Python Lex-Yacc
19 100 Languages Speedrun: Episode 19: Julia
20 100 Languages Speedrun: Episode 20: Forth
21 100 Languages Speedrun: Episode 21: Clojure
22 100 Languages Speedrun: Episode 22: XSLT
23 100 Languages Speedrun: Episode 23: Ruby Z3
24 100 Languages Speedrun: Episode 24: Postscript
25 100 Languages Speedrun: Episode 25: JQ
26 100 Languages Speedrun: Episode 26: Raku (Perl 6)
27 100 Languages Speedrun: Episode 27: Whenever
28 100 Languages Speedrun: Episode 28: TeX
29 100 Languages Speedrun: Episode 29: Verilog
30 100 Languages Speedrun: Episode 30: SageMath
31 100 Languages Speedrun: Episode 31: Fortran
32 100 Languages Speedrun: Episode 32: Gherkin
33 100 Languages Speedrun: Episode 33: Logo
34 100 Languages Speedrun: Episode 34: Racket Scheme
35 100 Languages Speedrun: Episode 35: Groovy
36 100 Languages Speedrun: Episode 36: AppleScript
37 100 Languages Speedrun: Episode 37: OCaml
38 100 Languages Speedrun: Episode 38: BC
39 100 Languages Speedrun: Episode 39: SQLite
40 100 Languages Speedrun: Episode 40: x86-64 Assembly
41 100 Languages Speedrun: Episode 41: WebGL Shader Language
42 100 Languages Speedrun: Episode 42: Prolog
43 100 Languages Speedrun: Episode 43: Thue
44 100 Languages Speedrun: Episode 44: RISC-V Assembly
45 100 Languages Speedrun: Episode 45: M4
46 100 Languages Speedrun: Episode 46: ARM64 Assembly
47 100 Languages Speedrun: Episode 47: Raku (Perl 6) Regular Expressions
48 100 Languages Speedrun: Episode 48: Elvish
49 100 Languages Speedrun: Episode 49: Crystal
50 100 Languages Speedrun: Episode 50: COBOL
51 100 Languages Speedrun: Episode 51: R
52 100 Languages Speedrun: Episode 52: Perl
53 100 Languages Speedrun: Episode 53: QBasic
54 100 Languages Speedrun: Episode 54: Haskell
55 100 Languages Speedrun: Episode 55: Better Thue Interpreter in Crystal
56 100 Languages Speedrun: Episode 56: PHP
57 100 Languages Speedrun: Episode 57: Scala
58 100 Languages Speedrun: Episode 58: XQuery
59 100 Languages Speedrun: Episode 59: Smalltalk
60 100 Languages Speedrun: Episode 60: Asciidots
61 100 Languages Speedrun: Episode 61: POV-Ray
62 100 Languages Speedrun: Episode 62: LLVM Intermediate Representation
63 100 Languages Speedrun: Episode 63: CSVQ
64 100 Languages Speedrun: Episode 64: ChucK
65 100 Languages Speedrun: Episode 65: Randomized Finite Automaton for Fast Thue Interpreter in Crystal
66 100 Languages Speedrun: Episode 66: Xonsh
67 100 Languages Speedrun: Episode 67: Io
68 100 Languages Speedrun: Episode 68: Raku (Perl 6) Grammars
69 100 Languages Speedrun: Episode 69: Ioke
70 100 Languages Speedrun: Episode 70: Wren
71 100 Languages Speedrun: Episode 71: Factor
72 100 Languages Speedrun: Episode 72: Windows Batch Files
73 100 Languages Speedrun: Episode 73: Free Pascal
74 100 Languages Speedrun: Episode 74: Python ANTLR 4
75 100 Languages Speedrun: Episode 75: Abstract Syntax Trees with Python ANTLR 4
76 100 Languages Speedrun: Episode 76: Python SLY
77 100 Languages Speedrun: Episode 77: JVM Assembly with Jasmin
78 100 Languages Speedrun: Episode 78: Better Whenever Interpreter with Python and SLY
79 100 Languages Speedrun: Episode 79: Designing New Esoteric Language Tuples
80 100 Languages Speedrun: Episode 80: Minimalistic Version of Esoteric Language Tuples
81 100 Languages Speedrun: Episode 81: Elixir
82 100 Languages Speedrun: Episode 82: Pyret
83 100 Languages Speedrun: Episode 83: PowerShell
84 100 Languages Speedrun: Episode 84: Lingua Romana Perligata
85 100 Languages Speedrun: Episode 85: Linguagem Potigol
86 100 Languages Speedrun: Episode 86: Emacs Lisp
87 100 Languages Speedrun: Episode 87: Sidef
88 100 Languages Speedrun: Episode 88: Brat
89 100 Languages Speedrun: Episode 89: MoonScript
90 100 Languages Speedrun: Episode 90: YueScript
91 100 Languages Speedrun: Episode 91: Arturo
92 100 Languages Speedrun: Episode 92: newLISP
93 100 Languages Speedrun: Episode 93: Coconut
94 100 Languages Speedrun: Episode 94: Ezhil
95 100 Languages Speedrun: Episode 95: Janet
96 100 Languages Speedrun: Episode 96: Langage Linotte
97 100 Languages Speedrun: Episode 97: Quackery
98 100 Languages Speedrun: Episode 98: Rexx
99 100 Languages Speedrun: Episode 99: Extending Esoteric Language Tuples
100 100 Languages Speedrun: Episode 100: Ruby
101 100 Languages Speedrun: Bonus Episode 101: Programming Languages Tier List
102 100 Languages Speedrun: Bonus Episode 102: Series Retrospective
JVM is a very powerful platform, but Java language is miserable. A bunch of alternatives emerged, Kotlin, Clojure, Scala, Groovy, and JRuby being the most popular ones.
If current trends continue, then in the next few years Kotlin might displace Java as the main JVM language.
But for this episode let’s check a less popular contender, Groovy.
Hello, World!
// Hello world in Groovy
println("Hello, world!")
Enter fullscreen mode Exit fullscreen mode
Guess what it does?
$ groovy hello.groovy
Hello, world!
Enter fullscreen mode Exit fullscreen mode
Notice lack of nasty semicolons, and other boilerplate. Normal Java-style comments with //
and /* ... */
are supported.
FizzBuzz
1.upto(100) {
if (it % 15 == 0) {
println("FizzBuzz")
} else if (it % 5 == 0) {
println("Buzz")
} else if (it % 3 == 0) {
println("Fizz")
} else {
println(it)
}
}
Enter fullscreen mode Exit fullscreen mode
There’s a bit of Ruby-inspired syntax with 1.upto(100) { ... }
. There’s a lot of other ways to loop, even Java-style for
loops.
it
is a default list iteration variable, which is a nice shortcut more languages could use.
Fibonacci
def fib(n) {
if (n <= 2) {
1
} else {
fib(n - 1) + fib(n - 2)
}
}
for (i in 1..30) {
println("fib(${i}) = ${fib(i)}")
}
Enter fullscreen mode Exit fullscreen mode
There’s no need to declare types if you don’t want to, and there’s no need for extra return
.
We have string interpolation with "${}"
. Can you imagine string interpolation used to be highly controversial? Even Python was resisting hard, and only finally saw the light in Python 3.6 in December 2016!
This example uses different style of looping. Ranges do the correct thing and 1..30
means 1 to 30 (not 1 to 29 as in some other languages).
Unicode
Just as all other JVM languages (except notably JRuby), Groovy can’t do Unicode correctly:
println("Hello".length())
println("Źółw".length())
println("".length())
Enter fullscreen mode Exit fullscreen mode
It outputs completely wrong results:
$ groovy unicode.groovy
5
4
2
Enter fullscreen mode Exit fullscreen mode
JRuby pays high performance price for being correct in such cases.
Data Classes
Let’s define a very simple data class Point to represent a point in 2D space. We want the class to have nice constructor, and to understand ==
and .toString()
, but we really don’t want to write all that boilerplate.
import groovy.transform.ToString
import groovy.transform.EqualsAndHashCode
@EqualsAndHashCode
@ToString(includeNames=true)
class Point {
Double x
Double y
def length() {
Math.sqrt(x * x + y * y)
}
}
a = [1, 2, 3]
b = [1, 2, 3]
c = new Point(x: 30.0, y: 40.0)
d = new Point(x: 30.0, y: 40.0)
println(a == b)
println(c == d)
println(null == d)
println("len of ${c} is ${c.length()}")
Enter fullscreen mode Exit fullscreen mode
Which outputs:
$ groovy equality.groovy
true
true
false
len of Point(x:30.0, y:40.0) is 50.0
Enter fullscreen mode Exit fullscreen mode
This is definitely more verbose than Kotlin’s data class
, but still saves us on boilerplate.
Let’s go over it:
-
@EqualsAndHashCode
– it defines==
and.hashCode()
methods, so we can check if two points are equal -
@ToString(includeNames=true)
– it defines.toString()
method, so we can print the point – annotations accept various arguments to customize their behavior, in this case we useincludeNames=true
-
import groovy.transform.ToString
etc. – it’s always annoying to import what feels like it should be just part of the language -
Double x
andDouble y
– static typing is optional, we can saydef x
anddef y
instead to have dynamic typing -
new Point(x: 30.0, y: 40.0)
– constructor with keyword arguments was automatically provided by Groovy -
null == d
– it does not crash like in Java, just returnsfalse
Operator Overloading
In one of oh so many terrible decisions Java made was banning operator overloading, so any code that uses any library-defined containers or mathematical objects looks completely unreadable. It’s like creators of Java did everything they could to make programmer life maximally miserable on purpose.
Anyway, in Groovy it all works fine. Every operator corresponds to some special name, like plus
method is called when you do +
:
import groovy.transform.*
@EqualsAndHashCode
@ToString
class Point {
Double x
Double y
def length() {
Math.sqrt(x * x + y * y)
}
def plus(other) {
new Point(x: x + other.x, y: y + other.y)
}
}
a = new Point(x: 10, y: 40)
b = new Point(x: 20, y: -20)
println("${a} + ${b} == ${a+b}")
Enter fullscreen mode Exit fullscreen mode
Collections
Groovy makes it easy to work with collections:
s = "Java is a terrible language"
println(s.split(" ").collect{ w -> w.capitalize() }.join(" "))
println(s.split(" ").collect{ it.capitalize() }.join(" "))
println(s.split(" ")*.capitalize().join(" "))
Enter fullscreen mode Exit fullscreen mode
$ groovy collections.groovy
Java Is A Terrible Language
Java Is A Terrible Language
Java Is A Terrible Language
Enter fullscreen mode Exit fullscreen mode
One interesting shortcut is *.
which calls a given method on every element of the collection.
Should you use Groovy?
It sure beats Java. Don’t use Java.
A more interesting question is Kotlin vs Groovy. Of the main non-Java languages on the JVM, Clojure, JRuby, and Scala are attempting to do their own thing and definitely not trying to take on Java directly. Groovy and Kotlin both do. They’re basically saying “if you even want to write Java, you should use us instead”.
Kotlin seems to be a bit closer to Java semantics, with everything typed by default and smaller runtime, instead of optionally typed with a bit bigger runtime of Groovy. But to me it seems like minor differences – either of them provides an overwhelming readability and productivity advantage over the pile of shitty boilerplate that’s Java.
Kotlin is definitely winning popularity contest in the JVM world right now, but you’ll do fine using either of them. Or Clojure. Or JRuby. I’m a bit less sure about Scala.
Also do I mention that Java is shit often enough?
Code
All code examples for the series will be in this repository.
Code for the Groovy episode is available here.
100 Languages Speedrun (102 Part Series)
1 100 Languages Speedrun: Episode 01: Python
2 100 Languages Speedrun: Episode 02: Emojicode
… 98 more parts…
3 100 Languages Speedrun: Episode 03: CSS
4 100 Languages Speedrun: Episode 04: Lua
5 100 Languages Speedrun: Episode 05: Kotlin
6 100 Languages Speedrun: Episode 06: Tcl/Tk
7 100 Languages Speedrun: Episode 07: Sed and Regular Expression FizzBuzz
8 100 Languages Speedrun: Episode 08: Reverse Polish Notation Calculator
9 100 Languages Speedrun: Episode 09: Ada
10 100 Languages Speedrun: Episode 10: Befunge
11 100 Languages Speedrun: Episode 11: Tcsh
12 100 Languages Speedrun: Episode 12: D
13 100 Languages Speedrun: Episode 13: Arc
14 100 Languages Speedrun: Episode 14: Recursive Descent Parser
15 100 Languages Speedrun: Episode 15: Awk
16 100 Languages Speedrun: Episode 16: Octave
17 100 Languages Speedrun: Episode 17: Rake
18 100 Languages Speedrun: Episode 18: PLY Python Lex-Yacc
19 100 Languages Speedrun: Episode 19: Julia
20 100 Languages Speedrun: Episode 20: Forth
21 100 Languages Speedrun: Episode 21: Clojure
22 100 Languages Speedrun: Episode 22: XSLT
23 100 Languages Speedrun: Episode 23: Ruby Z3
24 100 Languages Speedrun: Episode 24: Postscript
25 100 Languages Speedrun: Episode 25: JQ
26 100 Languages Speedrun: Episode 26: Raku (Perl 6)
27 100 Languages Speedrun: Episode 27: Whenever
28 100 Languages Speedrun: Episode 28: TeX
29 100 Languages Speedrun: Episode 29: Verilog
30 100 Languages Speedrun: Episode 30: SageMath
31 100 Languages Speedrun: Episode 31: Fortran
32 100 Languages Speedrun: Episode 32: Gherkin
33 100 Languages Speedrun: Episode 33: Logo
34 100 Languages Speedrun: Episode 34: Racket Scheme
35 100 Languages Speedrun: Episode 35: Groovy
36 100 Languages Speedrun: Episode 36: AppleScript
37 100 Languages Speedrun: Episode 37: OCaml
38 100 Languages Speedrun: Episode 38: BC
39 100 Languages Speedrun: Episode 39: SQLite
40 100 Languages Speedrun: Episode 40: x86-64 Assembly
41 100 Languages Speedrun: Episode 41: WebGL Shader Language
42 100 Languages Speedrun: Episode 42: Prolog
43 100 Languages Speedrun: Episode 43: Thue
44 100 Languages Speedrun: Episode 44: RISC-V Assembly
45 100 Languages Speedrun: Episode 45: M4
46 100 Languages Speedrun: Episode 46: ARM64 Assembly
47 100 Languages Speedrun: Episode 47: Raku (Perl 6) Regular Expressions
48 100 Languages Speedrun: Episode 48: Elvish
49 100 Languages Speedrun: Episode 49: Crystal
50 100 Languages Speedrun: Episode 50: COBOL
51 100 Languages Speedrun: Episode 51: R
52 100 Languages Speedrun: Episode 52: Perl
53 100 Languages Speedrun: Episode 53: QBasic
54 100 Languages Speedrun: Episode 54: Haskell
55 100 Languages Speedrun: Episode 55: Better Thue Interpreter in Crystal
56 100 Languages Speedrun: Episode 56: PHP
57 100 Languages Speedrun: Episode 57: Scala
58 100 Languages Speedrun: Episode 58: XQuery
59 100 Languages Speedrun: Episode 59: Smalltalk
60 100 Languages Speedrun: Episode 60: Asciidots
61 100 Languages Speedrun: Episode 61: POV-Ray
62 100 Languages Speedrun: Episode 62: LLVM Intermediate Representation
63 100 Languages Speedrun: Episode 63: CSVQ
64 100 Languages Speedrun: Episode 64: ChucK
65 100 Languages Speedrun: Episode 65: Randomized Finite Automaton for Fast Thue Interpreter in Crystal
66 100 Languages Speedrun: Episode 66: Xonsh
67 100 Languages Speedrun: Episode 67: Io
68 100 Languages Speedrun: Episode 68: Raku (Perl 6) Grammars
69 100 Languages Speedrun: Episode 69: Ioke
70 100 Languages Speedrun: Episode 70: Wren
71 100 Languages Speedrun: Episode 71: Factor
72 100 Languages Speedrun: Episode 72: Windows Batch Files
73 100 Languages Speedrun: Episode 73: Free Pascal
74 100 Languages Speedrun: Episode 74: Python ANTLR 4
75 100 Languages Speedrun: Episode 75: Abstract Syntax Trees with Python ANTLR 4
76 100 Languages Speedrun: Episode 76: Python SLY
77 100 Languages Speedrun: Episode 77: JVM Assembly with Jasmin
78 100 Languages Speedrun: Episode 78: Better Whenever Interpreter with Python and SLY
79 100 Languages Speedrun: Episode 79: Designing New Esoteric Language Tuples
80 100 Languages Speedrun: Episode 80: Minimalistic Version of Esoteric Language Tuples
81 100 Languages Speedrun: Episode 81: Elixir
82 100 Languages Speedrun: Episode 82: Pyret
83 100 Languages Speedrun: Episode 83: PowerShell
84 100 Languages Speedrun: Episode 84: Lingua Romana Perligata
85 100 Languages Speedrun: Episode 85: Linguagem Potigol
86 100 Languages Speedrun: Episode 86: Emacs Lisp
87 100 Languages Speedrun: Episode 87: Sidef
88 100 Languages Speedrun: Episode 88: Brat
89 100 Languages Speedrun: Episode 89: MoonScript
90 100 Languages Speedrun: Episode 90: YueScript
91 100 Languages Speedrun: Episode 91: Arturo
92 100 Languages Speedrun: Episode 92: newLISP
93 100 Languages Speedrun: Episode 93: Coconut
94 100 Languages Speedrun: Episode 94: Ezhil
95 100 Languages Speedrun: Episode 95: Janet
96 100 Languages Speedrun: Episode 96: Langage Linotte
97 100 Languages Speedrun: Episode 97: Quackery
98 100 Languages Speedrun: Episode 98: Rexx
99 100 Languages Speedrun: Episode 99: Extending Esoteric Language Tuples
100 100 Languages Speedrun: Episode 100: Ruby
101 100 Languages Speedrun: Bonus Episode 101: Programming Languages Tier List
102 100 Languages Speedrun: Bonus Episode 102: Series Retrospective
暂无评论内容