blog/content/post/2008-08-31-00001016.md

187 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
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">&#62;</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', '高階関数 &#8211; Wikipedia');" target="_blank">高階関数 &#8211; 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さんにコメントいただいた &#8211; 武蔵の日記');" target="_blank"> Lispの引数についてid:SaitoAtsushiさんにコメントいただいた &#8211; 武蔵の日記</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', ' 手続き中の引数の書き方がわからないかもしれない &#8211; 武蔵の日記');" target="_blank"> 手続き中の引数の書き方がわからないかもしれない &#8211; 武蔵の日記</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>