Factor/FAQ/Factor での開発

バグを見つけました。どうすればよいですか?

まず、バグレポートを参照し、既知の問題かどうかチェックしてください。次に、同じページか連鎖性 IRC チャンネル、またはメーリングリストでバグを報告してください。

自分のコードを Factor のソースツリー以外の場所に保存するにはどうすればよいですか?

http://docs.factorcode.org/content/article-add-vocab-roots.html を参照してください。

コンパイラのエラーや警告にはどんなものがありますか?

次の 2 つのヘルプトピックを参照してください。

コンパイラのエラーや警告はコードに問題があることを示しているので、問題を解決する必要があります。コンビネータのコンパイル時に警告が出る場合は、そのコンビネータを inline として宣言してください。これで警告は出なくなり、コンビネータを呼び出す側も警告なしにコンパイルされるようになります。詳細については、上の 2 つのリンク先を参照してください。

docs にあるコードや Factor プログラマから渡されたコードをリスナーで入力したのですが、"no word found" というエラーになります。コードが間違っているのでしょうか?

存在しないワードを呼び出すと、次のようなエラーが発生します。

( scratchpad ) fadf
1: fadf
       ^
Word not found in current vocabulary search path
"name" "fadf"

The following restarts are available:

:1    Defer word in current vocabulary

Type :help for debugging help.

ただし、メッセージが "Word not found in current vocabulary search path" (ワードが現在のボキャブラリ検索パスに見つかりません) となっている点に注意してください。実際にワードが存在していて、そのボキャブラリがリスナーの検索パスに含まれていない場合もあります (すべてのボキャブラリがデフォルトで追加されるわけではありません)。その場合には、同じようなエラーが出ますが、再起動の選択肢が表示されます。

( scratchpad ) "Hello world" <label>
1: "Hello world" <label>
                        ^
Word not found in current vocabulary search path
"name" "<label>"

The following restarts are available:

:1    Use the cpu.architecture vocabulary
:2    Use the ui.gadgets.labels vocabulary
:3    Defer word in current vocabulary

Type :help for debugging help.

上のように表示された場合、:1 または :2 を選択して cpu.architecture ボキャブラリまたは ui.gadgets.labels ボキャブラリを検索パスに追加すると、USE: cpu.architecture または USE: ui.gadgets.labels と入力したのと同じ結果になります。詳細については、http://docs.factorcode.org/content/article-errors-restartable.html を参照してください。

USE: fooUSING: foo ; はどう違うのですか?

違いはありません。USING: は、複数の USE: を 1 行で記述するのと等価です。

ファイルのトップレベルで 1 foo set として、リスナーで foo get と入力すると、このファイルをロードした後に f と表示されるですが、なぜですか?

ファイルをパースしてトップレベルのコードを実行するときに、新しく動的スコープが作成されます。foo の値を別のところからもアクセスできるようにするには、foo の値を変更する必要があるかどうかに応じて、1 foo set-global または : foo 1 ; を使ってください。: init-foo 1 foo set ; のようにワードを作成して値を初期化する方法もあります。

スタックを主要データ構造として使う言語でハッシュテーブルや配列を効率的に実装するにはどうすればよいですか?

これは実際によくある誤解の 1 つです。Factor のスタックはデータ構造ではなく、ワード間で値を受け渡しするための手段です。Factor はハッシュテーブルを十分簡単にサポートしています。新しいハッシュテーブルを作成するには <hashtable> を呼び出します。<hashtable> によってスタックにオブジェクトがプッシュされるので、ユーザーは atset-at といったワードを使ってオブジェクトを操作できます。重要なのは、ハッシュテーブルはスタック上では単一の値として格納されているという点です。スタック上の値は、数値やブール型などのスカラーだけでなく、複雑な型 (配列やハッシュテーブル、タプルなど) を取ることができます。また、実際にスタックデータ構造が必要な場合には、データスタックを使わないでください。代わりにベクトルを使用し、このベクトルに対して pushpop を呼び出してください。

詳細については、以下を参照してください。

ベクトルをスタックにプッシュするワードがあり、ソースでは空のベクトル V{} として記述されています。しかし、ワードを実行すると、ランダムなオブジェクトがベクトルに入っています。これはなぜですか?

リテラルは初心者が混乱しやすい概念です。リテラルは、それが使われる場所でスタックにプッシュされます。Factor でのリテラルは、メモリ内にある 1 つの固有のオブジェクトを指し、自動的には複製 (clone) されません。リテラルを複製せずに修正を加えると、その修正はグローバルなものになります。詳細については、リテラルに関するヘルプのドキュメントを参照してください。

1 つのスタックでは不十分です。新しいスタックを定義することはできますか?

データスタックだけを使ってデータフローを表現するのが困難だと感じた場合は、新しくスタックを追加することを考える前に、コードをリファクタリングするか、または locals を使ってください。

ただし、追加のスタックが本当に必要な場合 (たとえばパーサを作成していて、ネスト構造を追跡する必要がある場合など) には、さまざまな方法で簡単にスタックを作成できます。最も簡単なのは、スタックを動的変数に格納する方法です。

SYMBOL: my-stack

: >my-stack ( value -- ) my-stack get push ;
: my-stack> ( -- value ) my-stack get pop ;

: with-my-stack ( quot -- ) [ V{ } clone my-stack ] dip with-variable ; inline

dup のようなスタック操作ワードは、オブジェクトをコピーしますか?

いいえ。スタックはポインタのスタックなので、dup やこれに類するその他のワードは非常に高速です。大規模な配列やその他のデータ構造を作業対象にするときも、dup でプログラムの処理が遅くなることを心配する必要はありません。

自分の書いたコードが遅いのですが、どうすれば最も速くできますか?

まず、アルゴリズムが適切かどうかチェックしてください。時間・空間計算量に関する問題をすべて解決したら、低水準の最適化についても検討できます。詳細については、最適化を参照してください。

This revision created on Fri, 17 Apr 2009 04:25:39 by slava