一通りのセットとしてまとめる

[『1週間で学べる！Julia数値計算プログラミング』](https://www.amazon.co.jp/1%E9%80%B1%E9%96%93%E3%81%A7%E5%AD%A6%E3%81%B9%E3%82%8B-Julia%E6%95%B0%E5%80%A4%E8%A8%88%E7%AE%97%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-KS%E6%83%85%E5%A0%B1%E7%A7%91%E5%AD%A6%E5%B0%82%E9%96%80%E6%9B%B8-%E6%B0%B8%E4%BA%95-%E4%BD%91%E7%B4%80/dp/4065282829)の2.7章の内容について試してみたことをメモ書きした。

# 一通りのセットとしてまとめる

## includeによるコードの整理

以下のようなtest.jlを作成する。
```julia:test.jl
a=4
b=5
A=[1 2
3 4]
println(a*b*A)
```
また、test2.jlを作成する。
```julia:test2.jl
include("test.jl")
B=[3 4
5 6]
C=A+B
println(C)
```
これを実行すると
```:test2.jl実行結果
[20 40; 60 80]
[4 6; 8 10]
```
となる。includeはtest.jlを呼び出した位置に書き出すのと同じになる。

### プリプロセッサ処理？？？

test.jlとtest2.jlを以下のように書き換える。
```julia:test.jl
a=4
b=5
A=[1 2
3 4]
println(a*b*A)
function bug()
    println("No bug")
```
```julia:test2.jl
include("test.jl")
end
B=[3 4
5 6]
C=A+B
println(C)
```
これの結果は
```:実行結果
[20 40; 60 80]
ERROR: LoadError: syntax: incomplete: "function" at C:\Users\81906\Documents\Julia勉強会\test.jl:7 requires end
```
functionのendがないというエラーが出た。これより、includeはC言語でいうプリプロセッサ処理(コンパイル前に処理)ではなく、コンパイル後に行われる処理である。

### 多重includeはできる？

test2.jlの中でincludeを２回行う。
```julia:test2.jl
include("test.jl")
include("test.jl")
B=[3 4
5 6]
C=A+B
println(C)
```
```:実行結果
[20 40; 60 80]
[20 40; 60 80]
[4 6; 8 10]
```
test.jlが２回実行される。多重でincludeは可能。

## 関数の上書き

多重includeしたときに、関数が定義されていたら、
```julia:test.jl
function hello()
    println("Hello world")
end
```
```julia:test2.jl
include("test.jl")
include("test.jl")
println(methods(hello))
hello()
```
```:実行結果
# 1 method for generic function "hello" from Main:
 [1] hello()
     @ C:\Users\81906\Documents\Julia勉強会\test.jl:1
Hello world
```
関数定義がおかしくなることもない。関数の上書きが行われている。

## moduleの使用

module内にmoduleを定義することもできる。
```julia:originai.jl
module Original
    function tasu(a,b)
        println("tasu in original.jl")
        return a+b
    end
    function supercoolfunction(a,b)
        return tasu(a,b)/b
    end
    module Orig2
        function tasu(a,b)
            println("tasu in original.orig2")
            return a+10b
        end
    end
end
```
```julia:main.jl
include("original.jl")
using .Original
function tasu(a,b)
    println("tasu in main.jl")
    return a+2b
end
println(Original.supercoolfunction(4,10),"in main.jl")
using .Original.Orig2
println(Orig2.tasu(4,10),"in Orig2")
```
```:実行結果
tasu in original.jl
1.4in main.jl
tasu in original.orig2
104in Orig2
```

```using .Original.Orig2```のように重ねることでmodule内moduleをusingでき、実行時は```Orig2.tasu()```のように、一番下のmoduleから関数を呼び出せる。

## module内の関数の拡張機能

```julia:original.jl
module Util
    function util()
        println("util")
    end
end
```
```julia:main.jl
include("original.jl")
using .Util
function Util.util(string)
    println(string, "outside Util")
end
Util.util()
Util.util("original")
```
```:実行結果
util
originaloutside Util
```
moduleの関数をファイルの外で追加することができる。
同じ関数名で関数の上書きをすると実質関数の内容を書き換えることができる。
これを駆使することで秘伝のコードを触らなくても済む。

## usingとimportの違い

```import:util```とするとmodule名を省略して扱える。
そもそも個人的にはmodule名省略はしない方が良いと思うので、使いどころがない。


# 参考

- [『1週間で学べる！Julia数値計算プログラミング』](https://www.amazon.co.jp/1%E9%80%B1%E9%96%93%E3%81%A7%E5%AD%A6%E3%81%B9%E3%82%8B-Julia%E6%95%B0%E5%80%A4%E8%A8%88%E7%AE%97%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-KS%E6%83%85%E5%A0%B1%E7%A7%91%E5%AD%A6%E5%B0%82%E9%96%80%E6%9B%B8-%E6%B0%B8%E4%BA%95-%E4%BD%91%E7%B4%80/dp/4065282829)