I wrote this kind of thing before, but as a craftsman, I was tempted to make my own tools.
Well, even if you say no, it's something that you can find somewhere (I won't say it here), but I'm lonely even if I'm complacent, so let's leave a footprint of the explanation. (I will update this article as I add it to the table of contents)
When I posted it steadily, the number of articles increased considerably.
A scripting language that inherits the traditional C-syntax that is familiar to the hand. The aim is "** looks JavaScript **, ** brain (contents) is Ruby **, ** stability is AC / DC (?) **".
I haven't got the libraries and basic methods yet, so it's still a long way off, but the basic parts of the language are almost working.
A good adult, not a child.
JavaScript is the most successful scripting language in the C family. However, it is not good for desktop. node.js is convenient but too heavy and too quirky in its behavior.
On the other hand, I like the idea of Ruby, but I'm reluctant to use the syntax that ʻend` is noticeable. Ordinary keywords are usually buried ...
That said, I don't hate Ruby thinking. Yes, it's just a matter of appearance. Then it should be Ruby that looks different.
Let's emulate the place where there is no blur.
I can't touch it deeply (?), But the masterpiece of Red Warriors ["KING'S"](https://ja.wikipedia.org/wiki/ Let's just say that it goes back to KING'S).
At the moment, it is "KINX", so the origin is "[You Really Got Me](https: /), which is famous for ([VAN HALEN](https://ja.wikipedia.org/wiki/Van Halen)). /ja.wikipedia.org/wiki/You Really Got Me) "original) Kinks" I am also considering things.
Detailed explanations will be delivered in a series. I don't care if there is demand.
If you want to know the detailed specifications right now ... "here" please refer to.
fibonacci
fib.kx
function fib(n) {
if (n < 3) return n;
return fib(n-2) + fib(n-1);
}
System.println(fib($$[1].toInt()));
The first thing to write is a benchmark. It looks like JavaScript.
At that time, Ruby used to fuel everyone, saying, "Speed isn't the goal, isn't it fun?" Looking at the amount of sensation since YARV was released, I saw that stance was exactly "sour grapes" ... (No, I like Ruby, except for how it looks)
Let's benchmark immediately. By the way, I would like to see it appear in Python, which Ruby sees as a rival. Compared to this area, you can estimate your ability. The source code is as follows. Python3 is slower than Python2, so 2
fib.rb
def fib(n)
if n < 3
return n;
else
return fib(n-2) + fib(n-1);
end
end
puts fib(ARGV[0].to_i)
fib.py
import sys
def fib(n):
if n < 3:
return n
else:
return fib(n-1) + fib(n-2)
print fib(int(sys.argv[1]))
First of all, the version display.
$ ruby --version
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86-64-linux-gnu]
$ python --version
Python 2.7.15+
And the result. The unit is ** "seconds" **. The time
command ʻuser` in order of time. The fastest time I did about 5 times.
language | fib(34) |
fib(38) |
fib(39) |
---|---|---|---|
Ruby | 0.391 | 2.016 | 3.672 |
Kinx | 0.594 | 4.219 | 6.859 |
Python | 0.750 | 5.539 | 9.109 |
value | 9227465 | 63245986 | 102334155 |
Ruby is super fast. Slow Slow is just a story of the past. Rather, it seems that it is in the fast category.
I beat Python, so it's like this. I'm not thinking of becoming a speed king, so let's keep it within the permissible range if it's a practical speed. However, Kinx actually has a special move called native
. To be honest, I don't know how useful it is in practice, but I felt the possibility and put it in. The source code is below. I just changed function
to native
.
nfib.kx
native fib(n) {
if (n < 3) return n;
return fib(n-2) + fib(n-1);
}
System.println(fib($$[1].toInt()));
Let's add to the table above to show the results of how this minor modification will affect us.
language | fib(34) |
fib(38) |
fib(39) |
---|---|---|---|
Kinx(native) | 0.063 | 0.453 | 0.734 |
Ruby | 0.391 | 2.016 | 3.672 |
Kinx | 0.594 | 4.219 | 6.859 |
Python | 0.750 | 5.539 | 9.109 |
value | 9227465 | 63245986 | 102334155 |
Kita.
As the name suggests, the function with the native
keyword is natively compiled into machine language code and JIT executed, which I think you already know. It's fast, isn't it? However, the output assembly code is not optimized or registered and is not beautiful at all. I don't know if it's practically useful because there are various restrictions. I'll touch on it later, but I won't touch it today. See "here" for more information.
I will not explain in detail this time because it will be a series, but I will only show what you can do.
Prototype-based like JavaScript. However, there is no such thing as __proto__
. The method is tied directly to the object property. If you want to override it, simply overwrite it. The class
keyword is prepared, and the class can be defined. Like this.
class ClassName {
var privateVar_;
private initialize() {
privateVar_ = 0;
this.publicVar = 0;
}
/* private method */
private method1() { /* ... */ }
private method2() { /* ... */ }
/* public method */
public method3() { /* ... */ }
public method4() { /* ... */ }
}
var obj = new ClassName();
A simple and clear Stop The World mark-and-sweep. I'm not in trouble so far (I haven't used it so much that I'm in trouble), so there's no problem. If there is a problem, think about it then.
Function objects have lexical scope and can realize closures. If it becomes JavaScript (but not), it works naturally. Like this.
function newCounter() {
var i = 0; // a lexical variable.
return function() { // an anonymous function.
++i; // a reference to a lexical variable.
return i;
};
}
var c1 = newCounter();
System.println(c1()); // 1
System.println(c1()); // 2
System.println(c1()); // 3
System.println(c1()); // 4
System.println(c1()); // 5
Anonymous function objects can be written concisely. The arrow function was introduced in ES6, but it's not exactly the same and requires a &
at the beginning. Why you ask? I couldn't write well with Yacc. I can't resolve the conflict (sorry). Like this.
function calc(x, y, func) {
return func(x, y);
}
System.println("add = " + calc(10, 2, &(a, b) => a + b));
System.println("sub = " + calc(10, 2, &(a, b) => a - b));
System.println("mul = " + calc(10, 2, &(a, b) => a * b));
System.println("div = " + calc(10, 2, &(a, b) => a / b));
// add = 12
// sub = 8
// mul = 20
// div = 5
Actually, I have never used this function. It's just in Ruby, and it seems convenient, so I implemented it. I tried it with a light feeling that I could do it this way, and it worked quite well. However, since the stack state is not retained during yield
, yield
is valid only as a single expression statement. Substitution is possible. What this means is that you can't embed yield
directly as a function argument, but an expression like ʻa = yield 10; is OK. At this time, ʻa
comes with an array of caller arguments. A simple sample looks like this.
var fiber = new Fiber(function() {
System.println("fiber 1");
yield;
System.println("fiber 2");
});
System.println("main 1");
fiber.resume();
System.println("main 2");
fiber.resume();
System.println("main 3");
// main 1
// fiber 1
// main 2
// fiber 2
// main 3
The spread (rest) operator introduced in ES6 (isn't it?). Yes, I wanted this. Super convenient. There are various uses, but it looks like this.
function sample(a1, a2, ...a3) {
// a1 = 1
// a2 = 2
// a3 = [3, 4, 5]
}
sample(1, 2, 3, 4, 5);
Thank you for reading this far. Well, if you feel like it, please use it. I don't think there is any practical use yet.
Contributions are welcome. The easiest way to contribute is to click on the "★". It's still few, but if you increase it, you'll be more motivated. I hope there will be more ★.