SU-Ⅲ 電脳紀 Second -3ページ目

SU-Ⅲ 電脳紀 Second

基本的に雑記ですが、情報系の事も書きます。

繰り返しは再帰で書く(forも無くはないが) 例えば
(define fact
    (lambda (x)
        (if (= x 1) 1 (* x (fact (- x 1))))
    )
)
とした場合、引数として渡した自然数の階乗が得られる(この関数は引数として自然数を想定している。)
評価の過程を書くと、
(fact 4)
(* 4 (fact 3))
(* 4 (* 3 (fact 2)))
(* 4 (* 3 (* 2 (fact 1))))
(* 4 (* 3 (* 2 1)))
(* 4 (* 3 2))
(* 4 6)
24

となるが、次のようにプログラムを書き換えると評価の過程は変わってくる。
次のようにプログラムを書き換える。
(define fact
    (lambda (x)
        (define inner
            (lambda (n x)
                (if (= n 1) x (inner (- n 1) (* x n)))
            )
        )
        (inner x 1)
    )
)

と、計算過程はこうなる。
(fact 4)
(inner 4 1)
(inner 3 4)
(inner 2 12)
(inner 1 24)
24

注目すべきは前者は過程が横に膨らんでいた(与える値を大きくするともっと横に長くなる)が、後者は常にinner関数が呼び出されるだけで、ある階層における計算でそれより先の計算結果を利用していません。

前者を再帰的プロセス、後者を反復的プロセスと言う。
同じ結果が得られるとしても反復的プロセスの方が内部的に効率的に実行することができる。
最近本放送以来となる「ウルトラマンネクサス」(以後「ネクサス」)をめちゃくちゃ久しぶりにレンタルビデオ屋で1から借りて観なおしています。
なぜこうなったか。時間は少しさかのぼり、去年は「エヴァンゲリオン」と「まどかマギカ」)を観ました。「エヴァ」は夏に映画が放送され、そこからTV版と旧劇場版を一通り。「まどか」は「ネクサス」を適当に拾い観&MADを観ていた時ふと主人公が最後まで変身しないアニメがあったことを思い出して観賞。後者はその1点の共通点で見始めたのですが、道具や人物の設定に他にも似てる点があったので途中からはそっちを探してました(笑)。
で、「エヴァ」もウルトラシリーズの影響を受けてますし、そういえばTLTってネルフっぽさあったなとか思いつつ、10年ぶりに1話から順に連続で観直すということになりました。

現在(12話:別離-ロスト・ソウル-)まで観賞。
「まどか」についてはこちらの方がすでにたくさん書いてくれてました。すごいです。コメントで”見直して”なんて書いてましたがこの時は拾い観レベルでしたね。すみません。番外編を知らないためマミはアニメ登場2人目の魔法少女なのと武器が銃なので無理に姫屋(第2の適応者、ブラストショット最多使用)と重ねてましたがゲーム版設定にあんなものがあったとは。あとほむらはイラストレーターにも重なるんですよね(偶然とは思うが似ている台詞があった&後の展開を知っている)。今でも。ちなみに自分が最初に「あっ」ってなったのはソウルジェムです(笑)

「まどか」はどちらかと言うと個々の設定に共通点が多い印象。 一方で「エヴァ」は演出や雰囲気などに同じような何かを感じます。

例えば上層部が怪しすぎる防衛チーム、孤門が闇に囚われ絶望するシーン、クロスフェーズトラップのシーン、姫屋失踪~3人目の登場の間に行われた尋問のシーン、最終回のラスボスがレーテに接触と「諦めるな!」のシーンなどなど。 他にも選ばれた人間しか変身できないうえ、彼らを適応者、●人目、ザ・サードなどと呼称したりする点もですかね。

見返して思うんですが孤門の成長と挫折がとてもいい。でもこれは放送当時この歳でもなかなか気づけなかったと思います。週1で当時観てたからでしょうね。 前半は暗すぎる演出が多い印象が強かったのですが、これも成長の描写、そして最終回への感動には不可欠だなぁと思わされるものです。

あれこれ言っちゃいましたけど、結局「ネクサス」は面白いのです! 春休みに少しずつ進めていきたいと思います(昨晩課題を出し切ってめでたく春休みへ)。
分岐

condとifがある。まずはcond文。

(cond 
((述語) (式))
((述語) (式))
((述語) (式))
:
:
)


述語はC言語とかでifの()の中に書くやつ。
上から見ていき、一番最初にこの条件をクリアした部分の式が実行される。

述語としてSchemeには =,<,>,<=,>=,and,or,notが使える。
DrRacketではeven? odd?も使える。
一番左の記号から評価というのはこれらも変わらず、括弧で囲った一番左に記述する。
例えば100で割った余りが0と等しいかどうかはこう書く。
(= (remainder 100 10) 0)

これは真である。racketでは#tが返ってくるのが確認できる。
もし偽であれば#fが返ってくる。

繰り返すとcond文は複数の述語と式の組み合わせの内上から見て行って最初に#tとなる場所の式を評価し、その結果を返す

if文は
(if (述語) 
(式1)
  (式2)
)

となる。
述語を評価しそれが#tであれば式1を、そうでなければ式2を評価しその結果を返す


どちらを使っても同じことができるが、複数分岐する場合は入れ子しすぎると視覚的に分かりにくくなるのでcondのほうが書きやすいかも。
注意!
メモ的なつもりで書いており、管理者もまだ勉強不足気味です。
誤りがあるかもしれません。
もし間違いがあったら分かりやすく教えていただけると嬉しいです。



関数
関数もdefineを使って定義できます。

……、
という前に
関数はlambdaで作れます
と習い始めたほうが良かったのではなかろうかと授業後思ってます。
もちろんdefineを使って省略する書き方も綺麗なんですが、
lambdaで書いたほうが個人的には何が書いてあるのか分かりやすいというか、
ある関数に関数を引数で与える時にわざわざ外部にdefineで定義してある関数を
引数として与えるようなまどろっこしいことをしなくて済むので。

lambdaを使った関数作成は次のように書けばできます。
(lambda (引数) (関数の本体))

例えばある値を受け取ってそれに5を加算して返す関数は以下のように書ける。
(lambda (x) (+ x 5))

ただこの関数、まだ名無しです。
そこでdefineを使ってこれをadd5と呼称しようとなると次のようになります。
(define add5 (lambda (x) (+ x 5)))

例えば試しに2を関数にあたえて7が返ってくるのを確かめたいってなった場合は
(add5 2)

とすれば7が返ってくる。
前回括弧で囲んだ時、一番左の何かでそれに続く引数を使って計算的なことを書きましたが
一番左の何かが今回は関数なのでこうも書けます。
((lambda (x) (+ x 5)) 2)

add5と呼称せずにダイレクトに使っているパターンです。
まあadd5とは何かって言われると(lambda (x) (+ x 5))となるので。
一発屋で済む関数はむしろこうやってdefineせずに書いたほうがいい感じになる場合もあります。


最初にdefineでやるのは好きじゃない的なことを言ったのは次のような書き方です。
add5の例で、lambdaを利用しない場合は
(define (add5 x) (+ x 5))

とも書けます。
でも個人的には「常にlambda使用縛り」をしておいてlambdaに慣れておいたほうが良いかなぁとか思ったり。
以後更新していくときはlambdaを必ず使って関数書きます。
※注意
自分用のメモ書きのノリで書いています。
間違っていても責任は負いませんのでご注意ください。
また間違いをもし見つけて下さった方は分かりやすく教えていただけると非常に助かります。


授業で初めて今季習って結構衝撃だったので全授業が終わった今まとめてみることにしました。



プログラムは

  1. 基本式

  2. 組み合わせ

  3. 抽象化


この三つからなる。





演算子を一番左に書き、続いて演算子を書く。
それを括弧で囲む(括弧で囲まないと演算子による評価が行えない)

以下の場合であれば非演算子1と2に対して演算子+によって評価が行われ、3が返ってくる。
(+ 1 2)

他の-,*,/らも普段と同じ減算、乗算、除算が行える。
この四則演算子は非演算子として2より多くの引数を与えることも可能なので次のような計算であれば10が返ってくる。
(+ 1 2 3 4)

入れ子にもできる。
(+ 1 2 3 (* 2 2))

余りの計算はパーセント記号ではなくremainderが用意されている。
記号じゃないけどこれも四則演算子と扱いは変わらない。
15の10の余りを計算するときは次のようにすればいい。
(remainder 15 10)

ていうか授業が始まって直後はコイツらのせいでむしろ混乱してました。

(関数名 引数1 引数2 引数3 ...)

というふうに関数に引数を与えて括弧で囲って評価するという認識のほうがすんなり入ってくると思います。
最初の四則演算子も関数という認識で。
(っていうか資料にはそうも書いてあったと思う。でも最初に演算子から入って、しかも演算子って書かれるとあとで違和感を覚えるんですよ。バカだから。)



define

授業ではまず最初に
(define a 5)

みたいな例が出てきた後、
(define "変数の名前" "式")
みたいになってました。

が、
(define "名前" "実物")

のほうが後で悩まないで済むかなと思いました。
というのもまずこのdefineは代入とはちょっと印象が違うし、
普段Cとかで使う変数名の他に関数名の定義やその他もろもろにも出てくるから。
数字や文字列などの原始的なデータのほか、関数やリストとも対応付けするとき使います。
「変数aという箱に2を入れてます」って言うより「2っていう物体を以後aと呼称する」って感じなんですかねぇ……。