blog/content/post/2008/10/04/2008-10-04-00001045.md

290 lines
19 KiB
Markdown

---
title: Perlのリファレンスを学ぶ
author: kazu634
date: 2008-10-04
wordtwit_post_info:
- 'O:8:"stdClass":13:{s:6:"manual";b:0;s:11:"tweet_times";i:1;s:5:"delay";i:0;s:7:"enabled";i:1;s:10:"separation";s:2:"60";s:7:"version";s:3:"3.7";s:14:"tweet_template";b:0;s:6:"status";i:2;s:6:"result";a:0:{}s:13:"tweet_counter";i:2;s:13:"tweet_log_ids";a:1:{i:0;i:4323;}s:9:"hash_tags";a:0:{}s:8:"accounts";a:1:{i:0;s:7:"kazu634";}}'
categories:
- Perl
- Programming
---
<div class="section">
<h4>
はじめに
</h4>
<p>
<a href="http://d.hatena.ne.jp/asin/4774135046" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://d.hatena.ne.jp/asin/4774135046', 'すぐわかる オブジェクト指向 Perl');">すぐわかる オブジェクト指向 Perl</a>』を読んでいます。CやGaucheとの関連から結構、頭に入ってきやすいです。自分用の備忘録として書いておきます。
</p>
<h4>
主な違い
</h4>
<p>
Perlのリファレンスというのは、Cのポインタのこと。主な違いは:
</p>
<ol>
<li>
C言語のポインタは、メモリーアドレスがダイレクトに入っている。
</li>
<li>
ある文字列の1文字目をC言語のポインタで指し、ポインタに1加算すると、ポインタは2文字目を指す。同様に、ある配列の1要素目を指しているポインタに1を加算すると2要素目を指す。このようにポインタの中身を自由に計算できる。
</li>
<li>
ポインタを使うときは、コンピュータのどのメモリーをどのぐらい使うかあらかじめ計算しておく必要がある。
</li>
<li>
ポインタに意味のない値をうっかり入れてしまったり、不適切な演算を行ったりすると、プラグラムが馬鹿正直にそのメモリ空間を指すので暴走してしまう。
</li>
<li>
コンピュータ上ではプログラム自身もデータである。ポインタ演算の失敗によって、メモリー上の他のプログラムやOSも書き換えられてしまうことによって軒並み暴走が起こる可能性がある。
</li>
</ol>
<p>
<a name="seemore"></a><br />
</p>
<h4>
スカラー変数のリファレンス
</h4>
<h5>
Perlの場合
</h5>
<pre class="syntax-highlight">
<span class="synStatement">use strict</span>;
<span class="synStatement">use warnings</span>;
<span class="synStatement">my</span> <span class="synIdentifier">$age</span> = <span class="synConstant">26</span>;
<span class="synStatement">my</span> <span class="synIdentifier">$ref_age</span> = <span class="synIdentifier">\$age</span>;
<span class="synStatement">print</span>(<span class="synIdentifier">$$ref_age</span>, <span class="synConstant">&#34;</span><span class="synSpecial">\n</span><span class="synConstant">&#34;</span>);
</pre>
<h5>
Cの場合
</h5>
<pre class="syntax-highlight">
<span class="synPreProc">#include </span><span class="synConstant">&#60;stdio.h&#62;</span>
<span class="synType">int</span> main(<span class="synType">int</span> argc, <span class="synType">char</span> *argv[])
{
<span class="synType">int</span> age = <span class="synConstant">26</span>;
<span class="synType">int</span> *ref_age =
printf(<span class="synConstant">&#34;</span><span class="synSpecial">%3d\n</span><span class="synConstant">&#34;</span>, *ref_age);
<span class="synStatement">return</span> <span class="synConstant"></span>;
}
</pre>
<h4>
配列のリファレンス
</h4>
<h5>
Perlの場合
</h5>
<pre class="syntax-highlight">
<span class="synStatement">use strict</span>;
<span class="synStatement">use warnings</span>;
<span class="synStatement">my</span> <span class="synIdentifier">@month</span> = (
<span class="synConstant">'January'</span>, <span class="synConstant">'February'</span>, <span class="synConstant">'March'</span>, <span class="synConstant">'April'</span>, <span class="synConstant">'May'</span>, <span class="synConstant">'June'</span>,
<span class="synConstant">'July'</span>, <span class="synConstant">'August'</span>, <span class="synConstant">'September'</span>, <span class="synConstant">'October'</span>, <span class="synConstant">'November'</span>, <span class="synConstant">'December'</span>
);
<span class="synComment"># $ref_monthに@monthのリファレンスを代入</span>
<span class="synStatement">my</span> <span class="synIdentifier">$ref_month</span> = <span class="synIdentifier">\@month</span>;
<span class="synComment"># 配列のデリファレンス</span>
<span class="synStatement">print</span>(<span class="synIdentifier">@$ref_month</span>, <span class="synConstant">&#34;</span><span class="synSpecial">\n</span><span class="synConstant">&#34;</span>);
<span class="synStatement">print</span>(<span class="synIdentifier">$$ref_month</span>[<span class="synConstant">1</span>], <span class="synConstant">&#34;</span><span class="synSpecial">\n</span><span class="synConstant">&#34;</span>);
<span class="synComment"># $$ref_month[4]のシンタックスシュガー</span>
<span class="synStatement">print</span>(<span class="synIdentifier">$ref_month</span>-&#62;[<span class="synConstant">4</span>], <span class="synConstant">&#34;</span><span class="synSpecial">\n</span><span class="synConstant">&#34;</span>);
</pre>
<h5>
Cの場合
</h5>
<p>
char型の二次元配列をポインタでしか宣言できなかった(..;)だから、上のPerlとはちょっと違う。
</p>
<pre class="syntax-highlight">
<span class="synPreProc">#include </span><span class="synConstant">&#60;stdio.h&#62;</span>
<span class="synType">int</span> main(<span class="synType">int</span> argc, <span class="synType">char</span> *argv[])
{
<span class="synType">char</span> *month[] = {
<span class="synConstant">&#34;January&#34;</span>, <span class="synConstant">&#34;Feburary&#34;</span>, <span class="synConstant">&#34;March&#34;</span>, <span class="synConstant">&#34;April&#34;</span>, <span class="synConstant">&#34;May&#34;</span>,
<span class="synConstant">&#34;June&#34;</span>, <span class="synConstant">&#34;July&#34;</span>, <span class="synConstant">&#34;August&#34;</span>, <span class="synConstant">&#34;September&#34;</span>, <span class="synConstant">&#34;October&#34;</span>,
<span class="synConstant">&#34;November&#34;</span>, <span class="synConstant">&#34;December&#34;</span>
};
printf(<span class="synConstant">&#34;</span><span class="synSpecial">%s\n</span><span class="synConstant">&#34;</span>, month[<span class="synConstant">1</span>]);
printf(<span class="synConstant">&#34;</span><span class="synSpecial">%s\n</span><span class="synConstant">&#34;</span>, month[<span class="synConstant">4</span>]);
<span class="synStatement">return</span> <span class="synConstant"></span>;
}
</pre>
<h4>
二次元配列
</h4>
<p>
つぎのようにして、二次元配列を使うことができる。
</p>
<pre class="syntax-highlight">
<span class="synStatement">use strict</span>;
<span class="synStatement">use warnings</span>;
<span class="synStatement">my</span> <span class="synIdentifier">@jan</span> = (<span class="synConstant">'January'</span>, <span class="synConstant">31</span>);
<span class="synStatement">my</span> <span class="synIdentifier">@feb</span> = (<span class="synConstant">'Feburary'</span>, <span class="synConstant">28</span>);
<span class="synStatement">my</span> <span class="synIdentifier">@mar</span> = (<span class="synConstant">'March'</span>, <span class="synConstant">31</span>);
<span class="synStatement">my</span> <span class="synIdentifier">@apr</span> = (<span class="synConstant">'April'</span>, <span class="synConstant">30</span>);
<span class="synStatement">my</span> <span class="synIdentifier">@may</span> = (<span class="synConstant">'May'</span>, <span class="synConstant">31</span>);
<span class="synStatement">my</span> <span class="synIdentifier">@jun</span> = (<span class="synConstant">'June'</span>, <span class="synConstant">30</span>);
<span class="synStatement">my</span> <span class="synIdentifier">@jul</span> = (<span class="synConstant">'July'</span>, <span class="synConstant">31</span>);
<span class="synStatement">my</span> <span class="synIdentifier">@aug</span> = (<span class="synConstant">'August'</span>, <span class="synConstant">31</span>);
<span class="synStatement">my</span> <span class="synIdentifier">@sep</span> = (<span class="synConstant">'September'</span>, <span class="synConstant">30</span>);
<span class="synStatement">my</span> <span class="synIdentifier">@oct</span> = (<span class="synConstant">'October'</span>, <span class="synConstant">31</span>);
<span class="synStatement">my</span> <span class="synIdentifier">@nov</span> = (<span class="synConstant">'November'</span>, <span class="synConstant">30</span>);
<span class="synStatement">my</span> <span class="synIdentifier">@dec</span> = (<span class="synConstant">'December'</span>, <span class="synConstant">31</span>);
<span class="synStatement">my</span> <span class="synIdentifier">@month</span> = (<span class="synIdentifier">\@jan</span>, <span class="synIdentifier">\@feb</span>, <span class="synIdentifier">\@mar</span>, <span class="synIdentifier">\@apr</span>, <span class="synIdentifier">\@may</span>, <span class="synIdentifier">\@jun</span>, <span class="synIdentifier">\@jul</span>,
<span class="synIdentifier">\@aug</span>, <span class="synIdentifier">\@sep</span>, <span class="synIdentifier">\@oct</span>, <span class="synIdentifier">\@nov</span>, <span class="synIdentifier">\@dec</span>);
<span class="synStatement">foreach</span> <span class="synStatement">my</span> <span class="synIdentifier">$x</span> (<span class="synIdentifier">@month</span>) {
<span class="synStatement">print</span>(<span class="synIdentifier">$x</span>-&#62;[<span class="synConstant"></span>], <span class="synConstant">&#34;</span><span class="synSpecial">\n</span><span class="synConstant">&#34;</span>);
}
</pre>
<p>
また、Lispのlambdaみたいな無名の手続きならぬ、無名の配列を作ることができる。
</p>
<pre class="syntax-highlight">
<span class="synStatement">use strict</span>;
<span class="synStatement">use warnings</span>;
<span class="synStatement">my</span> <span class="synIdentifier">@month</span> = (
[ <span class="synConstant">'January'</span>, <span class="synConstant">31</span> ],
[ <span class="synConstant">'Feburary'</span>, <span class="synConstant">28</span> ],
[ <span class="synConstant">'March'</span>, <span class="synConstant">31</span> ],
[ <span class="synConstant">'April'</span>, <span class="synConstant">30</span> ],
[ <span class="synConstant">'May'</span>, <span class="synConstant">31</span> ],
[ <span class="synConstant">'June'</span>, <span class="synConstant">30</span> ],
[ <span class="synConstant">'July'</span>, <span class="synConstant">31</span> ],
[ <span class="synConstant">'August'</span>, <span class="synConstant">31</span> ],
[ <span class="synConstant">'September'</span>, <span class="synConstant">30</span> ],
[ <span class="synConstant">'October'</span>, <span class="synConstant">31</span> ],
[ <span class="synConstant">'November'</span>, <span class="synConstant">30</span> ],
[ <span class="synConstant">'December'</span>, <span class="synConstant">31</span> ],
);
<span class="synStatement">foreach</span> <span class="synStatement">my</span> <span class="synIdentifier">$x</span> (<span class="synIdentifier">@month</span>) {
<span class="synStatement">print</span>(<span class="synIdentifier">$x</span>-&#62;[<span class="synConstant"></span>], <span class="synConstant">&#34;: &#34;</span>);
<span class="synStatement">print</span>(<span class="synIdentifier">$x</span>-&#62;[<span class="synConstant">1</span>], <span class="synConstant">&#34;</span><span class="synSpecial">\n</span><span class="synConstant">&#34;</span>);
}
</pre>
<p>
</p>
<h4>
ハッシュのリファレンス
</h4>
<pre class="syntax-highlight">
<span class="synStatement">use strict</span>;
<span class="synStatement">use warnings</span>;
<span class="synComment"># ハッシュの宣言</span>
<span class="synStatement">my</span> <span class="synIdentifier">%month</span> = (
<span class="synConstant">January </span>=&#62; <span class="synConstant">31</span>,
<span class="synConstant">Feburary </span>=&#62; <span class="synConstant">28</span>,
<span class="synConstant">March </span>=&#62; <span class="synConstant">31</span>,
<span class="synConstant">April </span>=&#62; <span class="synConstant">30</span>,
<span class="synConstant">May </span>=&#62; <span class="synConstant">31</span>,
<span class="synConstant">June </span>=&#62; <span class="synConstant">30</span>,
<span class="synConstant">July </span>=&#62; <span class="synConstant">31</span>,
<span class="synConstant">August </span>=&#62; <span class="synConstant">31</span>,
<span class="synConstant">September </span>=&#62; <span class="synConstant">30</span>,
<span class="synConstant">October </span>=&#62; <span class="synConstant">31</span>,
<span class="synConstant">November </span>=&#62; <span class="synConstant">30</span>,
<span class="synConstant">December </span>=&#62; <span class="synConstant">31</span>,
);
<span class="synComment"># ハッシュの要素を表示</span>
<span class="synStatement">print</span>(<span class="synIdentifier">$month</span>{January}, <span class="synConstant">&#34;</span><span class="synSpecial">\n</span><span class="synConstant">&#34;</span>);
<span class="synComment"># ハッシュのキーを表示する</span>
<span class="synStatement">print</span>(<span class="synStatement">keys</span> <span class="synIdentifier">%month</span>, <span class="synConstant">&#34;</span><span class="synSpecial">\n</span><span class="synConstant">&#34;</span>);
<span class="synComment"># ハッシュのリファレンス</span>
<span class="synStatement">my</span> <span class="synIdentifier">$ref_month</span> = <span class="synIdentifier">\%month</span>;
<span class="synComment"># リファレンスのデリファレンス</span>
<span class="synStatement">print</span>(<span class="synStatement">keys</span> <span class="synIdentifier">%$ref_month</span>, <span class="synConstant">&#34;</span><span class="synSpecial">\n</span><span class="synConstant">&#34;</span>);
<span class="synComment"># リファレンスから要素を得る</span>
<span class="synStatement">print</span>(<span class="synIdentifier">$$ref_month</span>{January}, <span class="synConstant">&#34;</span><span class="synSpecial">\n</span><span class="synConstant">&#34;</span>);
<span class="synComment"># リファレンスから要素を得る(シンタックスシュガー)</span>
<span class="synStatement">print</span>(<span class="synIdentifier">$ref_month</span>-&#62;{January}, <span class="synConstant">&#34;</span><span class="synSpecial">\n</span><span class="synConstant">&#34;</span>);
</pre>
<h4>
無名ハッシュ
</h4>
<pre class="syntax-highlight">
<span class="synStatement">use strict</span>;
<span class="synStatement">use warnings</span>;
<span class="synComment"># ハッシュの宣言</span>
<span class="synStatement">my</span> <span class="synIdentifier">$ref_month</span> = {
<span class="synConstant">January </span>=&#62; <span class="synConstant">31</span>,
<span class="synConstant">Feburary </span>=&#62; <span class="synConstant">28</span>,
<span class="synConstant">March </span>=&#62; <span class="synConstant">31</span>,
<span class="synConstant">April </span>=&#62; <span class="synConstant">30</span>,
<span class="synConstant">May </span>=&#62; <span class="synConstant">31</span>,
<span class="synConstant">June </span>=&#62; <span class="synConstant">30</span>,
<span class="synConstant">July </span>=&#62; <span class="synConstant">31</span>,
<span class="synConstant">August </span>=&#62; <span class="synConstant">31</span>,
<span class="synConstant">September </span>=&#62; <span class="synConstant">30</span>,
<span class="synConstant">October </span>=&#62; <span class="synConstant">31</span>,
<span class="synConstant">November </span>=&#62; <span class="synConstant">30</span>,
<span class="synConstant">December </span>=&#62; <span class="synConstant">31</span>,
};
<span class="synComment"># リファレンスのデリファレンス</span>
<span class="synStatement">print</span>(<span class="synStatement">keys</span> <span class="synIdentifier">%$ref_month</span>, <span class="synConstant">&#34;</span><span class="synSpecial">\n</span><span class="synConstant">&#34;</span>);
<span class="synComment"># リファレンスから要素を得る</span>
<span class="synStatement">print</span>(<span class="synIdentifier">$ref_month</span>-&#62;{January}, <span class="synConstant">&#34;</span><span class="synSpecial">\n</span><span class="synConstant">&#34;</span>);
</pre>
<h4>
関数のリファレンス
</h4>
<pre class="syntax-highlight">
<span class="synStatement">use strict</span>;
<span class="synStatement">use warnings</span>;
<span class="synStatement">my</span> <span class="synIdentifier">$ref_sub</span> = \
<span class="synStatement">my</span> <span class="synIdentifier">$result</span> = <span class="synIdentifier">$ref_sub</span>-&#62;(<span class="synConstant">1</span>, <span class="synConstant">2</span>);
<span class="synStatement">print</span>(<span class="synIdentifier">$result</span>, <span class="synConstant">&#34;</span><span class="synSpecial">\n</span><span class="synConstant">&#34;</span>);
<span class="synStatement">exit</span>;
<span class="synStatement">sub</span><span class="synIdentifier"> add </span>{
<span class="synStatement">my</span> (<span class="synIdentifier">$x</span>, <span class="synIdentifier">$y</span>) = <span class="synIdentifier">@_</span>;
<span class="synStatement">return</span> (<span class="synIdentifier">$x</span> + <span class="synIdentifier">$y</span>);
}
</pre>
<h4>
無名関数
</h4>
<p>
これこそlambdaと同じだよ!
</p>
<pre class="syntax-highlight">
<span class="synStatement">use strict</span>;
<span class="synStatement">use warnings</span>;
<span class="synStatement">my</span> <span class="synIdentifier">$ref_sub</span> =<span class="synIdentifier"> </span><span class="synStatement">sub</span><span class="synIdentifier"> </span>{
<span class="synStatement">my</span> ( <span class="synIdentifier">$x</span>, <span class="synIdentifier">$y</span> ) = <span class="synIdentifier">@_</span>;
<span class="synStatement">return</span> ( <span class="synIdentifier">$x</span> + <span class="synIdentifier">$y</span> );
};
<span class="synStatement">my</span> <span class="synIdentifier">$result</span> = <span class="synIdentifier">$ref_sub</span>-&#62;(<span class="synConstant">1</span>, <span class="synConstant">2</span>);
<span class="synStatement">print</span>(<span class="synIdentifier">$result</span>, <span class="synConstant">&#34;</span><span class="synSpecial">\n</span><span class="synConstant">&#34;</span>);
<span class="synStatement">exit</span>;
</pre>
</div>