🐷

[julia] ワークフロー, スコープ, モジュール

2024/11/05に公開

久しぶりに julia にさわるので, 基本的なことを復習するためのメモ.

0. 概要

以下の内容について記載する.

  1. ワークフロー
  2. スコープ
  3. module

1. ワークフロー

1.1 REPLベースのワークフロー

(詳細は julia-1.11.1.pdf / 36.1 REPL-based workflow 参照.)

以下のようなファイルを作成する.

Tmp.jl
module Tmp
  say_hello() = println("Hello!")
  # Your other definitions here
end # module

using .Tmp

同じフォルダでREPLを起動し, 以下のように say_hello() 関数を実行できる.

REPL
julia> include("Tmp.jl")
julia> Tmp.say_hello()
Hello!

Tmp.jl を変更した場合, 再度 include することにより変更が反映される(REPL を再起動する必要がない).

1.2 Revise を使ったワークフロー

上の例では Tmp.jl を変更するたびに include を実行する必要があったが, Revise パッケージがインストールされていれば, 更新時の include の入力を省略することができる(最初の1回は includet する必要がある).

Revise がインストールされていない場合, REPLから以下のようにインストールする.

REPL
julia> ]
(@v1.11) pkg> add Revise
(@v1.11) pkg> [BS]
julia>

([BS]はバックスペースキーを押すことを表す.)

REPL
julia> using Revise
julia> includet("Tmp.jl")
julia> Tmp.say_hello()
Hello!

(include ではなく, includet であることに注意.)

Revise なしの場合と異なり, 一度 includet しておけば Tmp.jl が変更されると自動的に REPL にもそれが反映される. vscode で Julia 拡張を導入し, Revise がインストールされていると, REPL は using Revise の状態で起動される.

vscode で Julia 拡張のもと, REPL を起動するにはコマンドパレット(Shift+Ctrl+p)からJulia: Start REPL を選択すればよい(ショートカットは Alt+j Alt+o).

2. スコープ

(詳細は julia-1.11.1.pdf / 11 Scope of Variables 参照.)
julia のスコープ:

  • グローバル
  • ソフトローカル
  • ハードローカル

2.1 グローバルスコープ

  • 何も記載しない状態(デフォルト(Main)モジュール), もしくは明示的に module により生成
  • モジュール直下のスコープ
  • モジュール内でモジュールを定義してもスコープは入れ子にならない
  • モジュール名を明示的に付加して変数を指定すれば別のモジュールのグローバル変数も参照可能(Main.x など)

2.2 ローカルスコープ

  • if / begin では生成されない
  • 入れ子にでき, ローカルスコープ同士であれば必要に応じて外側の変数を参照できる
  • デフォルトではローカルスコープからグローバルスコープの変数を参照できない
  • ローカルスコープからグローバルスコープの変数を参照するためには global で宣言する
  • モジュール名を明示的に指定すればグローバルスコープの変数も参照できる(Main.x など)
  • REPL環境では一部のローカルスコープからグローバルスコープの変数が参照できる(ソフトローカルスコープ, 以下を参照)

2.3 ソフトローカルスコープ

(REPL環境における利便性のための機能だと思われる.)

  • REPL でのみ適用される特別なローカルスコープ
  • REPL 環境において for / while / try / struct によって生成されるローカルスコープからはグローバルスコープ(REPL環境)の変数が参照できる
  • 非対話環境では通常の(ハード)ローカルスコープになる

3. モジュール

3.1 デフォルトモジュール

  • モジュールを明示的に指定しなければデフォルトモジュール(Main モジュール)とみなされる
  • REPL環境は Main モジュールでの作業

3.2 include, using, import

  • include はその場所に引数のファイルを展開する命令であり, スコープや名前空間の概念とは関係ない
  • using は他のモジュールを現在の名前空間に取り込む(モジュール M に対して using M とすると M.x, M.f() などによりモジュールを参照することができるようになる)
  • モジュールの定義に export 文を記載しておけば(export x, f など) using したときにモジュール名を指定しなくても名前がそのまま使える(x, f() のように使える)
  • import は個別の名前を現在の名前空間に取り込む(import Musing M: M と同じ, import M: x なら M は取り込まれず, x のみ取り込まれる)

3.3 モジュールの相対パス

パッケージマネージャーで管理されていないモジュールはモジュールの入れ子構造を .(自分のモジュールからみた子モジュール), ..(自分のモジュールから見た親モジュール)で指定して参照することができる.

Discussion