<?xml version="1.0" encoding="UTF-8" ?>
<feed xml:lang="ja" xmlns="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:thr="http://purl.org/syndication/thread/1.0">
  <title type="text">管理人「まめ」の雑記ブログ</title>
  <subtitle type="html"></subtitle>
  <link rel="self" type="application/atom+xml" href="https://mame123.blog.shinobi.jp/atom"/>
  <link rel="alternate" type="text/html" href="https://mame123.blog.shinobi.jp/"/>
  <updated>2018-10-23T23:12:02+09:00</updated>
  <author><name>まめ</name></author>
  <generator uri="//www.ninja.co.jp/blog/" version="0.9">忍者ブログ</generator>
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" />
  <entry>
    <id>mame123.blog.shinobi.jp://entry/15</id>
    <link rel="alternate" type="text/html" href="https://mame123.blog.shinobi.jp/%E6%9C%AA%E9%81%B8%E6%8A%9E/20240717_tyou-seirihou" />
    <published>2024-07-17T05:45:38+09:00</published> 
    <updated>2024-07-17T05:45:38+09:00</updated> 
    <category term="未選択" label="未選択" />
    <title>「超」整理法を5年以上続けてきて気がついたこと</title>
    <content mode="escaped" type="text/html" xml:lang="utf-8"> 
      <![CDATA[<p>2024年7月17日</p>
<h2>*</h2>
<p>私は、自分の私的な[紙の書類]や[PC のファイル]を、<a href="https://www.chuko.co.jp/shinsho/1993/11/101159.html" title="">『「超」整理法』（野口悠紀雄、中公新書）</a>で紹介されている「押し出しファイリング」方式で管理している。このやり方を始めてもう5年以上になる。とても優れた方式だと感じる。</p>
<p>だが、最近この「超」整理法に関して、気がついたことがある。約1ヶ月以内に使った情報は、最終利用日がいつごろだったか自分の記憶に強く残っている。一方、何ヶ月も使っていない情報は、最終利用日よりも作成日のほうが、自分の記憶に強く残っているようだ。</p>
<p>そこで、こんなことを思いついた。自分が管理したい情報をまず「最近使ったもの」とそれ以外のもの（「書庫」と呼ぶことにしようか）に、大雑把に分ける。そして、「最近使ったもの」は、オリジナルの「超」整理法と同様に、最終利用日の順に並べる。一方「書庫」のほうは、（最終利用日ではなく）作成日の順にソート（整列）して配置する。</p>
<p>&hellip;&hellip;こうすれば、最近使った情報を取り出すときも、長い間使っていない情報を引っ張り出してこなければならないときも、[検索速度、アクセス速度]がもっと速くなるかもしれないなと&hellip;&hellip;。</p>]]> 
    </content>
    <author>
            <name>まめ</name>
        </author>
  </entry>
  <entry>
    <id>mame123.blog.shinobi.jp://entry/14</id>
    <link rel="alternate" type="text/html" href="https://mame123.blog.shinobi.jp/%E6%9C%AA%E9%81%B8%E6%8A%9E/20200426_processing-migu-1m" />
    <published>2020-04-26T21:23:29+09:00</published> 
    <updated>2020-04-26T21:23:29+09:00</updated> 
    <category term="未選択" label="未選択" />
    <title>Processing のエディターとコンソールのフォントを「Migu 1M」に変えてみた</title>
    <content mode="escaped" type="text/html" xml:lang="utf-8"> 
      <![CDATA[<p>2020年4月26日</p>
<h2>概要</h2>
<p><a href="https://processing.org/">Processing</a> 3.5.3 のエディターとコンソールのフォントを、プログラミングに適したフォント「<a href="https://mix-mplus-ipa.osdn.jp/migu/">Migu 1M</a>」に変更してみました。</p>
<p>この作業にかなり手こずったので、作業内容をここに書き留めておきます。</p><br /><br /><a href="https://mame123.blog.shinobi.jp/%E6%9C%AA%E9%81%B8%E6%8A%9E/20200426_processing-migu-1m" target="_blank">つづきはこちら</a>]]> 
    </content>
    <author>
            <name>まめ</name>
        </author>
  </entry>
  <entry>
    <id>mame123.blog.shinobi.jp://entry/13</id>
    <link rel="alternate" type="text/html" href="https://mame123.blog.shinobi.jp/%E6%9C%AA%E9%81%B8%E6%8A%9E/20200307_bouhuri-volume-8" />
    <published>2020-03-07T02:44:04+09:00</published> 
    <updated>2020-03-07T02:44:04+09:00</updated> 
    <category term="未選択" label="未選択" />
    <title>「防振り」8巻が書店の店頭に並んでいました</title>
    <content mode="escaped" type="text/html" xml:lang="utf-8"> 
      <![CDATA[<p>2020年3月7日</p>
<h2>*</h2>
<p>先日書店へ行ったところ、ライト・ノベル『痛いのは嫌なので防御力に極振りしたいと思います。』（略称: 防振り）の最新8巻が店頭に並んでいました。</p>
<p>この作品、私は以前1巻だけ買ったことがあり持っているのですが、この作品は2020年1月から TV アニメの放送が始まったらしいですね。知りませんでした。</p>
<ul>
<li><a href="https://kadokawabooks.jp/special/itainohaiya/"> 『痛いのは嫌なので防御力に極振りしたいと思います。』特設サイト | カドカワBOOKS<br />
https://kadokawabooks.jp/special/itainohaiya/ </a></li>
<li><a href="https://bofuri.jp/"> TVアニメ「痛いのは嫌なので防御力に極振りしたいと思います。」公式サイト<br />
https://bofuri.jp/ </a></li>
</ul>
<p>以下、最新8巻をちらっと立ち読みして思ったこと。（ネタバレあるかも）</p>
<p>&darr;</p>
<hr /><br /><br /><a href="https://mame123.blog.shinobi.jp/%E6%9C%AA%E9%81%B8%E6%8A%9E/20200307_bouhuri-volume-8" target="_blank">つづきはこちら</a>]]> 
    </content>
    <author>
            <name>まめ</name>
        </author>
  </entry>
  <entry>
    <id>mame123.blog.shinobi.jp://entry/12</id>
    <link rel="alternate" type="text/html" href="https://mame123.blog.shinobi.jp/%E6%9C%AA%E9%81%B8%E6%8A%9E/20191108_merc-storia" />
    <published>2019-11-08T22:27:43+09:00</published> 
    <updated>2019-11-08T22:27:43+09:00</updated> 
    <category term="未選択" label="未選択" />
    <title>TV アニメ『メルクストーリア』第4話の感想</title>
    <content mode="escaped" type="text/html" xml:lang="utf-8"> 
      <![CDATA[<p>2019年11月8日</p>
<p>最近、<a href="http://www.mercstoria.jp/">TV アニメ『メルクストーリア』</a>を知人から勧められたので少しずつ見ています。</p>
<p><a href="http://www.mercstoria.jp/"> TVアニメ「メルクストーリア」公式サイト<br />
http://www.mercstoria.jp/ </a></p>
<p>11月2日に、第4話を見ました。</p>
<p>以下、第4話の感想！ （ネタバレあるかも）<br />
&darr;</p><br /><br /><a href="https://mame123.blog.shinobi.jp/%E6%9C%AA%E9%81%B8%E6%8A%9E/20191108_merc-storia" target="_blank">つづきはこちら</a>]]> 
    </content>
    <author>
            <name>まめ</name>
        </author>
  </entry>
  <entry>
    <id>mame123.blog.shinobi.jp://entry/11</id>
    <link rel="alternate" type="text/html" href="https://mame123.blog.shinobi.jp/%E6%9C%AA%E9%81%B8%E6%8A%9E/20191023_build-your-own-lisp" />
    <published>2019-10-23T19:48:57+09:00</published> 
    <updated>2019-10-23T19:48:57+09:00</updated> 
    <category term="未選択" label="未選択" />
    <title>Build Your Own Lisp、Chapter 11 の勉強ノート</title>
    <content mode="escaped" type="text/html" xml:lang="utf-8"> 
      <![CDATA[<p>2019年10月23日</p>
<h2>概要</h2>
<p>C 言語を使って Lisp のインタプリターを作る講座「<a href="http://buildyourownlisp.com/">Build Your Own Lisp</a>」の <a href="http://buildyourownlisp.com/chapter11_variables">Chapter 11</a> の勉強ノート。</p>
<h2>関連記事</h2>
<p>Chapter 1 から Chapter 10 までの勉強ノートはこちら。<br />
<a href="http://mame123.blog.shinobi.jp/未選択/20191022_build-your-own-lisp">Build Your Own Lisp、Chapter 10 までの勉強ノート</a> （2019年10月22日）</p>
<hr />
<h2>Chapter 11</h2>
<p><a href="http://buildyourownlisp.com/chapter11_variables">Chapter 11</a> を読んだ。</p>
<p>この章では、シンボルに別の値やビルトイン関数を割り当てる（定義する）機能を実装する。<br />
そのために、lval 構造体型で関数を表せるよう改良する。<br />
また、lenv 構造体型（Lisp Environment、環境）というものを新たに作る。</p>
<p>この章ではさらに、エラー・レポーティング（エラー・メッセージにどのような情報を表示するか）の機能を強化する。</p>
<h3>Immutability</h3>
<p>この章でやることの概要が書かれている。</p>
<h3>Symbol Syntax</h3>
<p>パーザー（構文解析器）の symbol ルールを変更する。</p>
<h3>Function Pointers</h3>
<p>C 言語の関数ポインターについて簡単に紹介されている。<br />
関数ポインターについて詳しく学びたければ、別の資料をあたったほうが良いかも。</p>
<p>関数ポインターを使って、lbuiltin という新しい型を定義する。</p>
<h3>Cyclic Types</h3>
<p>cyclic type dependency（循環型依存、型の定義が循環参照を形成すること）は、forward declaration（プロトタイプ宣言）によって解決できるという旨が書かれている。</p>
<p>lval 構造体型の定義を改良して、lval 構造体型で関数（ビルトイン関数）を表せるようにする。</p>
<h3>Function Type</h3>
<p>前節で lval 構造体で関数を表せるように改良したのに伴い、<br />
lval 構造体のユーティリティ関数を、関数を表す lval 構造体変数を扱えるよう改良する。</p>
<p>lval 型の構造体変数をコピーする関数 lval_copy() を作成する。</p>
<h3>Environment</h3>
<p>lenv 構造体型を定義する。<br />
lenv は Lisp Environment、環境を意味する。<br />
環境とは、名前とその名前が指し示す内容、値の、組、関係を登録したものだ。</p>
<p>さらに、lenv 型の構造体を操作するのに便利なユーティリティ関数 lenv_new()、lenv_del()、lenv_get()、lenv_put() も作る。</p>
<p>lenv_new() 関数は、lenv 型の構造体、環境を新規作成する関数だ。</p>
<p>lenv_del() 関数は、lenv 型の構造体、環境を削除する関数だ。</p>
<p>lenv_get() 関数は、環境と名前を引数に取る。<br />
環境の中から名前に合致する登録内容を探し出し、名前に対応する値を戻り値とする。</p>
<p>lenv_put() 関数は、環境に新しい名前と値の関係を登録する関数だ。<br />
ただし、登録しようとした名前が環境中にすでに登録されているときは、古い値を新しい値で上書きする。</p>
<h3>Variable Evaluation</h3>
<p>Eval 部を改変する。</p>
<p>lval_eval() 関数の改良点:<br />
引数に lval 型の構造体だけではなく、環境（lenv 型の構造体）も取るようにする。<br />
シンボルを表す lval 型の構造体を評価すると、引数として与えられた環境の中からシンボルと同じ名前の登録内容を探し出し、その名前に対応する値（lval 型の構造体）（のコピー）が評価結果となるようにする。</p>
<p>lval_eval_sexpr() 関数の改良点:<br />
こちらも、引数に lval 型の構造体だけではなく、環境（lenv 型の構造体）も取るようにする。<br />
関数を適用、作用する際、lval 型の構造体の fun フィールド（要素）（lbuiltin 型）を使うことになるので、そのあたりを修正する。</p>
<h3>Builtins</h3>
<p>これまでに作ったビルトイン関数それぞれについて、引数に lval 型の構造体だけではなく、環境（lenv 型の構造体）も取るように修正する。</p>
<p>さらに、Lisp インタプリターの REPL、インタラクティブ・プロンプトが始まる前に、ビルトイン関数を環境に登録しておく必要がある。</p>
<p>そこで、lenv_add_builtin() 関数と lenv_add_builtins() 関数を作る。</p>
<p>lenv_add_builtin() 関数は、環境に、引数として指定された名前と関数ポインターの組を登録する関数だ。</p>
<p>lenv_add_builtins() 関数は、Lisp インタプリターの REPL が始まる前に呼ばれる、実行される関数だ。<br />
この関数は、すべてのビルトイン関数を環境に登録する。<br />
この関数のおかげで、REPL が始まった初期状態の時点ですべてのビルトイン関数が利用可能になる。</p>
<p>最後に、main() 関数を修正する。<br />
REPL が始まる前に環境を新規作成し、すべてのビルトイン関数をこの環境に登録する。<br />
また、REPL が終わった後（*1）、環境を削除する処理も書いておく。</p>
<p>この節まで終えた時点で、プログラムの動作確認を行う。</p>
<p>&nbsp;</p>
<p>*1<br />
現時点の main() 関数では、REPL が終わる、ということは起こらないのでは。<br />
将来の拡張で REPL を終わる、脱出する、正常終了する機能を加えたら、この、環境を削除するという処理が役に立つのではないか。</p>
<h3>Define Function</h3>
<p>この節では、REPL 中で使える新しい関数 def を作る。<br />
この関数は、REPL の実行中にユーザーが、環境にシンボルと値の組を登録できるというものだ。<br />
すなわち、def によって、ユーザーが REPL の実行中に、新しいシンボルと値の組を定義できるようになるのだ。</p>
<p>まず、builtin_def() 関数を作る。<br />
この関数は、引数として指定されたシンボルと値の組を、エラー・チェックをした後、lenv_put() を使って環境に登録するという処理を行う。</p>
<p>lenv_add_builtins() 関数に def と builtin_def() のことを書いておく。</p>
<p>ここまで終えた時点で、プログラムの動作確認を行う。</p>
<h3>Error Reporting</h3>
<p>この節では、Lisp インタプリターのエラー・レポーティング（エラー・メッセージにどのような情報を表示するか）の機能を強化する。</p>
<p>まず、C 言語の variable argument、variable argument function（可変数個の引数を取る関数、可変数引数関数）という機能である、「...」という記号や va_list 構造体の使い方が説明される。</p>
<p>variable argument を用いて、lval_err() 関数を改良する。</p>
<p>さらに、C 言語のマクロにおいて variable argument を利用する方法も解説される。</p>
<p>こうして説明されたことを用いて、LASSERT() マクロを改良する。</p>
<p>ltype_name() 関数も、あると便利なので作る。<br />
この関数は int 型の変数を引数に取り、char* 型の変数を返す関数だ。<br />
LVAL_FUN を入力すると "Function" を返す、<br />
LVAL_NUM を入力すると "Number" を返す<br />
――などというように、整数に対して、enum 列挙型で割り当てられた対応する型の名前を文字列で返す関数だ。</p>
<p>プログラム中随所のエラー・メッセージを生成する箇所をすべて直す。<br />
どこどこを直すかは Build Your Own Lisp の本文中には書かれていないので、<br />
Build Your Own Lisp のこの章に添付されているソース・コードを参照のこと。</p>
<p>これでこの章のプログラム改良作業は終わりである。<br />
プログラムの動作確認を行う。</p>
<p>この章の成果物のプログラムの動作結果</p>
<pre>lispy&gt; def {kuman} 90000
()
lispy&gt; def {shiyshiy} 44
()
lispy&gt; kuman
90000
lispy&gt; shiyshiy
44
lispy&gt; list kuman shiyshiy
{90000 44}
lispy&gt; + kuman shiyshiy
90044
lispy&gt;
()
lispy&gt; def {ppap} {pen pineapple apple pen}
()
lispy&gt; ppap
{pen pineapple apple pen}
lispy&gt; def {pen apple pineapple} 2 3 4
()
lispy&gt; pen
2
lispy&gt; apple
3
lispy&gt; pineapple
4
lispy&gt; eval (join {*} ppap)
48
</pre>
<h2>Chapter 11 variables.c</h2>
<h3>*</h3>
<p>Chapter 11 の成果物である variables.c を読み解いてみよう。</p>
<h3>登場する関数などを分類する</h3>
<p>このソース・ファイル variables.c にはたくさんの関数が含まれているが、これらの関数を</p>
<ul>
<li>main() （REPL）</li>
<li>Read 部</li>
<li>Eval 部</li>
<li>Print 部</li>
<li>lval 構造体型（Lisp Value、Lisp 値）の定義とユーティリティ関数</li>
<li>lenv 構造体型（Lisp Environment、Lisp 環境）の定義とユーティリティ関数</li>
<li>その他</li>
</ul>
<p>と分類すると理解の足掛かりになるだろう。</p>
<h3>*</h3>
<p>まず、lval 構造体型の定義とユーティリティ関数や、lenv 構造体型の定義とユーティリティ関数などを見ていこう。<br />
このあたりはシンプルな働きの関数が並んでいるだけなので理解は易しいだろう。</p>
<h3>lval 構造体型の定義</h3>
<p>lval 構造体型は Lisp Value（Lisp 値）を格納するための型である。<br />
lval 構造体型には、これ一つで、エラー値、数値、シンボル、関数、S 式、Q 式のいずれをも格納することができる。</p>
<p>lval 構造体には、</p>
<ul>
<li>type</li>
<li>num</li>
<li>err</li>
<li>sym</li>
<li>fun</li>
<li>count</li>
<li>cell</li>
</ul>
<p>という要素がある。</p>
<p>このうち必ず使われるのが type 要素である。<br />
type フィールドに格納された数値（整数）によって、この lval 型の構造体が<br />
エラー値を表しているのか（エラー型）、<br />
数値を表しているのか（数値型）、<br />
シンボルを表しているのか（シンボル型）、<br />
関数を表しているのか（関数型）、<br />
S 式を表しているのか（S 式型）、<br />
Q 式を表しているのか（Q 式型）、<br />
判別できるようになっている。</p>
<p>lval 型の構造体がエラー型の場合、err フィールドにエラー・メッセージの文字列が格納される。</p>
<p>lval 型の構造体が数値型の場合、num フィールドに数値が格納される。</p>
<p>lval 型の構造体がシンボル型の場合、sym フィールドにシンボルとなる文字列が格納される。</p>
<p>lval 型の構造体が関数型の場合、fun フィールドは関数ポインターになっているので、ここにビルトイン関数（へのポインター）を格納する。</p>
<p>lval 型の構造体が S 式型または Q 式型の場合、count フィールドに子の個数、cell フィールドに各子を表す lval 構造体へのポインターの配列を格納する。</p>
<h3>lenv 構造体型の定義</h3>
<p>lenv 構造体型は、Lisp Environment（Lisp 環境、環境）を格納するための型である。<br />
環境とは、名前とその名前が指し示す値との組の集まりである。</p>
<h3>lenv_put() 関数</h3>
<p>少し解説すると良さそうなのは lenv_put() 関数だろうか。</p>
<p>lenv_put() 関数は、環境に新しい名前と値の関係を登録する関数だ。<br />
ただし、登録しようとした名前が環境中にすでに登録されているときは、古い値を新しい値で上書きする。</p>
<h3>main() （REPL）</h3>
<p>それでは、main() 関数を見てみよう。</p>
<p>main() 関数の中では初めに、パーザー（構文解析器）が用意されている。<br />
この処理は mpc というライブラリーが使われているので詳しく立ち入る必要なし。</p>
<p>REPL を開始する前に、環境が新規作成され、その環境にすべてのビルトイン関数が登録される。</p>
<p>その後、REPL（Read-Eval-Print Loop）に入る。<br />
ユーザーからの入力文字列を構文解析し、Read し、Eval し、Print する。<br />
これを繰り返す。</p>
<p>REPL を終えた後、環境を削除する。</p>
<h3>Read 部</h3>
<p>それでは、Read 部を詳しく見てみよう。</p>
<p>ライブラリー mpc による構文解析の結果は抽象構文木（AST）になっている。<br />
これを lval 型の構造体に変換する。</p>
<p>抽象構文木（AST）も lval 型の構造体も、どちらも木構造なので、変換するのは易しい。</p>
<h3>Print 部</h3>
<p>次に、Eval 部を後に回して、Print 部を詳しく見てみよう。</p>
<p>Print 部はソース・コードを読んだだけで理解できるだろう。</p>
<h3>Eval 部</h3>
<p>それでは、Eval 部を詳しく見てみよう。</p>
<p>Eval 部の関数の多くは、環境と lval 型の構造体の二つを引数に取ることに留意しよう。</p>
<p>Eval 部の中核が lval_eval() 関数である。</p>
<p>引数、評価対象の lval 型の構造体には、エラー型、数値型、シンボル型、関数型、S 式型、Q 式型といった型があったことを思い出そう。</p>
<p>lval 型の構造体がエラー型、数値型、関数型、Q 式型の場合は、この lval 型の構造体に何も手を加えず、そのまま戻り値、評価結果とする。</p>
<p>lval 型の構造体がシンボル型の場合は、環境の中からこのシンボルと一致する名前を探し出し、その名前に対応する値（のコピー）を戻り値、評価結果とする。</p>
<p>lval 型の構造体が S 式型の場合は、評価の処理を lval_eval_sexpr() 関数に丸投げしている。</p>
<h3>lval_eval_sexpr() 関数</h3>
<p>lval_eval_sexpr() 関数の内容を詳しく見てみよう。</p>
<p>初めに、引数の S 式の各子が評価される。</p>
<p>次に、各子の評価結果の中にエラー値が見つかれば、それを lval_eval_sexpr() 関数の戻り値、評価結果とする。</p>
<p>エラー値がなかった場合、子の個数が0ならば（つまり引数の S 式が空リストだった）、引数の S 式をそのまま lval_eval_sexpr() 関数の戻り値、評価結果とする。<br />
すなわち、この場合の lval_eval_sexpr() 関数の戻り値、評価結果は空リストだ。</p>
<p>子の個数が1ならば、その唯一の子を抽出して lval_eval_sexpr() 関数の戻り値、評価結果とする。</p>
<p>子の個数が2以上ならば、まずこの時点で S 式の最初の子が関数型であることを確認する。<br />
（関数型でなかった場合はエラー値を戻り値、評価結果とする。）</p>
<p>確認できたら、その関数を S 式の2番目以降の子たちに作用させ、その結果を lval_eval_sexpr() 関数の戻り値、評価結果とする。<br />
なお、S 式の最初の子が表す関数はビルトイン関数のうちのいずれかで、def、list、head、tail、eval、join、+、-、*、/ の可能性がある。</p>
<h3>ビルトイン関数 list、head、tail、eval、join、+、-、*、/</h3>
<p>ビルトイン関数のうち、list、head、tail、eval、join、+、-、*、/ については、処理が単純なのでソース・コードを読んだだけで理解できるだろう。</p>
<p>注意が必要なのは、<br />
- は引数の数が1個の場合は符号反転、2個以上の場合は減法として機能するという点と、<br />
/ ではゼロ除算のチェックを行っているという点か。</p>
<h3>ビルトイン関数 def</h3>
<p>ビルトイン関数 def は、REPL の実行中にユーザーが、環境にシンボルと値の組を登録できるというものだ。<br />
すなわち、def によって、ユーザーが REPL の実行中に、新しいシンボルと値の組を定義できるようになるのだ。</p>
<p>ビルトイン関数 def の処理は、builtin_def() 関数で行われている。<br />
この関数は、引数として指定されたシンボルと値の組を、エラー・チェックをした後、lenv_put() を使って環境に登録するという処理を行う。</p>
<h3>*</h3>
<p>以上、Chapter 11 の成果物、variables.c の解説でした。</p>]]> 
    </content>
    <author>
            <name>まめ</name>
        </author>
  </entry>
  <entry>
    <id>mame123.blog.shinobi.jp://entry/10</id>
    <link rel="alternate" type="text/html" href="https://mame123.blog.shinobi.jp/%E6%9C%AA%E9%81%B8%E6%8A%9E/20191022_build-your-own-lisp" />
    <published>2019-10-22T21:04:47+09:00</published> 
    <updated>2019-10-22T21:04:47+09:00</updated> 
    <category term="未選択" label="未選択" />
    <title>Build Your Own Lisp、Chapter 10 までの勉強ノート</title>
    <content mode="escaped" type="text/html" xml:lang="utf-8"> 
      <![CDATA[2019年10月22日 <br />
&nbsp;<br />
&nbsp;
<h2>概要</h2>
&nbsp;<br />
「<a title="" href="http://www.buildyourownlisp.com/">Build Your Own Lisp</a>」というプログラミングの講座のウェブサイトがある。 <br />
&nbsp;<br />
Build Your Own Lisp <br />
<a title="" href="http://www.buildyourownlisp.com/">http://www.buildyourownlisp.com/</a>&nbsp;<br />
&nbsp;<br />
C 言語を使って、Lisp のインタプリターを作ろう！という内容だ。 <br />
&nbsp;<br />
私は今このウェブサイトを読んで勉強しているところなのだが、私が自分のために作成した勉強ノートが、ウェブで公開すれば誰かの役に立つかもしれないと思い、当ブログで公開することにした。 <br />
&nbsp;<br />
Build Your Own Lisp は全16章から成るが、この記事では Chapter 1 から Chapter 10 までを私なりにまとめている。 <br />
&nbsp;<br />
&nbsp;
<h2>Chapter 1</h2>
&nbsp;<br />
Build Your Own Lisp <br />
<a title="" href="http://www.buildyourownlisp.com/">http://www.buildyourownlisp.com/</a>&nbsp;<br />
&nbsp;<br />
適宜 <a title="" href="https://translate.google.com/?hl=ja">Google 翻訳</a>も利用すると便利。 <br />
&nbsp;<br />
Chapter 1 を読んだ。 <br />
内容はサブタイトルのとおり Introduction です。 <br />
&nbsp;<br />
&nbsp;
<h2>Chapter 2</h2>
<div>&nbsp;</div>
<div>Chapter 2 を読んだ。 </div>
<div>&nbsp;</div>
<div>この章では、&nbsp;</div>
<ul>
<li>テキスト・エディターと C のコンパイラーのインストール方法 </li>
<li>Hello, World プログラムの作成とコンパイルのし方 </li>
<li>デバッグ支援ツールの紹介 </li>
</ul>
<div>などが解説されている。 </div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<h3>コマンド覚え書き</h3>
&nbsp;<br />
コマンド・プロンプト（cmd.exe）で使えるコマンドの覚え書き。 <br />
&nbsp;<br />
<code>gcc --version</code> &nbsp; <br />
<code>gcc --help</code> &nbsp; <br />
<code>gcc -std=c99 -Wall hello_world.c -o hello_world</code> &nbsp;<br />
gcc の -Wall オプションについて Google で調べようと思い、Google の検索欄に <br />
<code>gcc -Wall</code> <br />
と入力したのだが、それらしい情報がまったくヒットしない。しばらく思案して、Google では「-」は not 検索の意だと気づき、一人大笑いしていた。 <br />
&nbsp;<br />
&nbsp;
<h2>Chapter 3</h2>
&nbsp;<br />
Chapter 3 を読んだ。 <br />
&nbsp;<br />
この章では、C 言語の文法の概要が解説されている。 <br />
&nbsp;<br />
&nbsp;
<h2>Chapter 4</h2>
&nbsp;<br />
Chapter 4 を読んだ。 <br />
&nbsp;<br />
この章では、入力された文字列をそのまま表示するという動作を繰り返すプログラムを作成する。 <br />
使っている OS によってソース・コードが少々異なってくるので、各 OS のためのソース・コード、一つのソース・コードですべての OS に対応する方法などが書かれている。 <br />
&nbsp;<br />
&nbsp;
<h2>Chapter 5</h2>
&nbsp;<br />
Chapter 5 を読んだ。 <br />
&nbsp;<br />
この章では、言語の文法というものについての理論が記されている。 <br />
&nbsp;<br />
&nbsp;
<h2>Chapter 6&nbsp;</h2>
&nbsp;<br />
Chapter 6 を読んだ。 <br />
&nbsp;<br />
mpc というライブラリーを導入して、ポーランド記法のパージング（構文解析）を行う。 <br />
&nbsp;<br />
今後 mpc というライブラリーを使うことになるので注意が必要かな。 <br />
コンパイルのコマンドが少し変更されているのかな？ <br />
<code>cc -std=c99 -Wall parsing.c mpc.c -o parsing</code> <br />
&nbsp;<br />
&nbsp;
<h2>Chapter 7</h2>
&nbsp;<br />
Chapter 7 を読んだ。 <br />
&nbsp;<br />
この章では、再帰とは何かが説明されている。 <br />
また、入力された式中の加減乗除の演算子の評価を行えるようにする。 <br />
&nbsp;<br />
&nbsp;
<h2>Chapter 7 までの復習</h2>
&nbsp;<br />
Chapter 7 を終えた時点のソース・コードは、 <br />
REPL（Read-Eval-Print Loop）になっていて、 <br />
Read 部でパージング（構文解析）、 <br />
Eval 部で加減乗除の演算子の評価、 <br />
Print 部で（Eval の結果は long 型なので）printf() で表示、 <br />
を行う、というものになっている。 <br />
&nbsp;<br />
&nbsp;
<h2>Chapter 8</h2>
&nbsp;<br />
Chapter 8 を読んだ。 <br />
&nbsp;<br />
この章では、ゼロ除算などを実行しようとしたときに、プログラムがクラッシュするのではなく、エラー・メッセージを表示するように、プログラムを改良する。 <br />
&nbsp;<br />
lval 構造体型を導入する。lval は Lisp Value を意味するという。 <br />
lval 型の変数を用意することにより、数値とエラーの種類の双方を一つの変数で扱えるようになる。 <br />
&nbsp;<br />
REPL（Read-Eval-Print Loop）の Eval 部と Print 部が、lval 型に対応するよう変更される。 <br />
&nbsp;<br />
C 言語における enum（列挙型）についてもこの章で解説がある。 <br />
&nbsp;<br />
&nbsp;
<h2>Chapter 9</h2>
&nbsp;<br />
Chapter 9 を読んだ。 <br />
&nbsp;<br />
この章では、lval 構造体型で S 式を表せるよう改良を加える。 <br />
この章の成果物のプログラムを実行すると、前章と外見上はあまり違いがないが、 <br />
プログラム内部では大規模な修正（リファクタリング）が行われている。 <br />
&nbsp;<br />
&nbsp;
<h3>Lists and Lisps</h3>
&nbsp;<br />
&nbsp;
<h3>Pointers</h3>
&nbsp;<br />
C 言語のポインターについての解説。 <br />
&nbsp;<br />
&nbsp;
<h3>The Stack &amp; The Heap</h3>
&nbsp;<br />
スタック と ヒープ についての解説。 <br />
&nbsp;<br />
&nbsp;
<h3>Parsing Expressions</h3>
&nbsp;<br />
ソース・コードの構文解析部に、 <br />
sexpr ルールを導入。 <br />
また、operator を symbol に改名。 <br />
&nbsp;<br />
&nbsp;
<h3>Expression Structure</h3>
&nbsp;<br />
lval 構造体型を、S 式を扱えるよう改造。 <br />
&nbsp;<br />
&nbsp;
<h3>Constructors &amp; Destructors</h3>
&nbsp;<br />
lval 型の構造体のコンストラクターとデストラクターを作る。 <br />
&nbsp;<br />
lval 型の構造体変数では、malloc() によってヒープ領域のメモリーを手動で確保しているので、lval 型の構造体変数を使い終わったときは必ず手動で free() をしてメモリーを解放しなくてはならない。 <br />
&nbsp;<br />
&nbsp;
<h3>Reading Expressions</h3>
&nbsp;<br />
REPL の Read 部の関数を作る。 <br />
抽象構文木（AST）を入力すると、対応する lval 型の構造体変数を出力する関数だ。 <br />
&nbsp;<br />
ついでに、lval_add() という、S 式を表す lval 型の構造体変数に要素（子）を追加する関数も作る。 <br />
&nbsp;<br />
&nbsp;
<h3>Printing Expressions</h3>
&nbsp;<br />
REPL の Print 部の関数を作る。 <br />
lval 型の構造体変数を print（画面に表示）する関数だ。 <br />
&nbsp;<br />
この時点で Read-Eval-Print Loop ならぬ Read-Print Loop を作り、プログラムの動作確認を行う。 <br />
&nbsp;<br />
&nbsp;
<h3>Evaluating Expressions</h3>
&nbsp;<br />
REPL の Eval 部を作る。 <br />
&nbsp;<br />
lval_eval() 関数は、 <br />
S 式を表す lval 型の構造体変数については lval_eval_sepxr() 関数に処理を丸投げする。 <br />
その他の場合の lval 型の構造体変数については、引数に何も変更を加えずそのまま返す。 <br />
&nbsp;<br />
lval_eval_sexpr() 関数は、 <br />
まず、引数として渡された S 式を表す lval 型の構造体変数の、各要素（子）を評価（eval）する。 <br />
評価を終えた子の中にエラーを表すものがあれば、それを戻り値とする。 <br />
空の S 式はそのまま返す。 <br />
1要素から成る S 式はその要素（子）を抽出して返す。 <br />
以上以外の場合は、第1要素がシンボルであることを確認して、builtin_op() を呼ぶ。 <br />
&nbsp;<br />
次に、lval_pop() 関数と lval_take() 関数を作る。 <br />
&nbsp;<br />
lval_pop() 関数は S 式を表す lval 型の構造体変数から i 番目の要素を取り出す。 <br />
取り出し元の lval 型の構造体変数は要素が1個減る。 <br />
&nbsp;<br />
lval_take() 関数は、S 式を表す lval 型の構造体変数から i 番目の要素を取り出す。 <br />
取り出し元の lval 型の構造体変数は破棄される。 <br />
&nbsp;<br />
その後、builtin_op() 関数を作る。 <br />
&nbsp;<br />
builtin_op() 関数は、加減乗除の演算の処理を行う。 <br />
&nbsp;<br />
最後に main() で REPL が回るようにし、プログラムの動作確認を行う。 <br />
&nbsp;<br />
&nbsp;
<h3>*</h3>
<div>&nbsp;</div>
<div>どこで malloc() や free() が行われているのかに着目してソース・コードを読むのもおもしろい。</div>
<div>&nbsp;</div>
<div>Chapter 9 の成果物のソース・コードは、まだそこまでこんがらがっていないので、普通に読めば理解できるだろう。</div>
<div>ソース・コード中に登場する各関数を</div>
<ul>
<li>main() （REPL）</li>
<li>Read 部</li>
<li>Eval 部</li>
<li>Print 部</li>
<li>lval 構造体型のユーティリティ関数&nbsp;</li>
</ul>
<div>などと頭の中で分類しておくと理解しやすいだろう。</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<h2>Chapter 10&nbsp;</h2>
<div>&nbsp;</div>
<div>Chapter 10 を読んだ。</div>
<div>&nbsp;</div>
<div>この章では、Q 式（Q-Expression）の取り扱いを実装する。</div>
<div>また、五つのビルトイン関数――list、head、tail、join、eval――を実装する。</div>
<div>&nbsp;</div>
<div>この本では、Q 式は {} で囲んで表される。</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<h3>Adding Features&nbsp;</h3>
<div>&nbsp;</div>
<div>これからの章はすべて似たような進め方になる、という説明。</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<h3>Quoted Expressions&nbsp;</h3>
<div>&nbsp;</div>
<div>パーザー（構文解析器）に qexpr ルールを追加する。</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<h3>Reading Q-Expressions&nbsp;</h3>
<div>&nbsp;</div>
<div>lval 構造体型で Q 式をストアできるようにする。</div>
<div>Read 部で Q 式を read できるようにする。</div>
<div>Print 部で Q 式を print できるようにする。</div>
<div>――などの変更を加える。</div>
<div>&nbsp;</div>
<div>この時点でプログラムの動作確認を行う。</div>
<div>{} で囲まれた Q 式が扱えるようになった。</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<h3>Builtin Functions&nbsp;</h3>
<div>&nbsp;</div>
<div>ここからは、五つのビルトイン関数――list、head、tail、join、eval――を実装する作業を行う。</div>
<div>&nbsp;</div>
<div>パーザー（構文解析器）の symbol ルールにこの五つの関数名を追加する。</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<h3>First Attempt</h3>
<div></div>
<div>&nbsp;</div>
<div>builtin_head() と builtin_tail() 関数を書いてみる。</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<h3>Macros</h3>
<div></div>
<div>&nbsp;</div>
<div>C 言語のマクロについて解説する。</div>
<div>&nbsp;</div>
<div>C 言語のマクロ LASSERT() を作る。</div>
<div>&nbsp;</div>
<div>LASSERT() を用いながら、builtin_head()、builtin_tail()、builtin_list()、builtin_eval()、builtin_join() の各関数を作る。</div>
<div>builtin_join() 関数では lval_join() という補助関数を使う。</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<h3>Builtins Lookup</h3>
<div></div>
<div>&nbsp;</div>
<div>builtin() 関数を作り、Eval 部から list、head、tail、eval、join、+、-、*、/ の各関数や演算子を呼べるようにする。</div>
<div>&nbsp;</div>
<div>これで Chapter 10 のソース・コードを書く作業は終わりである。</div>
<div>&nbsp;</div>
<div>プログラムを動作確認する。</div>
<div>&nbsp;</div>
<pre>lispy&gt; list 10 20 30 
{10 20 30} 
lispy&gt; head {10 20 30} 
{10} 
lispy&gt; tail {10 20 30} 
{20 30} 
lispy&gt; join {10} {20 30} {40 50 60} 
{10 20 30 40 50 60} 
lispy&gt; eval {+ 10 20} 
30 
lispy&gt; 
</pre>
<div>&nbsp;</div>
<div>&nbsp;</div>
<h3>*</h3>
<div></div>
<div>&nbsp;</div>
<div>Chapter 10 の成果物のソース・コードは、まだそこまでこんがらがっていないので、普通に読めば理解できるだろう。</div>
<div>ソース・コード中に登場する各関数を</div>
<ul>
<li>main() （REPL）</li>
<li>Read 部</li>
<li>Eval 部</li>
<li>Print 部</li>
<li>lval 構造体型のユーティリティ関数</li>
</ul>
<div>などと頭の中で分類しておくと理解しやすいだろう。<br />
&nbsp;</div>]]> 
    </content>
    <author>
            <name>まめ</name>
        </author>
  </entry>
  <entry>
    <id>mame123.blog.shinobi.jp://entry/9</id>
    <link rel="alternate" type="text/html" href="https://mame123.blog.shinobi.jp/%E6%9C%AA%E9%81%B8%E6%8A%9E/20191020_grandmother-s-photos" />
    <published>2019-10-20T06:47:56+09:00</published> 
    <updated>2019-10-20T06:47:56+09:00</updated> 
    <category term="未選択" label="未選択" />
    <title>祖母が撮った写真</title>
    <content mode="escaped" type="text/html" xml:lang="utf-8"> 
      <![CDATA[2019年10月20日<br />
&nbsp;<br />
&nbsp;<br />
母が、祖母が若いころに撮った写真をどう扱うか困ると言っていた。<br />
祖母は若いころ日本各地へ旅行に行っていて、<br />
自分を写した写真は少なく、一緒に旅行に行った人や旅行先で出されたお膳などを撮った写真が多いのだという。<br />
フイルム・カメラの時代。当時は料理の写真を撮る人はあまりいなかった。<br />
今日のインスタ映えを狙っている人かな？ w<br />
祖母は時代を先取りしていたのである。 ww]]> 
    </content>
    <author>
            <name>まめ</name>
        </author>
  </entry>
  <entry>
    <id>mame123.blog.shinobi.jp://entry/8</id>
    <link rel="alternate" type="text/html" href="https://mame123.blog.shinobi.jp/%E6%9C%AA%E9%81%B8%E6%8A%9E/20191020_hisasiburi" />
    <published>2019-10-20T06:36:42+09:00</published> 
    <updated>2019-10-20T06:36:42+09:00</updated> 
    <category term="未選択" label="未選択" />
    <title>久しぶりの更新</title>
    <content mode="escaped" type="text/html" xml:lang="utf-8"> 
      <![CDATA[2019年10月20日<br />
&nbsp;<br />
&nbsp;<br />
このブログを久しぶりに更新しました。<br />
&nbsp;<br />
<a title="" href="http://mame123.blog.shinobi.jp/未選択/20191020_01">統計学を使って確かな結論を精度良く得るには&hellip;&hellip;</a>&nbsp;（2019年10月20日）<br />
&nbsp;<br />
1年近く放置しちゃった (^-^;)ゞ]]> 
    </content>
    <author>
            <name>まめ</name>
        </author>
  </entry>
  <entry>
    <id>mame123.blog.shinobi.jp://entry/7</id>
    <link rel="alternate" type="text/html" href="https://mame123.blog.shinobi.jp/%E6%9C%AA%E9%81%B8%E6%8A%9E/20191020_01" />
    <published>2019-10-20T06:28:35+09:00</published> 
    <updated>2019-10-20T06:28:35+09:00</updated> 
    <category term="未選択" label="未選択" />
    <title>統計学を使って確かな結論を精度良く得るには……</title>
    <content mode="escaped" type="text/html" xml:lang="utf-8"> 
      <![CDATA[2019年10月20日<br />
&nbsp;<br />
&nbsp;<br />
統計学を使って確かな結論を精度良く得るには、数千件とか数万件といった単位の大量の標本データが必要になることが多いです。しかし、世の中の多くの人は、数件のデータを集めただけで早急に結論を出すようです。私の周りの人数人はみんなこうして早急に結論を出していたから間違いない。 #メタ #自虐]]> 
    </content>
    <author>
            <name>まめ</name>
        </author>
  </entry>
  <entry>
    <id>mame123.blog.shinobi.jp://entry/6</id>
    <link rel="alternate" type="text/html" href="https://mame123.blog.shinobi.jp/%E6%9C%AA%E9%81%B8%E6%8A%9E/1%E5%B9%B4%E3%81%BB%E3%81%A9%E5%89%8D%E3%81%AE%E7%A7%81%E3%81%AE%E5%A4%A2%E6%97%A5%E8%A8%98" />
    <published>2018-10-25T22:01:40+09:00</published> 
    <updated>2018-10-25T22:01:40+09:00</updated> 
    <category term="未選択" label="未選択" />
    <title>1年ほど前の私の夢日記</title>
    <content mode="escaped" type="text/html" xml:lang="utf-8"> 
      <![CDATA[パソコンの HDD を漁（あさ）っていたら、1年ほど前に書いた私の夢日記が出てきたので、このブログで紹介する w<br />
&nbsp;<br />
<hr />&nbsp;<br />
2017年10月21日（土）、12時ごろから20時ごろまで（妹）とクトゥルフ TRPG（「毒入りスープ」）をやっていた。<br />
TRPG が終わった後、疲れて寝た。<br />
そのとき、変な夢を見た。<br />
以下にその夢の内容を記す。<br />
&nbsp;<br />
私は高校2年生という設定。<br />
■■高校の校舎の南東の角にある階段を降りていた。<br />
2階から1階へ降りていると、突然周りの風景が変わり、<br />
私とそばにいた女子生徒二人が、謎の部屋に閉じ込められた。<br />
その謎の部屋は倉庫のような場所で、さまざまな教材やら棚やらが雑然と置かれていた。<br />
しかし、出口が見つからない。<br />
あ、これは夢の中の世界だ、と気がついた（明晰夢）私は、この謎の倉庫の中の探索を開始。<br />
私と女子二人が倉庫の中を探索していると、<br />
女子の一人が、いくつかの棚を階段のように踏み台にして登っていくと、倉庫から出られることに気がついた。<br />
出口に気がついた女子、続いてもう一人の女子が倉庫の外へ脱出した。<br />
私も後に続こうとして踏み台の棚の近くに近づくと、遠くから見たときと近くで見たときとでは棚の高さが違っていて、私は女子二人のようにはこの倉庫から出られないことに気がつく。<br />
と、そこへ謎の女の子の声が。<br />
「やっと二人きりになれたね」<br />
私の前にその声の主が現れる。<br />
彼女は高校1年生、髪型は黒髪のショート・カットで、眼鏡をかけていた。<br />
顔つきは SHOW BY ROCK! のレトリーに似ていた。<br />
彼女は一瞬で部屋の様子を一変させたり、早着替えを披露したり、分身の術を披露したり、何もないところから銃を出現させてみたりしてくれた。<br />
私は、前にも一度夢の中で彼女に会ったことがある、と思った。<br />
彼女は高校1年生。現役女子高生眼鏡っ子手品師タレントとして、芸能活動をしているという。<br />
片手に銃を持って決めポーズをとる姿、かっこ良かったなあ。<br />
どうせここは夢の中なんだから、どうにでもなれと思った私は、<br />
そのままこの謎の空間で彼女とお泊りデートしました。<br />
楽しかったです。<br />
あ、そうそう、今回は彼女の名前を聞き出すことに成功したよ。<br />
彼女は自分の名前を「らん」と名乗った。<br />
楽しい夢でした。<br />
また会いたいです。<br />
&nbsp;<br />
<hr />&nbsp;<br />
この夢に登場したらんちゃんは、そのままオリキャラ（オリジナル・キャラクター）として採用しちゃいました。 &larr;<br />
夢の中の設定をそのまま引き継いで、このオリキャラも現役女子高生眼鏡っ子手品師タレントという設定です。 (*&acute;&forall;｀)<br />
&nbsp;<br />
いやあ、素敵な夢を見ると、忘れないように書き留めておきたくなるよね！<br />
&nbsp;<br />
それにしても、私の頭の中にこんなかわいい女の子が住んでるって、ヤバない？ なんというか&hellip;&hellip;いいよね。<br />
&nbsp;
<h2>関連記事</h2>
&nbsp;<br />
<a title="" href="http://mame123.blog.shinobi.jp/未選択/夢日記の話題。">夢日記の話題。</a>&nbsp;（2018年10月24日） -- 夢日記の書き方などに言及している記事。<br />
&nbsp;
<h2>検索用タグ</h2>
&nbsp;<br />
夢日記<br />
明晰夢<br />
深刻な知能低下]]> 
    </content>
    <author>
            <name>まめ</name>
        </author>
  </entry>
</feed>