見出し画像

Retro-gaming and so on

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

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

まずGaucheから。

Gaucheは日本では一番人気がある処理系だし、とにかくドキュメントがいい。
ただし、世界的には今ひとつ人気がないっつーか・・・・・・多分ほぼ無名なんだよな(笑)。
例えば、SpacemacsScheme layerでもハブられている(苦笑)。


はあるのにGaucheはない・・・・・・。
もちろん何か頑張ればSpacemacsでもGaucheは使えるかもしんない。
でもそこが問題じゃないんだ。デフォルトで用意されてない、ってのが問題なんだよな(※1)。つまり、明らかに世界的に見るとユーザー数が少ない、マイナーな処理系だ、って事になる。
まぁね、SpacemacsのScheme layerの著者の趣味かもしんないが・・・なんせSchemeじゃないRacketが含まれてるし。あと、処理系を見るとC言語とやりとりするのが比較的得意そうな処理系が中心的に選ばれてるような気がする(Racket、Chez、MIT以外は多かれ少なかれCとのやり取りを念頭に設計されてる筈だ)。
ただ、日本で何かやる、って前提ならGauche最強なんだけど、世界に出ちゃうとそうじゃない、って事になるんだよなぁ、残念ながら(※2)。

paiza.ioは日本国内企業によるサービスなんでGaucheなんでしょう。ideoneだったらRacketが使える(Schemeなら別に三種類使える)。

おさらい。
GaucheはR7RS準拠なんでレコード型がそのまま使える(※3)筈なんだけど、paiza.ioだと上手く行かない。
従って、星田さんがやったようにSRFI-9に頼るのは正解だと思われる。
Racketのstructとは違って、書式はこうなる。

(define-record-type レコード型の名前
 コンストラクタ(レコード型生成関数)定義
 述語名定義
 (フィールドとフィールド名) ...)

つまりこうなる。


ここで、

  • 定義したレコード型の名称 -> gakusei_t
  • コンストラクタ(生成関数名とフィールド(スロット)に何が必要か) -> make-gakusei そして3つフィールドが必要(x, y, z)
  • 述語名定義 -> そのレコード型がgakusei_t型か調べる
  • xnameytensuuzseisekiとしてアクセス可能 -> アクセサ定義
ちょっと書く要素が多いんだけど、これでRacketのstructとほぼ同じ事が出来るようになる。

次に、GaucheにもOCamlよろしくパターンマッチング構文がある。

(use util.match)

で使用可能となる。


レコード型のパターンマッチングの場合、ちとコツがいるんだけど、

($ レコード型名 フィールド(定義順))

でパターンマッチが出来る(パターンマッチングのデータ別の「記述形式」はコチラから)。
ただし、やっぱ全般的にはRacketの方が簡単に書けるかも。



しかも、OCamlと違って、「構造体のフィールド(スロット)定義順」に任意に名付けられるので、面倒が少ない。
いずれにせよ、GaucheもRacketもパターンマッチングが入ってるんで、文法的にはほぼOCamlのコードをそのまま移植可能です。


 プログラミングの基礎の補助関数add to eachを作る。うーん・・こんな感じ?

これは当然、Lisp慣れしてればmapの出番だ。

(define (add_to_each n lst)
 (map (lambda (x)
     (cons n x)) lst))

ただ、教科書にはまだmapが出てきてないんだろう(笑)。


 リストを変えても動くのでこれにて落着とする。いや〜foldを使ってやってみたりしたんですけど思った形にならなくてですねぇ(^_^;)

これはこうかな?

(define (prefix lst)
 (cdr (reverse (foldl (lambda (y x)
          (cons `(,@(car x) ,y) x)) '(()) lst))))

> 2022/07/14 訂正編

逆クオート(quasiquote)とコンマが何の為に存在するのか、と言うのが、こういう時の為。

(define asai (make-test 100 "S"))
(define hirui (make-test 80 "A"))
(define yorui (make-test 70 "A"))
(define yuui (make-test 65 "B"))
(define mimei (make-test 65 "B"))
(define gakusei `(,asai ,hirui ,yorui ,mimei)) ;; ここに注目!

フツーにクオートしちゃうと中に含まれるモノは全部クオートされた事になって、未評価になっちゃう。
,(コンマ)で「任意に評価させる」機能が必要になるのは、このため、です。

※1: Scheme Layerの公式マニュアルにはさも「Gaucheも対応している」って書いてるが対応していない。

※2: 別にケチを付けてるわけじゃない。
実際問題、Scheme Layerでデフォルトで設定されてる処理系の殆どがR5RS準拠な方がおかしい、って意見の方が理論的な事を言えば「正しい」んだ。
Racketは既にSchemeである事を止めてるし、ChezはR6RS止まり。他の処理系は古いR5RS準拠である。
現在のScheme実装のその殆どはR5RS準拠と、R6RS以降に出てきたR7RS準拠の処理系に分かれている。そして後者の方はいまだどれもマイナーな処理系の域を出ていない。
つまり、R5RS時代から続けて、R6RS、R7RS対応、と順調にアップデートしてきてるのは世界的に見てもGaucheくらいしかないのである(他のメジャー処理系はR6RSの発表で脱落しちまったのが殆ど、ってのが実情だ)。Gaucheは仕様へのキャッチアップを継続して行ってる稀有な処理系なんだ。
逆に言うと、何故にScheme Layerに含まれないくらい(翻って言うとGeiserに含まれないくらい)Gaucheがマイナーなのか意味が分からん、ってのが正直なトコだ。
ただし残念な事に、コンピュータやプログラミングの世界では「理論的に正しい」事よりも「デファクトスタンダード」の方が圧倒的に強い、ってのはしばしば見かける事であり、仮にRacketを脱するのなら、殆どのメジャー処理系が現時点準拠してるR5RSに戻るしかない、ってのが現実で、SchemeのスタンダードはR6RS時点で「割れた」と言う残念な事実しか今のトコ残っていないのだ。

※3: C言語系では「構造体」、Pascal系では「レコード型」と呼ぶ。この2つは機能的には全く同じもの、である。
ANSI Common Lisp及びRacketはC言語系のネーミングだが、一般にSchemeはPascal系の呼称を用いてる。
  • Xでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

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

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