[julia] ワークフロー, スコープ, モジュール
久しぶりに julia にさわるので, 基本的なことを復習するためのメモ.
0. 概要
以下の内容について記載する.
- ワークフロー
- スコープ
- module
1. ワークフロー
1.1 REPLベースのワークフロー
(詳細は julia-1.11.1.pdf / 36.1 REPL-based workflow 参照.)
以下のようなファイルを作成する.
module Tmp
say_hello() = println("Hello!")
# Your other definitions here
end # module
using .Tmp
同じフォルダでREPLを起動し, 以下のように say_hello() 関数を実行できる.
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から以下のようにインストールする.
julia> ]
(@v1.11) pkg> add Revise
(@v1.11) pkg> [BS]
julia>
([BS]はバックスペースキーを押すことを表す.)
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 Mはusing M: Mと同じ,import M: xならMは取り込まれず,xのみ取り込まれる)
3.3 モジュールの相対パス
パッケージマネージャーで管理されていないモジュールはモジュールの入れ子構造を .(自分のモジュールからみた子モジュール), ..(自分のモジュールから見た親モジュール)で指定して参照することができる.
Discussion