こんにちは、3日目の投稿になります。
Introduction
みなさんはrakudo-and-nqp-internals-courseを知っていますか?
rakudo-and-nqp-internalsはMoarVMの開発者であるJonathan Worthington氏の作ったnqpとrakudoの内部構造に関するチュートリアルです。
スライドだけじゃなくて、エクササイズ問題も用意されています。
http://edumentab.github.io/rakudo-and-nqp-internals-course/
というわけで、詳しい話はスライドを見てもらうとして、今回のアドベントカレンダーでは私がエクササイズ問題に挑戦していきたいと思います。
3日目はExercise 1に挑戦します。
Exercise 1
1.1 Hello, World
- 初めの儀式、Hello, worldをしてみましょうという問題です。
!# nqp
say('Hello, world');
1.2 Variables
- スカラ、配列、ハッシュに対して値を代入していきましょうという問題です
- 代入(=)じゃなくて束縛(:=)つかっていくのがポイントです。
!# nqp
my $a := 10;
say($a);
my @b;
@b[0] := 10;
my @c;
@c := [1,2,3];
say(@c[0]);
say(@c[1]);
say(@c[2]);
my $scalar;
$scalar := [1,2,3];
my %h;
%h<key> := 10;
%h{'key'} := 10;
1.3 Loops
- 配列、ハッシュに対してループ処理を書いてみましょうという問題です
- 配列のループのところで一度に2つの値を見るのはこんな感じの解き方であってるのかなあというのだけ気になりました (#1)
!# nqp
my @a := [1,2,3];
for @a {
say($_);
}
for @a -> $val {
say($val);
}
my @b;
@b[0] := [1,2];
@b[1] := [2,3];
for @b { # (#1)
say($_[0]);
say($_[1]);
}
my %h<key> := 10;
for %h {
say($_.key);
say($_.value);
}
1.4 Subroutines
- 階乗を表現する関数を書いてみましょうという問題です。
- 特にnqp独特の部分はなさそうです。
!# nqp
sub fac($a) {
$a == 0 ?? 1 !! $a * fac($a - 1)
}
say(fac(10));
1.5 Classes
-
下記のような複数の問題になっています
- BarTabクラスをつくって、newメソッドを書いてみる
-
$!num-tables
,@!items
といったアトリビュートを書いてみる -
$!num-tables
のゲッターのtable()
メソッドを書いてみる -
$name
と$price
を受け取って@!items
の中身を更新するadd_order
を書いてみる -
@!items
の中身を文字列で提示するrender_tab()
を書いてみる
-
nqp::create()
,nqp::list()
,nqp::push()
が見慣れないかもしれません- nqpのページにドキュメントがあるので、詳しくはそれを参照すると良いでしょう。
-
問題文に
BUILD
を使いなさいとは書いてなかったかもしれませんが、オブジェクトをnqp::create
で作るのはnew
に任せて、いろいろな初期化作業はBUILD
にやらせる感じにしてみました。
!# nqp
class BarTab {
has int $!num-tables;
has @!items;
method new(:$table!) {
my $obj := nqp::create(self);
$obj.BUILD(:table($table));
$obj
}
method BUILD(:$table!) {
$!num-tables := $table;
@!items := nqp::list();
}
method table() {
$!num-tables
}
method add_order(str $name, int $price) {
my %h;
%h<name> := $name;
%h<price> := $price;
nqp::push(@!items, %h);
}
method render_tab() {
my $total := 0;
for @!items {
say($_<name>);
say($_<price>);
$total := $total + $_<price>;
}
say($total);
}
}
my $bar-tab := BarTab.new(table => 42);
say($bar-tab.table);
$bar-tab.add_order("name", 1000);
$bar-tab.render_tab();
1.6 Multi-methods
-
add_order
をmulti-methodに変更しましょうという問題です。 -
int
やstr
のような型を引数にしていするとうまく動かない(スライドにも書いてある)ので注意が必要です。
!# nqp
class BarTab {
has int $!num-tables;
has @!items;
method new(:$table!) {
my $obj := nqp::create(self);
$obj.BUILD(:table($table));
$obj
}
method BUILD(:$table!) {
$!num-tables := $table;
@!items := nqp::list();
}
method table() {
$!num-tables
}
proto method add_order($name, $price, $quantity?) { * }
multi method add_order($name, $price) {
my %h;
%h<name> := $name;
%h<price> := $price;
nqp::push(@!items, %h);
}
multi method add_order($name, $price, $quantity) {
my $i := 0;
while $i < $quantity {
my %h;
%h<name> := $name;
%h<price> := $price;
nqp::push(@!items, %h);
$i := $i + 1;
}
}
method render_tab() {
my $total := 0;
for @!items {
say($_<name>);
say($_<price>);
$total := $total + $_<price>;
}
say($total);
}
}
my $bar-tab := BarTab.new(table => 42);
say($bar-tab.table);
$bar-tab.add_order("name", 1000);
$bar-tab.render_tab();
1.7
- 解いてないです:)
以上、3日目の投稿でした。
ライセンス
rakudo-and-nqp-internals-course is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.