JSerが比較コードを書きながらPerlのデータ構造を学ぶ
厳密に言うと間違ってるかもしれないことを感覚的に書いているので、あまり間に受けない方がいいかもしれません。
JavaScriptは、自分が触ったことがある言語の中では、最も仕様を理解している言語になると思います。
そろそろ真面目にサーバーサイドの言語も学んでいきたいと思っているところです。
初めて触れた言語であるPerlをサンプルコードを書きながら比較して理解していこという趣旨のもと、メモがてら完全なるひとりごとをエントリーとして起こしました。
以下、延々とサンプルコードと感想コメントです。
数字や文字列
Perl
my $hoge = 1; print $hoge;
JavaScript
var hoge = 1;
print hoge;
JavaScriptで言うvarはPerlでいうmy。Perlは他にもlocalとかourとかあるけど、JavaScriptにはそれに相当するものはない。
ご指摘いただきました
配列
Perl
my @hoge = (1, 2, 3); print $hoge[1];
JavaScript
対応なし
Perlでいう配列ってJavaScriptにはない気がする。
Perlの例はプリミティブな配列だけど、JavaScriptにプリミティブな配列ってないはず。(参照の配列はある)
代入時には@がプレフィクスだけど、参照時は$を使う。
ハッシュ
Perl
my %hoge = ( hoge => 1, fuga => 2, piyo => 3 ); print $hoge{hoge};
数字や文字列のリファレンス
Perl
my $hoge = 1; my $one = \$hoge; print $$one;
JavaScript
対応なし
PerlはJavaScriptでいうプリミティブなデータもリファレンスにできるみたい。JavaScriptだとコピーになる。
リファレンスを渡すときには、\を先頭に書いて、呼び出す時には、$の頭に$を付ける。
配列のリファレンス
Perl
my @hoge = (1, 2, 3); my $fuga = \@hoge; print $fuga->[0];
JavaScript
var hoge = [1, 2, 3]; var fuga = hoge; print fuga[1];
Perlの配列リファレンスは、JavaScriptの配列と同等と思った。
通常の配列は()で定義するけど、配列のリファレンスは[]で定義する。
リファレンスを渡すときには、\を先頭に書いて、呼び出す時には、$を付けて、アロー演算子の後にインデックスを指定する。
JSerはPerlの配列リファレンスを使えば、JavaScript感覚で操作できるかもしれない。
無名配列のリファレンス
Perl
my $hoge = [1, 2, 3]; print $hoge->[0];
ハッシュのリファレンス
Perl
my %hoge = (hoge => 1, fuga => 2, piyo => 3); my $fuga = \%hoge; print $fuga->{hoge};
JavaScript
var hoge = { hoge: 1, fuga: 2, piyo: 3 }; var fuga = hoge; print fuga.hoge;
配列のリファレンスと同じような感じ。
通常のハッシュは()で定義するけど、ハッシュのリファレンスは{}で定義する。
リファレンスを渡すときには、\を先頭に書いて、呼び出す時には、$を付けて、アロー演算子の後にkeyを指定する。
配列と同様に、JserはPerlのハッシュリファレンスを使えば、JavaScript感覚で操作できるかもしれない。
無名ハッシュのリファレンス
Perl
my $hoge = { hoge => 1, fuga => 2, piyo => 3 }; print $hoge->{hoge};
関数
Perl
sub hoge { # これの省略形↓ my $arg = shift @_; my $arg = shift; } hoge('hoge');
JavaScript
function hoge { var arg = Array.prototype.shift.call(arguments); return arg; } hoge('hoge');
JavaScriptは普通に引数指定できるけど、Perlに合わせるとこんな感じかなと思う。
JavaScriptでいうargumentsが、Perlだと@_で、shiftすれば先頭を取れる。
で、Perlはreturn書かなくても、最後に評価した変数が自動的に返る。
無名関数のリファレンス
Perl
my $hoge = sub { my $arg = shift; }; print $hoge->('hoge');
JavaScript
var hoge = function() { var arg = Array.prototype.shift.call(arguments); return arg; }; print hoge('hoge');
Perlでも関数を変数に格納できる。これで名前付き関数の定義ができるけど、あんまりこういう書き方は見たことがない。
JSer的にはしっくり来るけど、Perlでは気持ち悪い書き方なのかもしれない。
関数と文字列を同じ名前で定義
Perl
my $hoge = 'hoge'; sub hoge { print 'fuga'; } print $hoge; hoge();
Perl
my $hoge = 'hoge'; my $hoge = sub { print 'fuga'; }; print $hoge; $hoge->();
配列のコピー
Perl
my @hoge = (1,2,3); my @fuga = @hoge; print @fuga[0];
JavaScript
var hoge = [1,2,3]; var fuga = Array.prototype.slice.call(hoge); print fuga[0];
Perlだとプリミティブな配列があるからコピーは簡単そう。
JavaScriptは参照型だからめんどくさい。
無名関数リファレンスを定義してその場で実行
Perl
my $hoge = sub { my $num1 = 10; my $num2 = 100; return $num1 * $num2; }->(); print $hoge;
JavaScript
var hoge = (function() { var num1 = 10; var num2 = 100; return num1 * num2; })(); print hoge;
JavaScriptで使ったりする書き方だけど、Perlでも難なくできた。
まとめ
- Perlは変数の型(コンテキスト)を意識して使いわける必要があるけど、JavaScriptは変数の型を意識しなくても良い。
- Perlは変数の型(コンテキスト)によって名前空間が違う。
- Perlの型グロブを使って、すべての型をまとめて扱うこともできるらしい。
- JavaScriptの配列やオブジェクトは、Perlの配列やハッシュではなく、配列のリファレンス、ハッシュのリファレンスに近い。記法もすごく似ている。
- Perlでは値を参照する時にデリファレンスする必要があるが、JavaScriptではデリファレンスする必要がない。
- Perlでは文字列や数値もリファレンスとして渡すことができる。
JavaScriptな頭でPerlを理解するには、JavaScriptではPerlのリファレンス相当のものを常に触っているという意識を持つと良さそうです。
そうすると一見ややこしく感じる、リファレンスの理解が進む気がしました。