見出し画像

Retro-gaming and so on

RE: プログラミング学習日記 2022/06/24〜

星田さんの記事に対するコメント。



 という訳で・・とりあえずレコード形式を使って成績の集計を行うってのは・・うッ(;´Д`)・・動作するのは出来ました。

うん。よく出来てる。
そして「なんかなぁ・・・」って思うのはいい事です。常にリファクタリング出来ないか?って考えるのも良い練習。
多分必要なのはcaseequal?で一々比較したくない、っつったらこれしかない。
こんな風に書きたいんじゃないかな。

(define (shukei lst)
 (let loop ((lst lst) (kekka kekka))
  (if (null? lst)
   (hyouzi_kekka)
   (loop (cdr lst)
    (begin (case (test-seiseki (car lst))
        (("S") (set! (kekka0-s kekka) (+ (kekka0-s kekka) 1)))
        (("A") (set! (kekka0-a kekka) (+ (kekka0-a kekka) 1)))
        (("B") (set! (kekka0-b kekka) (+ (kekka0-b kekka) 1)))
        (else (set! (kekka0-c kekka) (+ (kekka0-c kekka) 1))))
       kekka)))))

caseは第一引数で、結果、「与えられたデータのどの部分で判定を下したいのか」指定できる。いまは(car lst)と言う構造体のseisekiスロットがどうなのか調べたいだけ、なんでそう指定する。これでこの部分を何度も書く必要はなくなる。
あとは第二引数以降は「指定したデータが何だったのか」場合分けするだけでいい。今は文字列となってるデータが"S"、"A"、"B"、かそれ以外、しかないんで、それを指定する。あとはそれに従った「操作」を記述していけばいいだけ。
LispのcaseはC言語のswitch文なんかより強力なんで重宝する。Lispのcaseに慣れるとC言語のswitch文はあまりに原始的でお粗末だ。

そしてここまで来ると、「構造体を破壊的変更する」んじゃなくって「構造体を新しく生成しても良い」と言う事に気づくんじゃないか。

(define (shukei lst)
 (let loop ((lst lst) (kekka kekka))
  (if (null? lst)
   (hyouzi_kekka)
   (loop (cdr lst)
    (let ((s (kekka0-s kekka)) (a (kekka0-a kekka)) (b (kekka0-b kekka)) (c (kekka0-c kekka)))
     (case (test-seiseki (car lst))
      (("S") (make-kekka0 (+ s 1) a b c))
      (("A") (make-kekka0 s (+ a 1) b c))
      (("B") (make-kekka0 s a (+ b 1) c))
      (else (make-kekka0 s a b (+ c 1)))))))))

Racketのbig-bangで行ってたのはこの形式だ。

ところでLispのcasematchは構文的に非常に似通ってるのが分かるだろう。
実はこの2つは殆ど同じなんだけど、違いは次の点にある。

  • caseは第一引数に与えられたデータが「具体的に」何なのか、で処理を分ける。
  • match は第一引数に与えられたデータが「どんなパターンになってるか」分解してそれによって処理を継続する。
言い換えると上の例のように具体的にデータが"S"だとか"A"だとか分かってる時はcaseの出番。一方、データが具体的にどう、って分からなくって良い場合がmatchの出番。
「具体」のcase、「抽象」のmatchと覚えておこう。


ちょうど良いのでMatchを使って教科書そのままで置き換えてみるか・・あれ?1は?

うん、パターン記述を忘れてる(笑)。
正解はこう。


2番目のパターンの記述をキチンとしておかないとならない。


 そのままいつもの(if (null?を使った形にしたらちゃんと動くよなぁ?と言うか・・(・.・;) 結局いつものこの形で良くない?

うん(笑)。
っつーか翻って言うと、「プログラミングの基礎」で使われてるパターンマッチングの例も実はそこまで旨味はないのよね(笑)。オーバースペックと言おうか。
だからフツーのプログラミングでも、ifcondcaseの出番が殆どを占めて、パターンマッチングの出番なんて殆どないかもしんない。だからこそSchemeの仕様に含まれてないわけで。
ところがプログラミングやっていくと分かるんだけど、レアケースでもデータ構造の分解、そしてその内情調査が必要になる、ってのがしばしば出てくるんだよな。
この、「たまに出てくる割にはプログラミングが面倒」ってのはすんげぇ嫌なんだよ(笑)。
こういうケースではifを入れ子にしたりcondを入れ子にしたり・・・とかとかく面倒なのね。
でも、OCaml式のパターンマッチングならデータを分解させる、って簡単じゃない。だからいざとなるとき重宝する。条件文の入れ子をガンガン書かなくて済むわけ。

だから条件分岐系機能としてはパターンマッチングはすごく抽象度が高いの。「プログラミングの基礎」ではその「高抽象性」にまずは慣れましょう、それが「モダンなスタイル」です、ってメッセージで徹頭徹尾パターンマッチングを掛けてるんだと思う。
  • Xでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

最近の「RE: プログラミング学習日記」カテゴリーもっと見る

最近の記事
バックナンバー
人気記事