情報 / Info
当サイトは、Typst GmbHの許諾を得て、日本語コミュニティ「Typst Japanese Community」がTypst v0.13.1の公式ドキュメントを翻訳したものです。誤訳や古い情報が含まれている可能性があるため、公式ドキュメントとの併用を推奨します。翻訳の改善やサイトの機能向上について、GitHubでのIssueやPull Requestを歓迎します。コミュニティにご興味のある方はDiscordサーバー「くみはんクラブ」にぜひご参加ください。
This site provides a Japanese translation of the Typst v0.13.1 documentation maintained by the "Typst Japanese Community" with permission from Typst GmbH. We recommend using this alongside the official documentation. We welcome contributions through Issues and Pull Requests on our GitHub repository for both translation improvements and website enhancements. Feel free to join our Discord server "Kumihan Club".
未翻訳

このページはまだ翻訳されていません。原文の内容が表示されています。

state

文書中の状態の管理。

文書中で何回か計算を行い、最後の計算結果を次の計算で使用するために記憶しておきたいとします。 以下と同等のコードを試すと10、13、26、21と出力されることを期待するでしょう。 しかしTypstではそうはなりません。 このコードを試してみると、Typstは Variables from outside the function are read-only and cannot be modified. というエラーメッセージを出力することが分かります。

// This doesn't work!
#let x = 0
#let compute(expr) = {
  x = eval(
    expr.replace("x", str(x))
  )
  [New value is #x. ]
}

#compute("10") \
#compute("x + 3") \
#compute("x * 2") \
#compute("x - 5")

状態と文書のマークアップ

なぜこうなるのでしょうか? 一般的に副作用を伴うこの手の計算は文書のマークアップにおいて問題を引き起こすためで、Typstではこれをエラーとして扱います。 この結果を理解するには、計算処理が文書内で生成物がレイアウトされる順序と同じ順序で行われる必要があります。 今回の単純な例ではこの条件が満たされますが、一般的には必ずしもそうとは限りません。

見出しの番号付けという、類似した状態ですが、少し異なる例を見てみましょう。 各見出しで見出しカウンターの値を増やしたいとします。 簡単そうですよね? ただ1を足すだけです。 残念ながらそう単純ではないのです。 以下の例を考えます。

#set heading(numbering: "1.")
#let template(body) = [
  = Outline
  ...
  #body
]

#show: template

= Introduction
...
Preview

ここで、Typstはまずshowルール以降の文書本体を処理し、Introduction見出しを検知します。 続いてtemplate関数に生成コンテンツを渡します。 その後、初めてOutlineを検知します。 単にカウンター値を増やすとIntroduction1に、Outline2となります。

Typstにおける状態管理

それでは代わりにどうするのでしょうか? Typstの状態管理システムを使用します。 識別用のキーとなる文字列とオプションの初期値とともにstate関数を呼び出すことで状態値が得られます。 この状態値はいくつかの関数を公開しており、最も重要な2つの関数がgetupdateです。

  • get関数は状態の現在値を取得します。 値は文書中で変化するため、これはコンテキストが利用可能な場合にのみ使用できる コンテキスト 関数です。

  • update関数は状態に修正を加えます。 任意の値が使用できます。 関数ではない値が渡された場合、状態にその値が設定されます。 関数が与えられた場合、その関数は前の状態を受け取り、新しい状態を返さなければなりません。

最初の例は以下のようになります。

#let s = state("x", 0)
#let compute(expr) = [
  #s.update(x =>
    eval(expr.replace("x", str(x)))
  )
  New value is #context s.get().
]

#compute("10") \
#compute("x + 3") \
#compute("x * 2") \
#compute("x - 5")
Preview

Typstが管理する状態は常に評価順ではなくレイアウト順で更新されます。 updateメソッドはコンテンツを返し、その影響は文書に返されたコンテンツが挿入された場所で生じます。

このようにして、計算結果を変数に保存できるようになり、正しい結果を表示しています。

...

#let more = [
  #compute("x * 2") \
  #compute("x - 5")
]

#compute("10") \
#compute("x + 3") \
#more
Preview

この例はもちろん少々極端ですが、これが実際に本当に必要となることがよくあります! 良い例は見出しカウンターです。 これはTypstのカウンターシステムが状態システムにとてもよく似ているためです。

タイムトラベル

Typstの状態管理システムを使用するとタイムトラベルもできます! 文書内の任意の位置でその状態がどの値になっているのかを、どこからでも突き止めることができます。 特に、atメソッドを用いると特定の任意の位置での状態値が取得でき、finalメソッドを用いると文書の終わりでの状態値を取得できます。

...

Value at `<here>` is
#context s.at(<here>)

#compute("10") \
#compute("x + 3") \
*Here.* <here> \
#compute("x * 2") \
#compute("x - 5")
Preview

注意事項

全ての状態値を解決するために、Typstはコードを複数回評価します。 しかしながら、実際に状態操作が完全に解決されるかは保証されません。

例えば、状態の最終的な値に依存する更新を行う状態を作成した場合、決して収束しなくなるでしょう。 以下の例はこの実演です。 状態を1で初期化し、続いて自身の最終値に1を足した値に更新します。 したがって値は2になるべきですが、最終値が2となったので3に更新します。以下同様です。 この例では有限値が表示されていますが、これは単にTypstが数回試行した後に諦めるためです。

// This is bad!
#let s = state("x", 1)
#context s.update(s.final() + 1)
#context s.get()
Preview

一般に、コンテキスト内部で更新を行う状態を作成しないようにしてください。 可能であれば、更新内容をコンテキストに依存しない値として、あるいは前の値から新しい値を計算する関数として定義してください。 どうしても避けられない場合がありますが、その場合は結果が適切に収束することを保証することはあなたの責任です。

コンストラクタ
引数
引数は関数への入力値です。関数名の後に括弧で囲んで指定します。

キーで識別される新しい状態の作成。

state(
any
)->

key
必須引数
必須引数
必須引数は、関数を呼び出す際に必ず指定しなければなりません。
位置引数
位置引数
位置引数は順序通りに指定することで、引数名を省略して設定できます。

状態を識別するキー。

init
any
位置引数
位置引数
位置引数は順序通りに指定することで、引数名を省略して設定できます。

状態の初期値。

デフォルト値:

none

定義
定義
これらの関数や型には、関連する定義を持たせることができます。定義にアクセスするには、対象の関数や型の名前を指定した後に、ピリオド区切りで定義名を記述します。

get
コンテキスト関数
コンテキスト関数
コンテキスト関数は、コンテキストが既知の場合にのみ使用できます。

現在のロケーションでの状態値を取得。

これはstate.at(here())と等価です。

self.get(
)->
any

at
コンテキスト関数
コンテキスト関数
コンテキスト関数は、コンテキストが既知の場合にのみ使用できます。

指定したセレクターで一意に特定される対象の状態値を取得。

selectorは文書中で厳密に1つだけの要素にマッチしなければなりません。 この目的で最も便利なセレクターはラベルロケーションです。

selector
必須引数
必須引数
必須引数は、関数を呼び出す際に必ず指定しなければなりません。
位置引数
位置引数
位置引数は順序通りに指定することで、引数名を省略して設定できます。

状態値を取得する場所。

final
コンテキスト関数
コンテキスト関数
コンテキスト関数は、コンテキストが既知の場合にのみ使用できます。

文書の終わりでの状態値の取得。

self.final(
)->
any

update

状態値を更新。

更新は、返り値であるコンテンツが文書中に挿入された位置で適用されます。 文書中に出力がなければ何も起こりません! 例えばlet _ = state("key").update(7)と書いた場合が、この何も起きないときに該当します。 状態の更新は常にレイアウト順に適用されるため、この場合にはTypstはいつ状態を更新するのか分かりません。

self.update()->

update
必須引数
必須引数
必須引数は、関数を呼び出す際に必ず指定しなければなりません。
位置引数
位置引数
位置引数は順序通りに指定することで、引数名を省略して設定できます。

関数ではない値が与えられた場合、状態にその値を設定します。 関数が与えられた場合、その関数は前の状態を受け取り、新しい状態を返さなければなりません。

原文(英語)を開く

検索