見出し画像

Retro-gaming and so on

RE: プログラミング学習日記 2023/02/22〜

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


 こうなってたけど順番が謎だぞ?と

うん。
「キーワード引数」ってのは順序は関係ない、んです。
Pythonでもそうなんで覚えていた方がエエかも。

元々Schemeには仕様上、オプショナル引数もなかった。
確か元々「オプショナル引数」が導入されたのはR6RSかな?case-lambdaの導入でオプショナル引数が仕様に含まれた。
だから、オプショナル引数は新参者なんだけど、いまだキーワード引数ってのは正式仕様じゃない。
もちろんRacketは既にSchemeを止めて久しいんだけど、結局、キーワード引数はRacketの独自拡張で、また、ぶっちゃけ、ANSI Common Lispからその機能を持ってきてる。

通常、引数ってのは順番通りに実引数が手渡される。よって「順序引数」と呼ばれる事もある。オプショナル引数でさえ「順序」が大事だ。
一方、キーワード引数は順序は関係ない。オプショナル引数じゃない「必須の引数」の後だったらどこに置いても良い、ってパターンが多い。

例えば次のような単純な関数を書いてみる。

(define (keylist a #:key (x '()) (y '()) (z '()))
 `(,a ,x ,y ,z))

順序としてはキーワード引数であるxはデフォルト値としては'()が与えられ、その位置は2番目だ。
しかし、実行する際にキーワード引数xに与える実値はどこに置いても問題がない、ってのが次の実行例で分かると思う。

> (keylist 1) ; 必須引数aに1を与えたパターン
'(1 () () ())
> (keylist 1 #:key 2) ; 必須引数aに1を、キーワード引数xに2を与えたパターン
'(1 2 () ())
> (keylist 1 2) ; キーワード引数を使わないので2番目の値は順序によりyだと解釈される
'(1 () 2 ())
> (keylist 1 3 #:key 2) ; 実行時にキーワード引数へ2を与える位置を最後にしても関数定義時の「位置」に2が入る
'(1 2 3 ())
>

つまり、キーワード引数を使った場合、sortの実行は次のどれでも正解、って事になるわけだ。


順序引数は順序が大事だけど、キーワード引数はどこに挿入して使っても構わない。
キーワード引数の重要な性質なんで押さえておこう。


 昼間諦めていたドットリストで座標を備えた構造体のリストのSort問題、こうやって書けば・・


 ちゃんと出来た、スゲーッ!

あと、こういう手もあります。
つまり、こう継承してるわけでしょ?

(struct CHARACTER (Name Race Class Ali Lv Hp Ac Exp Money Move foo Arm Armor Item Str Int Wis Dex Con Chr) #:transparent)
(struct HERO () #:super struct:CHARACTER)
(struct ENEMY () #:super struct:CHARACTER)

そして、これで作ったインスタンスをそれぞれ「位置情報」にconsしたリストを作る、と。

`(
 (,(HERO "tawa" "ELF" "MAGIC-USER" "" 1 6 10 0 90 6 '() '() '() '() 10 18 6 11 9 10) . ,(make-posn 31 31))
 (,(HERO "hosida" "HUMAN" "FIGHTER" "" 1 1 10 0 90 5 '() '() '() '() 17 10 12 8 15 14) . ,(make-posn 93 93))
 (,(ENEMY "DEMON1" "ENEMY" "" "" 1 1 10 0 90 5 '() '() '() '() 10 10 10 18 10 10) . ,(make-posn 155 155))
         (,(ENEMY "DEMON2" "ENEMY" "" "" 1 1 10 0 90 5 '() '() '() '() 10 10 10 2 10 10) . ,(make-posn 217 217)))

これを構造体(CHARACTER)のDEX値でsortしたい場合は次のように書けばいい。

(sort `(
   (,(HERO "tawa" "ELF" "MAGIC-USER" "" 1 6 10 0 90 6 '() '() '() '() 10 18 6 11 9 10) . ,(make-posn 31 31))
   (,(HERO "hosida" "HUMAN" "FIGHTER" "" 1 1 10 0 90 5 '() '() '() '() 17 10 12 8 15 14) . ,(make-posn 93 93))
   (,(ENEMY "DEMON1" "ENEMY" "" "" 1 1 10 0 90 5 '() '() '() '() 10 10 10 18 10 10) . ,(make-posn 155 155))
   (,(ENEMY "DEMON2" "ENEMY" "" "" 1 1 10 0 90 5 '() '() '() '() 10 10 10 2 10 10) . ,(make-posn 217 217)))
  > #:key (match-lambda ((cons head tail) ; 注目!
             (CHARACTER-Dex head))))

lambdaが使えるトコは当然match-lambdaも使える、と言う事に注目しよう。
こういう時に、散々っぱら鍛えた「パターンマッチング」を堂々と応用しよう。
  • Xでシェアする
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

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

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