<?xml version="1.0" encoding="utf-8" ?>


<?xml-stylesheet href="http://d.hatena.ne.jp/gfx/rssxsl" type="text/xsl" media="screen"?>


<rdf:RDF
	xmlns="http://purl.org/rss/1.0/"
	xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xml:lang="ja">
<channel rdf:about="http://d.hatena.ne.jp/gfx/rss">
	<title>Islands in the byte stream</title>
	<link>http://d.hatena.ne.jp/gfx/</link>
	<description>Islands in the byte stream</description>
	
	<dc:creator>gfx</dc:creator>
	<dc:date>2010-02-07T15:10:29+09:00</dc:date>
	<items>
	<rdf:Seq>
		<rdf:li rdf:resource="http://d.hatena.ne.jp/gfx/20100207/1265523020"/>
		<rdf:li rdf:resource="http://d.hatena.ne.jp/gfx/20100205/1265344597"/>
		<rdf:li rdf:resource="http://d.hatena.ne.jp/gfx/20100202/1265091606"/>
		<rdf:li rdf:resource="http://d.hatena.ne.jp/gfx/20100201/1265026337"/>
		<rdf:li rdf:resource="http://d.hatena.ne.jp/gfx/20100126/1264474754"/>
	</rdf:Seq>
	</items>
</channel>



<item rdf:about="http://d.hatena.ne.jp/gfx/20100207/1265523020">
	<title>[Perl]ホットスポットを最適化する</title>
	<link>http://d.hatena.ne.jp/gfx/20100207/1265523020</link>
	<description> 最適化するのに相応しいサブルーチンのみ最適化できるように，optimizer::hotspotというモジュールを考えてみた。まだCPANクオリティではないのでgithubのみ。 http://github.com/gfx/Perl-optimizer-hotspot 仕組みとしては，PL_peeppをフックして，生成されるサブルーチン</description>

	<content:encoded><![CDATA[
		<div class="section">
			<p>最適化するのに相応しいサブルーチンのみ最適化できるように，optimizer::hotspotというモジュールを考えてみた。まだCPANクオリティではないのでgithubのみ。</p>
			<ul>
				<li> <a href="http://github.com/gfx/Perl-optimizer-hotspot">http://github.com/gfx/Perl-optimizer-hotspot</a></li>
			</ul>
			<p>仕組みとしては，PL_peeppをフックして，生成されるサブルーチンの頭にホットスポット計測のためのopcode<span class="footnote"><a href="/gfx/#f1" name="fn1" title="対応するppcodeはoptimizer_pp_count() ">*1</a></span>を仕込み，そのopcodeが一定数呼ばれると，最適化器<span class="footnote"><a href="/gfx/#f2" name="fn2" title="optimizer_hotspot_peep() -&#62; optimizer_combine_opcode() ">*2</a></span>を起動するというものだ。</p>
			<p>最適化の基本は，いまのところ特定パターンをもつ構文木を高速な一つのノードに置き換えるというもの。少し実装してみたところ，以下のような結果となった。</p>
			<p><a href="http://github.com/gfx/Perl-optimizer-hotspot/blob/master/benchmarks/arbit.pl">benchmarks/arbit.pl</a></p>
<pre>
# &#39;s&#39; represents &#39;single-threaded&#39;
$ sperl -Mblib benchmarks/arbit.pl
Perl/5.10.1 on i686-linux
           Rate     plain optimized
plain     489/s        --      -39%
optimized 797/s       63%        --
</pre>

			<p>以上，Perlを63%高速化することができた。</p>
			<p>.</p>
			<p>.</p>
			<p>.</p>
			<p>もちろん，これで済むほど話は簡単ではない。このベンチマークは恣意的なもので，ベンチマークスクリプトは非常に不自然なコードである。もう少しまともなbenchmark/math.plを実行すると，効果は誤差の範囲内でしかないことがわかる。</p>
			<p>ホットスポットを検出して最適化器を起動する，というところまではいいが，そこから先の最適化についてはもう少しいい方法を考えないと使い物にならないのではないかと思う。</p>
			<p>特定パターンを検出する方法は，まずパターンの検出が大変すぎるし，この調子でパターンを増やしたとしても所詮ヒューリスティクスによる小手先の最適化にすぎず，アプリケーションレベルで+10%達成できれば御の字だろう。</p>
			<p>ということを考えると，プロファイラでボトルネックを探してその部分をXS化するほうがずっと簡単だ。</p>
		</div>
		<div class="footnote">
			<p class="footnote"><a href="/gfx/#fn1" name="f1">*1</a>：対応するppcodeはoptimizer_pp_count() </p>
			<p class="footnote"><a href="/gfx/#fn2" name="f2">*2</a>：optimizer_hotspot_peep() -&#62; optimizer_combine_opcode() </p>
		</div>
]]></content:encoded>
	<dc:creator>gfx</dc:creator>
	<dc:date>2010-02-07T15:10:20+09:00</dc:date>
	<dc:subject>Perl</dc:subject>
</item>
<item rdf:about="http://d.hatena.ne.jp/gfx/20100205/1265344597">
	<title>[Perl]Perlの最適化の概要</title>
	<link>http://d.hatena.ne.jp/gfx/20100205/1265344597</link>
	<description> Perlコアの最適化をまとめておく。 まず，opcodeの最適化を主に行っているのは，op.cのPerl_peep()である。ただし，これは最適化以外の処理，たとえばuse strict ’subs’の下でベアワードに対して致命的エラーを投げる，なども行っている。 さて，Perl_peep()の最適化はだい</description>

	<content:encoded><![CDATA[
		<div class="section">
			<p>Perlコアの最適化をまとめておく。</p>
			<p>まず，opcodeの最適化を主に行っているのは，<a href="http://cpansearch.perl.org/src/DAPM/perl-5.10.1/op.c">op.c</a>のPerl_peep()である。ただし，これは最適化以外の処理，たとえば<code>use strict 'subs'</code>の下でベアワードに対して致命的エラーを投げる，なども行っている。</p>
			<p>さて，Perl_peep()の最適化はだいたい以下の3パターンである。</p>
			<ul>
				<li> 不要なopcodeを削除
				<ul>
					<li> opcodeを構築する際につかわれる，op_stubやop_nullなどのスタブノード</li>
					<li> op_scalar<span class="footnote"><a href="/gfx/#f1" name="fn1" title="CORE::scalar()の実体">*1</a></span>など，実質的な意味を持たないopcode</li>
				</ul>
				</li>
				<li> よくあるopcodeパターンを一つにまとめる
				<ul>
					<li> "reverse sort LIST"において，op_sortの逆順ソートビットを立ててop_reverseを消す<span class="footnote"><a href="/gfx/#f2" name="fn2" title="sortの最適化については[http://d.hatena.ne.jp/gfx/20090531/1243743871:title=Optimization of sort()]で解説済み">*2</a></span></li>
					<li> $arrary[10]などの定数添え字が小さな定数の場合，op_aelemfastに変換してopcodeに添え字を埋め込む</li>
				</ul>
				</li>
				<li> データに細工を施す
				<ul>
					<li> $hash{foo}などの定数キーをShared SVに変換する</li>
				</ul>
				</li>
			</ul>
			<p>このうち，頻出するopcodeパターンを一つにまとめる方法は実装も試験も容易であり，いろいろ試してもいいかもしれない。その場合，「頻出するopcodeパターン」を探すようなプロファイラをまず書く必要があるだろう。</p>
			<p>また，現状の最適化器は本格的なコンパイラが行うようなアグレッシブなコード書き換えは行っていないので，それを考慮すると試せることはまだ沢山あるように思う。</p>
		</div>
		<div class="footnote">
			<p class="footnote"><a href="/gfx/#fn1" name="f1">*1</a>：CORE::scalar()の実体</p>
			<p class="footnote"><a href="/gfx/#fn2" name="f2">*2</a>：sortの最適化については<a href="http://d.hatena.ne.jp/gfx/20090531/1243743871">Optimization of sort()</a>で解説済み</p>
		</div>
]]></content:encoded>
	<dc:creator>gfx</dc:creator>
	<dc:date>2010-02-05T13:36:37+09:00</dc:date>
	<dc:subject>Perl</dc:subject>
</item>
<item rdf:about="http://d.hatena.ne.jp/gfx/20100202/1265091606">
	<title>[Perl]XS基礎文法最速マスター</title>
	<link>http://d.hatena.ne.jp/gfx/20100202/1265091606</link>
	<description> 元ネタ：Perl基礎文法最速マスター(id:perlcodesample) XSを始めるための手順といくつかの要素の解説です。C言語をある程度知っている人でも，これを読んだだけでXSの基礎をマスターしてXSを書くことができるようにはなっていません。リファレンスでもありません。 XSとは，</description>

	<content:encoded><![CDATA[
		<div class="section">
			<p>元ネタ：<a href="http://d.hatena.ne.jp/perlcodesample/20091226/1264257759">Perl基礎文法最速マスター</a>(<a href="http://d.hatena.ne.jp/perlcodesample/">id:perlcodesample</a>)</p>
			<p>XSを始めるための手順といくつかの要素の解説です。C言語をある程度知っている人でも，これを読んだだけでXSの基礎をマスターしてXSを書くことができるようにはなっていません。リファレンスでもありません。</p>
			<p>XSとは，狭義ではPerlでエクステンションを書くためのマクロ言語の名前ですが，広義ではエクステンションを書くための技術の総称です。ここでは，広義のXSを俯瞰します。</p>
			<p>XSはいろいろと特殊なのでテンプレは無視で行きます。</p>
			<p>目次：</p>
			<ol>
				<li> h2xsで空のディストリビューションを作る</li>
				<li> XSファイルの構成</li>
				<li> スレッドコンテキスト</li>
				<li> SVファミリ</li>
				<li> GCとスコープ</li>
				<li> さらなる学習のために</li>
			</ol>
			<h4> h2xsで空のディストリビューションを作る</h4>
			<p>以下のコマンドで空のXSディストリビューションを作ることができます。</p>
<pre class="syntax-highlight">
h2xs <span class="synSpecial">-A</span> <span class="synSpecial">-b</span> <span class="synConstant">5</span>.<span class="synConstant">8</span>.<span class="synConstant">1</span> <span class="synSpecial">-n</span> Foo::Bar
</pre>

			<p>ディストリビューションを作るためのモジュールはModule::Starter, Module::Setupなどもありますが，最初はh2xsで十分でしょう。なによりインストールの必要がありません。</p>
			<p>ディストリビューションを作ったら，その中のディレクトリに移動してとりあえずビルドしてみます。</p>
<pre class="syntax-highlight">
<span class="synStatement">cd</span> Foo-Bar
perl Makefile.PL
make <span class="synStatement">&#38;&#38;</span> make <span class="synStatement">test</span>
</pre>

			<p>これがうまくいかなければコンパイラをセットアップする必要がありますが，省略します。WindowsならStrawberry PerlやCygwinを使うのがお勧めです。</p>
			<p>次の節に進む前に，XSファイルの先頭，Perlのヘッダファイルをインクルードする前に，<code>"#define PERL_NO_GET_CONTEXT"</code>という行を追加しておきましょう。これはスレッドコンテキストと関係があるのですが，とりあえずオマジナイと考えてかまいません。また，XSセクションには<code>"PROTOTYPES: DISABLE"</code>という行を加えておきましょう。この行がないとXSUBに自動的にプロトタイプがついてしまい，予想外の挙動を招くことになります。</p>
			<h4> XSファイルの構成</h4>
			<p>一つのXSファイルはCセクションとXSセクションに分かれています。CセクションはC言語そのもので，モジュールのユーザーからは見えません。XSセクションでXSUBを書き，これはモジュールのユーザーから見えます。</p>
			<p>たとえば，以下のようになります。</p>
<pre class="syntax-highlight">
<span class="synPreProc">#define PERL_NO_GET_CONTEXT</span>
<span class="synPreProc">#include </span><span class="synConstant">&#34;EXTERN.h&#34;</span>
<span class="synPreProc">#include </span><span class="synConstant">&#34;perl.h&#34;</span>
<span class="synPreProc">#include </span><span class="synConstant">&#34;XSUB.h&#34;</span>

<span class="synPreProc">#include </span><span class="synConstant">&#34;ppport.h&#34;</span>

=pod

C section

=cut

<span class="synStatement">MODULE</span> = Foo::Bar		<span class="synStatement">PACKAGE</span> = Foo::Bar	

<span class="synStatement">PROTOTYPES</span>: DISABLE	

=pod

XS section

=cut

<span class="synType">void</span>
hello()
<span class="synStatement">CODE</span>:
{
    PerlIO_stdoutf(<span class="synConstant">&#34;Hello, world!</span><span class="synSpecial">\n</span><span class="synConstant">&#34;</span>);
}
</pre>

			<p>これは，以下のコマンドで実行できます。</p>
<pre class="syntax-highlight">
make
perl <span class="synSpecial">-Mblib</span> <span class="synSpecial">-MFoo</span>::Bar <span class="synSpecial">-e</span> <span class="synStatement">'</span><span class="synConstant">Foo::Bar::hello()</span><span class="synStatement">'</span>
</pre>

			<p>なお，上の例が示すように，セクションにかかわらず任意の場所にPODを書くことができます<span class="footnote"><a href="/gfx/#f1" name="fn1" title="使っている例を見たことはありませんが！">*1</a></span>。</p>
			<h4> スレッドコンテキスト</h4>
			<p>Cセクションにいろいろ書くつもりがなければ，この節の内容は特に必要ありません。</p>
			<p>スレッドコンテキストとは，Perlインタプリタレベルでのグローバル変数を持っている構造体で，ほとんどすべてのPerlAPIの最初の引数として渡すものです。ただし，ほとんどすべてのPerlAPIは，このことを意識しなくてすむようにマクロでラップしてあります。</p>
			<p>このことを意識しなければならないのは，Cセクションに関数を書くときです。</p>
			<p>このとき，自分の関数についても，PerlAPI と同じように最初の引数にスレッドコンテキスト渡すようにしないと，その関数の内部でPerlAPIが使えません。</p>
			<p>スレッドコンテキストの宣言にはpTHX<span class="footnote"><a href="/gfx/#f2" name="fn2" title="唯一の引数として">*2</a></span>/pTHX_<span class="footnote"><a href="/gfx/#f3" name="fn3" title="数ある引数の中の最初のものとして。アンダーバーはカンマに置き換えられると考えてよい。">*3</a></span>を使います。API の呼出には aTHX/aTHX_ を使います。</p>
<pre class="syntax-highlight">
<span class="synComment">/* in C section */</span>
<span class="synType">static</span> <span class="synType">void</span>
hello(pTHX) {
    PerlIO_stdoutf(<span class="synConstant">&#34;Hello, world!</span><span class="synSpecial">\n</span><span class="synConstant">&#34;</span>);
}

<span class="synComment">/* IV: Integer Value */</span>
<span class="synType">static</span> <span class="synType">void</span>
increment(pTHX_ <span class="synPreProc">SV</span>* <span class="synType">const</span> sv) {
    sv_inc(sv); <span class="synComment">/* 実際には Perl_sv_inc(aTHX_ sv) に展開される */</span>
}

<span class="synStatement">MODULE</span> = Foo::Bar		<span class="synStatement">PACKAGE</span> = Foo::Bar	

<span class="synType">void</span>
hello()
<span class="synStatement">CODE</span>:
{
    hello(aTHX);
}

<span class="synType">void</span>
increment(<span class="synPreProc">SV</span>* sv)
<span class="synStatement">CODE</span>:
{
    increment(aTHX_ sv);
}
</pre>

			<p>特定のプロトタイプが必要なコールバックなどではスレッドコンテキストを受け取れないことがありますが，その場合は関数の最初で <code>dTHX;</code> 宣言をすることにより，スレッドコンテキストを定義することができます。</p>
			<h4> SVファミリ</h4>
			<p>Perlのデータは，CレベルではSV*(スカラー)，AV*(配列)，HV*(ハッシュ)などで表現されますが，これらすべてはSV*の派生クラスと考えられます。つまり，SvTYPE() や SvREFCNT_inc()/SvREFCNT_dec() などのAPIは，その引数としてどのSVファミリでも受け取れるようになっています。以後，単にSVと書くときは，SVファミリのことと考えてください。</p>
			<p>SVファミリを操作するためのAPIの数は多いので紹介はしませんが，一般に，スカラー値であれば sv_<span class="footnote"><a href="/gfx/#f4" name="fn4" title="関数の場合">*4</a></span>/Sv<span class="footnote"><a href="/gfx/#f5" name="fn5" title="マクロの場合">*5</a></span> というプレフィクスを持ち，同様に配列では av_/Av，ハッシュでは hv_/Hv というプレフィクスを持つので，ソースコードを読むときには頭に入れておくといいでしょう。</p>
			<p>なお，SVファミリの具体的な挙動については，<a href="http://perldoc.jp/docs/perl/5.10.0/perlapi.pod">perldoc perlapi</a>を参照してください。</p>
			<h4> GCとスコープ</h4>
			<p>Perlはリファレンスカウントベースのガベージコレクション機構を持っています。また，スコープと揮発性(mortality)という概念で，XSレベルでもリファレンスカウントの管理を自動化できるようになっています。</p>
			<p>XSにおけるスコープは，Perlレベルでのスコープと同じです。これは，<code>ENTER; SAVETMPS;</code> というマクロで開き，<code>FREETMPS; LEAVE;</code> というマクロで閉じます<span class="footnote"><a href="/gfx/#f6" name="fn6" title="なぜそれぞれ二つのマクロが必要なのかについてはきちんとした理由があるのですが，込み入った話になるので省略します。とにかく，ENTERとSAVETMPSのどちらも必要なのです。">*6</a></span>。</p>
			<p>そして，このスコープの中であるSVを揮発性にすると，そのSVのリファレンスカウントは，そのスコープを抜けるときに一つ減ります<span class="footnote"><a href="/gfx/#f7" name="fn7" title="そして，リファレンスカウントが0になると当然解放されます">*7</a></span>。この処理はスコープの中で例外が起きたときでもきちんと行われるので，手動でリファレンスカウントを減らすよりも安全です。SVを揮発性にするには，sv_2mortal()を使います。初めから揮発性のSVがほしいときは，sv_newmortal()が，SVの揮発性コピーがほしいときはsv_mortalcopy()を使います。</p>
<pre class="syntax-highlight">
<span class="synComment">/* in C section */</span>
<span class="synType">static</span> <span class="synType">void</span>
foo(pTHX) {
    <span class="synPreProc">SV</span>* sv;
    ENTER;
    SAVETMPS;

    sv = sv_newmortal();
    sv_setpvs(sv, <span class="synConstant">&#34;Hello, world!</span><span class="synSpecial">\n</span><span class="synConstant">&#34;</span>);
    PerlIO_stdoutf(<span class="synConstant">&#34;%&#34;</span>SVf, sv); <span class="synComment">/* -&#62; &#34;Hello, world!&#34; */</span>

    FREETMPS;
    LEAVE;
    <span class="synComment">/* ここでsvはすでに解放されている */</span>
}
</pre>

			<p>SvREFCNT_inc()とSvREFCNT_dec()でリファレンスカウントを手動で操作することもできますが，慣れないうちは手動で操作する代わりにsv_mortalcopy()とスコープメカニズムを使ったほうが安全です。</p>
			<p>なお，すべてのXSUBは呼び出されるときにスコープで囲まれます。また，XSUBからの戻り値は揮発性のSVでなければならないという呼出規約があります<span class="footnote"><a href="/gfx/#f8" name="fn8" title="正確には違います。Perlは引数スタックのSVのリファレンスカウントには触らないのです。したがって，作ったSVをそのままスタックに置いておくと，そのSVは解放されません。">*8</a></span>。したがって，XSUBからSVを直接返す時は，必ずsv_2mortal()で揮発性にしましょう。</p>
			<p>sv_2mortal()を掛けすぎると，Perlインタプリタが「不正にSVの解放が行われた」と文句を言ってくれますが，メモリリークについてはインタプリタは文句を言いません。したがって，不安だったらsv_2mortal()するように習慣づけておくと安全です。</p>
			<h4> さらなる学習のために</h4>
			<p>以上，XSを俯瞰しましたが，実際にXSを一から書くのは大変です。いくつかのXSモジュールを実際に読んでみたり，改造してみたり<span class="footnote"><a href="/gfx/#f9" name="fn9" title="「このSVにsv_2mortal()を掛けるとどうなるだろう？」">*9</a></span>することをお勧めします。</p>
			<p><a href="http://search.cpan.org/dist/Scalar-List-Utils/">Scalar-List-Utils</a>のXSセクションは比較的理解しやすいのではないかと思います<span class="footnote"><a href="/gfx/#f10" name="fn10" title="Cセクションはすべてバージョン間の差異を吸収するための#ifdefです。">*10</a></span>。</p>
			<p>また，Perl自身のソースコードは，その時の最新の PerlAPI <span class="footnote"><a href="/gfx/#f11" name="fn11" title="古いスタイルのPerlAPIを知る必要はほとんどありません。ppport.hというヘッダファイルを使うことにより，古いバージョンのperlでも最新のPerlAPIを使うことができるからです。">*11</a></span>に則って書かれているため，最良の教科書です。sv.c，av.c，pp_hot.c，universal.c は比較的読みやすく，重要性も高いのでお勧めです。細かな挙動について知るためにはPerlのソースコードを参照するしかないことも少なくなく，XSを書くならPerlソースコードを手元に置いておくのは必須といえます。</p>
			<p>See also:</p>
			<ul>
				<li> <a href="http://perldoc.perl.org/perlxstut.html">perlxstut</a>(<a href="http://perldoc.jp/docs/perl/5.10.0/perlxstut.pod">ja</a>) - XS のチュートリアル</li>
				<li> <a href="http://perldoc.perl.org/perlxs.html">perlxs</a>(<a href="http://perldoc.jp/docs/perl/5.10.0/perlxs.pod">ja</a>) - XS のリファレンス</li>
				<li> <a href="http://perldoc.perl.org/perlapi.html">perlapi</a>(<a href="http://perldoc.jp/docs/perl/5.10.0/perlapi.pod">ja</a>) - PerlAPI のリファレンス</li>
				<li> <a href="http://perldoc.perl.org/perlguts.html">perlguts</a> - Perl の内部構造(データ編)</li>
				<li> <a href="http://perldoc.perl.org/perlhack.html">perlhack</a> - Perl の内部構造(インタプリタ編)</li>
				<li> <a href="http://perldoc.perl.org/perlclib.html">perlclib</a> - Cライブラリの代替API</li>
			</ul>
			<p>Enjoy XS!</p>
		</div>
		<div class="footnote">
			<p class="footnote"><a href="/gfx/#fn1" name="f1">*1</a>：使っている例を見たことはありませんが！</p>
			<p class="footnote"><a href="/gfx/#fn2" name="f2">*2</a>：唯一の引数として</p>
			<p class="footnote"><a href="/gfx/#fn3" name="f3">*3</a>：数ある引数の中の最初のものとして。アンダーバーはカンマに置き換えられると考えてよい。</p>
			<p class="footnote"><a href="/gfx/#fn4" name="f4">*4</a>：関数の場合</p>
			<p class="footnote"><a href="/gfx/#fn5" name="f5">*5</a>：マクロの場合</p>
			<p class="footnote"><a href="/gfx/#fn6" name="f6">*6</a>：なぜそれぞれ二つのマクロが必要なのかについてはきちんとした理由があるのですが，込み入った話になるので省略します。とにかく，ENTERとSAVETMPSのどちらも必要なのです。</p>
			<p class="footnote"><a href="/gfx/#fn7" name="f7">*7</a>：そして，リファレンスカウントが0になると当然解放されます</p>
			<p class="footnote"><a href="/gfx/#fn8" name="f8">*8</a>：正確には違います。Perlは引数スタックのSVのリファレンスカウントには触らないのです。したがって，作ったSVをそのままスタックに置いておくと，そのSVは解放されません。</p>
			<p class="footnote"><a href="/gfx/#fn9" name="f9">*9</a>：「このSVにsv_2mortal()を掛けるとどうなるだろう？」</p>
			<p class="footnote"><a href="/gfx/#fn10" name="f10">*10</a>：Cセクションはすべてバージョン間の差異を吸収するための#ifdefです。</p>
			<p class="footnote"><a href="/gfx/#fn11" name="f11">*11</a>：古いスタイルのPerlAPIを知る必要はほとんどありません。ppport.hというヘッダファイルを使うことにより，古いバージョンのperlでも最新のPerlAPIを使うことができるからです。</p>
		</div>
]]></content:encoded>
	<dc:creator>gfx</dc:creator>
	<dc:date>2010-02-02T15:20:06+09:00</dc:date>
	<dc:subject>Perl</dc:subject>
</item>
<item rdf:about="http://d.hatena.ne.jp/gfx/20100201/1265026337">
	<title>Re: プログラミングについての雑記</title>
	<link>http://d.hatena.ne.jp/gfx/20100201/1265026337</link>
	<description> プログラミングについての雑記(id:perlcodesample) プログラミングが上達するコツは簡単なプログラミングをできるだけたくさん書いて実行することです。本やインターネットを読むだけではプログラミングは上達しません。読むのは3割、書くのが7割ぐらいになるとちょうど良い</description>

	<content:encoded><![CDATA[
		<div class="section">
			<p><a href="http://d.hatena.ne.jp/perlcodesample/20100108/1264941583">プログラミングについての雑記</a>(<a href="http://d.hatena.ne.jp/perlcodesample/">id:perlcodesample</a>)</p>
			<blockquote>
			<p>プログラミングが上達するコツは簡単なプログラミングをできるだけたくさん書いて実行することです。本やインターネットを読むだけではプログラミングは上達しません。読むのは3割、書くのが7割ぐらいになるとちょうど良いのではないかと思います。もしプログラムの意味がわからない場合は丸写ししてプログラムの動きをみてください。たくさん書いているうちに次第にわかってくるようになります。</p>
			</blockquote>
			<p>前半には異論はありません。しかし，意味がわからないまま丸写しすること，いわゆる「写経」は一般に薦められてますが，私はあまり効果がないんじゃないかと思ってます。というより，面白くないから続かないんじゃないでしょうか。しかも，何も新しいことを生み出さないじゃないですか，写経って。しかも，最近の書籍だと大抵実行可能なサンプルコードが付いてますから，写経が終わっても達成感がありません。</p>
			<p>私はむしろ，あるコードを別の言語の等価コードに移植することが上達への近道だと思っています。元のコードの言語に精通している必要は必ずしもなく，移植先の言語とともに初心者レベルで構いません。いずれにせよ，移植するためにはコードの中身を理解する必要に迫られますから。移植は写経よりも面白い，というのもいいですね。</p>
			<p>アルゴリズムのテキストから好きなアルゴリズムを選び，それを学習したい言語で実装する，というのも同じパターンです。</p>
		</div>
]]></content:encoded>
	<dc:creator>gfx</dc:creator>
	<dc:date>2010-02-01T21:12:17+09:00</dc:date>
</item>
<item rdf:about="http://d.hatena.ne.jp/gfx/20100126/1264474754">
	<title>The difference of ”return;” and ”return undef;” </title>
	<link>http://d.hatena.ne.jp/gfx/20100126/1264474754</link>
	<description> ”Perl Best Practices” recommends to use ”return;”*1 to return nothing, but it might be wrong in some cases. If you use this idiom for those functions which are expected to return a scalar value, e.g. searching functions, the user of those functions will </description>

	<content:encoded><![CDATA[
		<div class="section">
			<p>"Perl Best Practices" recommends to use "return;"<span class="footnote"><a href="/gfx/#f1" name="fn1" title="it returns an empty list in list context, or returns undef in scalar context">*1</a></span> to return nothing, but it might be wrong in some cases. If you use this idiom for those functions which are expected to return a scalar value, e.g. searching functions, the user of those functions will be surprised at what they return in list context, an empty list - note that many functions and all the methods evaluate their arguments in list context. You'd better to use "return undef;" for such scalar functions.</p>
			<p>『Perlベストプラクティス』は名著だが，中には奨励できないプラクティスもある。「無効値を示すためには"return;"を使用せよ」というのもその一つだ。"return;"を使うと，そのサブルーチンはリストコンテキストでは空リストを返すのだが，下記のコードのように，スカラーを返すべきサブルーチンで空リストを返すと予想外の振る舞いをとることがある。このようなことを避けるため，スカラー値を返すべきサブルーチンでは，"return;"ではなく"return undef;"を使ったほうがよい。</p>
<pre class="syntax-highlight">
<span class="synStatement">sub</span><span class="synIdentifier"> search_something </span>{
    <span class="synStatement">my</span>(<span class="synIdentifier">$arg</span>) = <span class="synIdentifier">@_</span>;
    <span class="synComment"># search_something...</span>
    <span class="synStatement">if</span>(<span class="synStatement">defined</span> <span class="synIdentifier">$found</span>){
        <span class="synStatement">return</span> <span class="synIdentifier">$found</span>;
    }
    <span class="synStatement">return</span>; <span class="synComment"># </span><span class="synTodo">XXX</span><span class="synComment">: you'd better to &#34;return undef;&#34;</span>
}

<span class="synComment"># ...</span>

<span class="synComment"># you'll get what you want, but ...</span>
<span class="synStatement">my</span> <span class="synIdentifier">$something</span> = search_something(<span class="synIdentifier">$source</span>);

<span class="synComment"># you won't get what you want here.</span>
<span class="synComment"># @_ for doit() is (-foo =&#62; $opt), not (undef, -foo =&#62; $opt).</span>
<span class="synIdentifier">$obj</span>-&#62;doit(search_something(<span class="synIdentifier">$source</span>), -<span class="synConstant">option</span>=&#62; <span class="synIdentifier">$optval</span>);

<span class="synComment"># you have to use the &#34;scalar&#34; operator in such a case.</span>
<span class="synIdentifier">$obj</span>-&#62;doit(<span class="synStatement">scalar</span> search_something(<span class="synIdentifier">$source</span>), ...);
</pre>

		</div>
		<div class="footnote">
			<p class="footnote"><a href="/gfx/#fn1" name="f1">*1</a>：it returns an empty list in list context, or returns undef in scalar context</p>
		</div>
]]></content:encoded>
	<dc:creator>gfx</dc:creator>
	<dc:date>2010-01-26T11:59:14+09:00</dc:date>
</item>
</rdf:RDF>
