0

これは、Mythender (自由に配布されたテーブルトップ RPG) のダイスローラーとして、Lisp プログラムでの 2 回目の適切な試みです。ただし、いくつかの問題があります。

  • 読み込まれると、パッケージの作成を確認するプロンプトが表示されます。確かにこのファイルはそれを作成しているはずですか?

  • LispWorks アプリケーション ビルダーを使用してスタンドアロンでビルドしようとすると、コンパイル時に CAPI 関数を呼び出そうとしていることを示すエラーが表示されますが、それがどこにあるのかわかりません。

  • 関数に戻りがないことを示すための (null ()) セクションについて話した一部の Lisp 関係者から、否定的なコメントが寄せられたので、スタックに何も残す意味がありません。これは適切でしょうか? それを行うより良い方法はありますか?

一般的な提案も歓迎します。

(defpackage :mythender (:add-use-defaults t) (:use "CAPI"))
(in-package :mythender)

(defun d6 () (the fixnum (+ 1 (random 6))))

(defun d6s (count)
  (declare (type fixnum count))
  (the list (loop for x from 1 to count collecting (d6))))

(defun d6over (count threshold) 
  (declare (type fixnum count threshold))
  (the fixnum (count-if 
   (lambda (x) (> threshold x)) 
   (d6s count))))

(defvar *storm* 3)
(defvar *thunder* 3)
(defvar *lightning* 0)

(declare (ftype (function) printstate))
(defun printstate ()
  (print *storm*)
  (print *thunder*)
  (print *lightning*)
  (the null ()))

(defun roll () 
  (incf *lightning* (d6over *thunder* 3))
  (incf *thunder* (d6over *storm* 3))
  (the null ()))

(defun damage (threshold)
  (setf *thunder* (d6over *thunder* threshold))
  (the null ()))

(defun doroll (&rest args)
  (roll)
  (update-interface)
  (the null ()))


(define-interface mythender-interface () ()
  (:panes
   (roll-button push-button :data "Roll" :callback #'doroll)
   (damage-button push-button :data "Damage")
   (storm-pane display-pane :title "Storm:" :title-position :left)
   (thunder-pane display-pane :title "Thunder:" :title-position :Left)
   (lightning-pane display-pane :title "Lightning:" :title-position :left))
  (:layouts
   (main-layout column-layout '(storm-pane thunder-pane lightning-pane buttonlayout))
   (buttonlayout row-layout '(roll-button damage-button))))

(defvar *interface*)

(defun update-interface-slot (slotname value)
  (declare (type string slotname) (type fixnum value))
  (setf (display-pane-text (slot-value *interface* slotname)) (write-to-string value))
  (the null ()))

(defun update-interface () 
  (update-interface-slot 'storm-pane *storm*)
  (update-interface-slot 'thunder-pane *thunder*)
  (update-interface-slot 'lightning-pane *lightning*)
  (the null ()))


(defun start () 
  (setf *interface* (make-instance 'mythender-interface))
  (display *interface*)
  (the null (update-interface)))
4

1 に答える 1

3

ビルドの問題に対する回答は、ビルド ステートメントとエラー メッセージをお知らせいただくまでお待ちいただく必要があります。

最後の質問:

(declare (ftype (function) printstate))
(defun printstate ()
  (print *storm*)
  (print *thunder*)
  (print *lightning*)
  (the null ()))

関数であることが知られています。それを宣言する必要はありません。そのような型を宣言することは、単純な Common Lisp では、コンパイラーが無視するかもしれないコンパイラーへの最適化ヒントの目的のみを持っています。CMUCL (および SBCL や SCL などの派生コンパイラ) だけが、宣言された型を実際に処理します。

Lisp でそのようなコードを書く人はいません。型は省略したほうがよい。注意: Lisp は静的に型付けされた言語ではありません。

(defun printstate ()
  (print *storm*)
  (print *thunder*)
  (print *lightning*)
  (values))

を使用する(values)と、関数は値を返さなくなります。を返さずに、通常はそれが好まれNILます。

実行時に意味のある方法で型を実際にチェックしたい場合はASSERT、 、CHECK-TYPEおよび/またはを使用しますDEFMETHOD

(defun d6s (count)
  (declare (type fixnum count))
  (the list (loop for x from 1 to count collecting (d6))))

ただ:

(defmethod d6s ((n integer))
  "Returns a list of n dice rolls."
  (loop repeat n collect (d6)))

関数のセマンティクスを人間が読める形式で記述することを忘れないでください。

于 2014-05-11T07:46:04.920 に答える