187 lines
6.5 KiB
Markdown
187 lines
6.5 KiB
Markdown
|
---
|
|||
|
title: もう一度第七章をはじめから
|
|||
|
author: kazu634
|
|||
|
date: 2008-08-31
|
|||
|
url: /2008/08/31/_1092/
|
|||
|
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:4247;}s:9:"hash_tags";a:0:{}s:8:"accounts";a:1:{i:0;s:7:"kazu634";}}'
|
|||
|
categories:
|
|||
|
- gauche
|
|||
|
- Lisp
|
|||
|
|
|||
|
---
|
|||
|
<div class="section">
|
|||
|
<blockquote>
|
|||
|
<p>
|
|||
|
「手続き」は、数値、文字列、真偽値と同様、「値」として他の変数に束縛したり、引数として他の手続きに渡したり、他の手続きの戻り値として返したりできます。
|
|||
|
</p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<p>
|
|||
|
ここらへんはややトリッキーだけど、Cとかでも関数ポインタとかあったはず。Javaとかだと、オブジェクト型を渡していたりするから、そこらへんと同じ感じなんだろう…と思う。
|
|||
|
</p>
|
|||
|
|
|||
|
<h4>
|
|||
|
foldってトリッキー
|
|||
|
</h4>
|
|||
|
|
|||
|
<pre class="syntax-highlight">
|
|||
|
<span class="synSpecial">(</span>define <span class="synSpecial">(</span>print_element lis<span class="synSpecial">)</span>
|
|||
|
<span class="synSpecial">(</span>fold <span class="synSpecial">(</span><span class="synStatement">lambda</span> <span class="synSpecial">(</span>a b<span class="synSpecial">)</span> <span class="synSpecial">(</span><span class="synStatement">print</span> a<span class="synSpecial">))</span> #f lis<span class="synSpecial">))</span>
|
|||
|
</pre>
|
|||
|
|
|||
|
<p>
|
|||
|
foldは順番にlisを処理する。ちなみに「(lambda (a b) (print a)」という無名関数への引数は順番に次のようになるよ(lisが「(1 2 3 4 5)」の場合):
|
|||
|
</p>
|
|||
|
|
|||
|
<table>
|
|||
|
<tr>
|
|||
|
<th>
|
|||
|
第一引数
|
|||
|
</th>
|
|||
|
|
|||
|
<th>
|
|||
|
第二引数
|
|||
|
</th>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td>
|
|||
|
1
|
|||
|
</td>
|
|||
|
|
|||
|
<td>
|
|||
|
#f
|
|||
|
</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td>
|
|||
|
2
|
|||
|
</td>
|
|||
|
|
|||
|
<td>
|
|||
|
1
|
|||
|
</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td>
|
|||
|
3
|
|||
|
</td>
|
|||
|
|
|||
|
<td>
|
|||
|
2
|
|||
|
</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td>
|
|||
|
4
|
|||
|
</td>
|
|||
|
|
|||
|
<td>
|
|||
|
3
|
|||
|
</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td>
|
|||
|
5
|
|||
|
</td>
|
|||
|
|
|||
|
<td>
|
|||
|
4
|
|||
|
</td>
|
|||
|
</tr>
|
|||
|
</table>
|
|||
|
|
|||
|
<p>
|
|||
|
となることに注意。なんか自分の直感に反している。
|
|||
|
</p>
|
|||
|
|
|||
|
<h4>
|
|||
|
ようやく自分が何が理解できていないのかわかった!
|
|||
|
</h4>
|
|||
|
|
|||
|
<p>
|
|||
|
「高階手続き」がわかっていないんだ!これをキーワードに勉強していこう!
|
|||
|
</p>
|
|||
|
|
|||
|
<h4>
|
|||
|
高階手続き(Wikipediaから)
|
|||
|
</h4>
|
|||
|
|
|||
|
<blockquote title="高階関数 - Wikipedia" cite="http://ja.wikipedia.org/wiki/%E9%AB%98%E9%9A%8E%E9%96%A2%E6%95%B0">
|
|||
|
<p>
|
|||
|
関数を戻り値とする関数
|
|||
|
</p>
|
|||
|
|
|||
|
<pre class="syntax-highlight">
|
|||
|
<span class="synSpecial">(</span>define <span class="synSpecial">(</span>add x y<span class="synSpecial">)</span>
|
|||
|
<span class="synSpecial">(</span><span class="synStatement">+</span> x y<span class="synSpecial">))</span><span class="synError">))</span>
|
|||
|
</pre>
|
|||
|
|
|||
|
<p>
|
|||
|
このaddを次のように書き直す
|
|||
|
</p>
|
|||
|
|
|||
|
<pre class="syntax-highlight">
|
|||
|
<span class="synSpecial">(</span>define <span class="synSpecial">(</span>add x<span class="synSpecial">)</span>
|
|||
|
<span class="synSpecial">(</span><span class="synStatement">lambda</span> <span class="synSpecial">(</span>y<span class="synSpecial">)</span> <span class="synSpecial">(</span><span class="synStatement">+</span> x y<span class="synSpecial">)))</span>
|
|||
|
</pre>
|
|||
|
|
|||
|
<p>
|
|||
|
これを使って加算をするには、次のように書く。
|
|||
|
</p>
|
|||
|
|
|||
|
<pre class="syntax-highlight">
|
|||
|
<span class="synStatement">></span> <span class="synSpecial">((</span>add <span class="synConstant">2</span><span class="synSpecial">)</span> <span class="synConstant">3</span><span class="synSpecial">)</span>
|
|||
|
<span class="synConstant">5</span>
|
|||
|
</pre>
|
|||
|
|
|||
|
<p>
|
|||
|
ここで、まず(add 2)の戻り値は1つ引数をとって2を足す関数になる。そして、戻り値として返ってきた関数に、更に3を渡して最終的な計算結果を得ている。つまり、add自身は関数を戻り値とする高階関数となっている。 上記のような、n引数ある関数を、1引数だけの高階関数に変換する操作をカリー化と呼ぶ。
|
|||
|
</p>
|
|||
|
|
|||
|
<p>
|
|||
|
<cite><a href="http://ja.wikipedia.org/wiki/%E9%AB%98%E9%9A%8E%E9%96%A2%E6%95%B0" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://ja.wikipedia.org/wiki/%E9%AB%98%E9%9A%8E%E9%96%A2%E6%95%B0', '高階関数 – Wikipedia');" target="_blank">高階関数 – Wikipedia</a></cite>
|
|||
|
</p>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<p>
|
|||
|
なんかよくわからなかったんだけど、わかった瞬間がきた!
|
|||
|
</p>
|
|||
|
|
|||
|
<h4>
|
|||
|
つまり
|
|||
|
</h4>
|
|||
|
|
|||
|
<pre class="syntax-highlight">
|
|||
|
<span class="synSpecial">(</span>define <span class="synSpecial">(</span>reversed walker<span class="synSpecial">)</span>
|
|||
|
<span class="synSpecial">(</span><span class="synStatement">lambda</span> <span class="synSpecial">(</span>proc lis<span class="synSpecial">)</span>
|
|||
|
<span class="synSpecial">(</span>walker proc <span class="synSpecial">(</span><span class="synStatement">reverse</span> lis<span class="synSpecial">))))</span>
|
|||
|
</pre>
|
|||
|
|
|||
|
<p>
|
|||
|
のreversedという手続きは「一つ引数をとって、戻り値として二つの引数をとる手続きを返す」ってことなんだ!(間違えてない…はず。大丈夫だよね。。。)
|
|||
|
</p>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
「gauche」に関連する最近のエントリ <ul>
|
|||
|
<li>
|
|||
|
<a href="http://d.hatena.ne.jp/sirocco634/20080830/1220052100" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://d.hatena.ne.jp/sirocco634/20080830/1220052100', ' Lispの引数について(id:SaitoAtsushiさんにコメントいただいた) – 武蔵の日記');" target="_blank"> Lispの引数について(id:SaitoAtsushiさんにコメントいただいた) – 武蔵の日記</a>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<a href="http://d.hatena.ne.jp/sirocco634/20080828/1219931251" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://d.hatena.ne.jp/sirocco634/20080828/1219931251', ' 手続き中の引数の書き方がわからないかもしれない – 武蔵の日記');" target="_blank"> 手続き中の引数の書き方がわからないかもしれない – 武蔵の日記</a>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<a href="http://d.hatena.ne.jp/sirocco634/20080825/1205475020" onclick="__gaTracker('send', 'event', 'outbound-article', 'http://d.hatena.ne.jp/sirocco634/20080825/1205475020', '武蔵の日記');" target="_blank">武蔵の日記</a>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
</blockquote>
|
|||
|
</div>
|