$30 off During Our Annual Pro Sale. View Details »

Julia クイズ ~API編~ for JuliaTokai #19

Julia クイズ ~API編~ for JuliaTokai #19

Julia クイズ ~API編~
JuliaTokai #19 発表資料

GOTOH Shunsuke

June 29, 2024
Tweet

More Decks by GOTOH Shunsuke

Other Decks in Technology

Transcript

  1. 自己紹介 • 名前:後藤 俊介 • 所属:有限会社 来栖川電算 • コミュニティ:🌟JuliaTokai, 🌟機械学習名古屋,

    ⭐JuliaLangJa, Ruby東海, Python東海, … • 言語:Julia, Python, Ruby, … • SNS等:                  (@antimon2) • SNS等(2):      (@antimon2.jl) • 著書:実践Julia入門
  2. Julia とは?(1) • The Julia Language • 最新 v1.10.4(2024/06/04) ◦

    LTS:v1.6.7(2022/07/19) ◦ 次期:v1.11.0-rc1(2024/06/25) • 科学技術計算に強い! • 動作が速い!(LLVM JIT コンパイル)
  3. Julia とは?(2) • Rのように中身がぐちゃぐちゃでなく、 • Rubyのように遅くなく、 • Lispのように原始的またはエレファントでなく、 • Prologのように変態的なところはなく、

    • Javaのように硬すぎることはなく、 • Haskellのように抽象的すぎない ほどよい言語である 引用元:http://www.slideshare.net/Nikoriks/julia-28059489/8
  4. Julia とは?(3) • C のように高速だけど、 Ruby のようなダイナミズムを併せ持っている • Lisp のような真のマクロを持ちながら、

    MATLAB のような直感的な数式表現もできる • Python のように総合的なプログラミングができて、 R のように統計処理も得意で、 Perl のように文字列処理もできて、 MATLAB のように線形代数もできて、 shell のように複数のプログラムを組み合わせることもできる • 超初心者にも習得は容易でありながら、 ハッカーの満足にも応えられる • インタラクティブな動作環境もあって、コンパイルもできる (Why We Created Julia から抜粋・私訳)
  5. Julia API クイズ 概要 • Julia の 標準API の知識を問う内容をクイズにしました。 • このスライドで言う

    標準API とは、以下のような関数・定数 等を指します: ◦ 素の状態で hoge() のように使えるもの ◦ 〃 «モジュール名».hoge() のように使えるもの(一部) ◦ 組み込みパッケージで提供されているもの(using Hoge だけで利用できるもの)
  6. 第1問: 実際にある関数 以下のうち、Julia 標準に存在する関数はどれ? 1. 数値が 平方数かどうか を判定する関数 2. 文字列が

    Julia の 予約語かどうか を判定する関数 3. イテレータの要素が すべて異なるかどうか を判定する関数 4. 型が Julia 組み込みの型かどうか を判定する関数
  7. 第1問: 実際にある関数《解答》 以下のうち、Julia 標準に存在する関数はどれ? 1. 数値が 平方数かどうか を判定する関数 2. 文字列が

    Julia の 予約語かどうか を判定する関数 3. イテレータの要素が すべて異なるかどうか を判定する関数 4. 型が Julia 組み込みの型かどうか を判定する関数
  8. 第1問: 実際にある関数《解説》 allunique() • allunique() は、引数 にイテレータ(配列じゃな くてもOK)を受け取り、そ の要素がすべて異なる場 合に

    true を返す関数。 • 同一性の判定は isequal() で行われる。 • 類似の関数として、 allequal() (すべての 要素が同じかどうかを判 定する関数)もある。 (Julia v1.8 以降) allunique([1, 2, 3]) #> true allunique("ABCDEFGHIA") #> false allequal(ones(100)) #> true
  9. 第1問: 実際にある関数《補足 1》 平方数の判定 • 「数値が平方数かどう かを判定する関数」は 存在しない。 • 比較的簡潔に定義で

    きる。 issq(n::Integer) = 0 ≤ n == isqrt(n)^2 # 整数版 issq(n::Number) = 0 ≤ n == trunc(√n)^2 # 整数以外版 issq(25) #> true issq(25.0) #> true
  10. 第1問: 実際にある関数《補足 2》 予約語? • 「文字列が予約語かど うかを判定する関数」 は存在しない。 • 「Julia

    の識別子とし て利用できるかどう かを判定する関数」な ら存在する (Base.isidentifi er()) Base.isidentifier("x") #> true # 一部の予約語は `false` が返る(この場合(狭義の)リテラル) Base.isidentifier("true") #> false # 多くの予約語は `true` が返る(実は識別子として利用できる) Base.isidentifier("if") #> true
  11. 第1問: 実際にある関数《補足 3》 プリミティブ型 • 「Julia 組み込みの型 かどうかを判定する 関数」はない。 •

    isprimitivetype( ) という関数はある が、プリミティブ型(原 始型)は 組み込み型 のことではない。 isprimitivetype(Int) # Julia の `Int` 型はプリミティブ型 #> true isprimitivetype(String) # `String` 型はプリミティブ型ではない #> false # 24ビットの整数型を定義してみた primitive type Int24 <: Signed 24 end isprimitivetype(Int24) #> true
  12. 第2問: 実際にはない関数・機能 以下のうち、Julia 標準には 存在しない 関数・機能はどれ? 1. 数値を 0から遠い方へ丸める RoundingMode

    2. 数値の 4乗根を返す演算子 3. 対数スケールで等間隔の数列(=等比数列)を生成する関数 4. イテレータを連結する 関数
  13. 第2問: 実際にはない関数・機能《解答》 以下のうち、Julia 標準には 存在しない 関数・機能はどれ? 1. 数値を 0から遠い方へ丸める RoundingMode

    2. 数値の 4乗根を返す演算子 3. 対数スケールで等間隔の数列(=等比数列)を生成する関数 4. イテレータを連結する 関数
  14. 第2問: 実際にはない関数・機能《解説》 logrange() • 『対数スケールで等間 隔の数列(=等比数 列)を生成する関数』 は Julia v1.10

    には まだない。 • Julia v1.11 から そ のような関数 logrange(start, stop, length) が 追加される模様。 ◦ v1.11-RC1 には少な くとも入っています。 @assert VERSION ≥ v"1.11.0-" # この時点でエラーが出たら以下は動作しない logrange(10, 4000, length=3) #> 3-element Base.LogRange{Float64, Base.TwicePrecision{Float64}}: #> 10.0, 200.0, 4000.0 logrange(1, 1000, 4) ≈ 10 .^ (0:3) #> true
  15. 第2問: 実際にはない関数・機能《補足 1》 RoundFromZero • RoundFromZero はそ の名の示すとおり「ゼロ から遠い方に丸める」丸 めモード。

    ◦ round(v, RoundFromZero) は v < 0 ? floor(v) : ceil(v) と等価 • 実は Julia v0.x の時 代からあるにはあった。 ◦ v1.8 までは BigFloat だけに対応 していた。 round(1.1, RoundFromZero) # == ceil(1.1) #> 2.0 round(-1.1, RoundFromZero) # == floor(-1.1) #> -2.0
  16. 第2問: 実際にはない関数・機能《補足 2》 ∜ 演算子 • ∜ 演算子 (fourthroot() 関

    数)は Julia v1.10 で追加。 • √(sqrt())、∛ (cbrt())と同様に扱 える。 ∜2 # == fourthroot(2) #> 1.189207115002721 2∜2 # == 2 * fourthroot(2) #> 2.378414230005442
  17. 第2問: 実際にはない関数・機能《補足 3》 Iterators.flatten() • Iterators.flatte n() は、引数に イテ レータを列挙するイテ

    レータ を受け取り 各 イテレータの列挙する 要素を列挙するイテ レータ を返す関数。 • つまり引数に「連結し たいイテレータを並べ たタプル」を渡せば、 それを連結したイテ レータが返ってくる。 Iterators.flatten(( 1:3, (:a, :b, :c), "あいうえお" )) |> collect #> [1, 2, 3, :a, :b, :c, 'あ', 'い', 'う', 'え', 'お']
  18. 第3問: 文字列以外の replace() (1) 次のうち、動作するものを すべて選べ(複数回答) 1. replace([1, 2, 3],

    1=>100) 2. replace((1, 2, 3), 1=>100) 3. replace(Set([1, 2, 3]), 1=>100) 4. replace(Dict(:a=>1, :b=>2, :c=>3), 1=>100)
  19. 第3問: 文字列以外の replace() (1)《解答》 次のうち、動作するものを すべて選べ(複数回答) 1. replace([1, 2, 3],

    1=>100) 2. replace((1, 2, 3), 1=>100) 3. replace(Set([1, 2, 3]), 1=>100) 4. replace(Dict(:a=>1, :b=>2, :c=>3), 1=>100)
  20. 第3問: 文字列以外の replace() (1)《解説 1》 • replace() は、一般 的なコレクション型の 多くで動作するよう多

    重定義されている。 • 配列(Array)・タプル (Tuple)・集合(Set) などは右の通り。 replace([1, 2, 3], 1=>100) #> [100, 2, 3] replace((1, 2, 3), 1=>100) #> (100, 2, 3) replace(Set([1, 2, 3]), 1=>100) #> Set([2, 3, 100])
  21. 第3問: 文字列以外の replace() (1)《解説 2》 • replace() は辞書 (Dict)でも右のよう にすれば動作する

    • 名前付きタプル (NamedTuple)には 非対応。 # ↓これだと `«old»=>«new»` が型が合わないためエラー replace(Dict(:a=>1, :b=>2, :c=>3), 1=>100) #! MethodError # ↓これならエラーにならない replace(Dict(:a=>1, :b=>2, :c=>3), (:a=>1)=>(:a=>100)) #> Dict(:a=>100, :b=>2, :c=>3) # NamedTuple には非対応 replace((a=1, b=2, c=3), (:a=>1)=>(:a=>100)) #! MethodError
  22. 第4問: 文字列以外の replace() (2) replace([1, 2, 3, 2], >(1)=>100) の実行結果は?

    1. [1, 100, 100, 100] 2. [1, 100, 3, 2] 3. [1, 2, 3, 2] 4. MethodError が発生
  23. 第4問: 文字列以外の replace() (2)《解答》 replace([1, 2, 3, 2], >(1)=>100) の実行結果は?

    1. [1, 100, 100, 100] 2. [1, 100, 3, 2] 3. [1, 2, 3, 2] 4. MethodError が発生
  24. 第4問: 文字列以外の replace() (2)《解説》 • replace(collectio n, «old»=>«new») は、collection 中に

    存在する «old» とい う要素を «new» に置 き換えるだけの機能。 • replace(«文字列», «関数»=>~) は、「その 関数に渡して true が 返ってくる文字を~に 置換する」という動きを する。 replace([1, 2, 3, 2], >(1)=>100) #> [1, 2, 3, 2] replace([1, isodd, 2, iseven], isodd=>100) #> [1, 100, 2, iseven] replace("1232", >('1')=>'X') #> "1XXX"
  25. 第5問: replace() の do ブロック構文 次のうち、動作するものを すべて選べ(複数回答) # 1. replace("ABC")

    do v v > 'A' ? 'X' : v end # 2. replace([1, 2, 3]) do v v > 1 ? 100 : v end # 3. replace(Set([1, 2, 3])) do v v > 1 ? 100 : v end # 4. replace(Dict(:a=>1, :b=>2, :c=>3)) do (k, v) k=>(v > 1 ? 100 : v) end
  26. 第5問: replace() の do ブロック構文《解答》 次のうち、動作するものを すべて選べ(複数回答) # 1. replace("ABC")

    do v v > 'A' ? 'X' : v end #! MethodError # 2. replace([1, 2, 3]) do v v > 1 ? 100 : v end #> [1, 100, 100] # 3. replace(Set([1, 2, 3])) do v v > 1 ? 100 : v end #> Set([1, 100]) # 4. replace(Dict(:a=>1, :b=>2, :c=>3)) do (k, v) k=>(v > 1 ? 100 : v) end #> Dict(:a=>1, :b=>100, :c=>100)
  27. 第5問: replace() の do ブロック構文《解説》 • replace(collecti on) do «old»;

    ~; end は、do ブ ロックの戻り値に従っ て要素を置換 する。 • replace(«文字列») do ~ はサポートさ れていない。 replace([1, 2, 3]) do v v > 1 ? 100 : v end #> [1, 100, 100] replace("ABC") do v v > 'A' ? 'X' : v end #! MethodError
  28. 第5問: replace() の do ブロック構文《補足》 • 配列に対する replace(arr) do v

    ~ は実質 map(arr) do v ~ と同等。 • 配列以外のコレクションに対 する replace(collection) do ~ は map() の代わり に「要素を加工して新しい (同じ型の)コレクションを生 成」する目的にも使える。 • 破壊的関数 replace!(~) を使えばコレクションの更新 も可能。 dic = Dict(v=>v for v=0:3); replace!(dic) do (k, v) (k - k % 2)=>v end; dic #> Dict(0=>1, 2=>3) # ↑どうしてこうなるか考えてみよう!
  29. 第6問: pairs() 以下の説明について 誤っているもの はどれか? 1. Julia では enumerate(arr) より

    pairs(arr) が推奨される。 2. pairs(arr)(arr isa AbstractVector)は、配列(ベクトル)のインデックス と値の タプルを列挙するイテレータを返す。 3. pairs(IndexLinear(), arr)(arr は2次元以上の配列)という書き方もで きる。 4. pairs(dict)(dict isa Dict)は、引数に渡した辞書 dict そのものを返 す。
  30. 第6問: pairs() 《解答》 以下の説明について 誤っているもの はどれか? 1. Julia では enumerate(arr)

    より pairs(arr) が推奨される。 2. pairs(arr)(arr isa AbstractVector)は、配列(ベクトル)のインデックス と値の タプルを列挙するイテレータを返す。 3. pairs(IndexLinear(), arr)(arr は2次元以上の配列)という書き方もで きる。 4. pairs(dict)(dict isa Dict)は、引数に渡した辞書 dict そのものを返 す。
  31. 第6問: pairs() 《解説 1》 • pairs(coll) は、 coll の「キー」と「値」 の

    ペア(Pair)を列挙 するイテレータを返す 関数。 • coll は配列だけで なく、keys(coll) が動作するもの なら 何でもOK(文字列も OK) eltype(pairs([1, 2, 3])) #> Pair{Int64, Int64} str = "あいう"; for (idx, chr) in pairs(str) @assert str[idx] == chr end # ↑ `enumerate(str)` だとこうはいかない
  32. 第6問: pairs() 《解説 2》 • pairs(«IndexStyl e», arr) のように 第1引数に

    インデック ススタイルを指定する ことも可能。 • Dict はそれ自体が キーと値のペアを列 挙するイテレータとし て動作するので、 pairs(dict::Dict ) は dict そのもの を返す。 pairs([1 2; 3 4]) |> collect #> [CartesianIndex(1, 1)=>1 CartesianIndex(1, 2)=>2 #> CartesianIndex(2, 1)=>3 CartesianIndex(2, 2)=>4] pairs(IndexLinear(), [1 2; 3 4]) |> collect #> [1=>1 3=>2 #> 2=>3 4=>4] pairs(Dict(:a=>1, :b=>2)) == Dict(:a=>1, :b=>2) #> true
  33. 第7問: => (1) print(=>) の実行結果は? 1. 「=>」が出力される 2. 「Pair」が出力される 3.

    「Tuple」が出力される 4. 文法エラー(ParseError) 第8問: => (2) a=>b=>c の実行結果は? 1. (a=>b)=>c (左結合) 2. a=>(b=>c) (右結合) 3. (a, b, c) (3値タプル) 4. 文法エラー(ParseError)
  34. 第7問: => (1) 《解答》 print(=>) の実行結果は? 1. 「=>」が出力される 2. 「Pair」が出力される

    3. 「Tuple」が出力される 4. 文法エラー(ParseError) 第8問: => (2) 《解答》 a=>b=>c の実行結果は? 1. (a=>b)=>c (左結合) 2. a=>(b=>c) (右結合) 3. (a, b, c) (3値タプル) 4. 文法エラー(ParseError)
  35. 第7, 8問: => 《解説》 • =>(ペア演算子)は、実は Pair 型のエイリアス! a =>

    b は Pair(a, b) と同じ意味 になる。タプ ルではない。 • Julia の => は文法要素 ではなく純粋に演算子。 なので print(=>) など というコードも別にエラー にならない。 • 右結合 となっており a=>b=>c は a=>(b=>c) と同等となる。 print(=>) ## Pair (:a => 1) === Pair(:a, 1) #> true (:a => (:b => :c)) == (:a => :b => :c) != ((:a => :b) => :c) #> true (:a => :b => :c) != (:a, :b, :c) #> true
  36. 第9問: 標準ライブラリ(標準パッケージ) (1) Julia 標準パッケージについて正しい説明はどれ? 1. ArgTools は コマンドライン引数を扱う パッケージ

    2. Dates パッケージで扱える日付の最大値は 146138512年12月31日 である 3. Tar パッケージは .tar.gz ファイルは扱えない 4. UUIDs パッケージは最新の uuidv7 にも対応済 である
  37. 第9問: 標準ライブラリ(標準パッケージ) (1)《解答》 Julia 標準パッケージについて正しい説明はどれ? 1. ArgTools は コマンドライン引数を扱う パッケージ

    2. Dates パッケージで扱える日付の最大値は 146138512年12月31日 である 3. Tar パッケージは .tar.gz ファイルは扱えない 4. UUIDs パッケージは最新の uuidv7 にも対応済 である
  38. 第9問: 標準ライブラリ(標準パッケージ) (1)《解説》 • ArgTools は ファイル入出力やデータ処理のためのユーティリ ティパッケージ。 • typemax(Dates.Date)

    == Date(252522163911149, 12, 31)  • Tar パッケージは tarball を扱えるが、各種圧縮形式には対応 していない。 • UUIDs で最新の uuidv7 がサポートされるのは Julia v1.12 以降の予定(nightly build では利用できる)。
  39. 第10問: 標準ライブラリ(標準パッケージ) (2) Julia 標準パッケージについて 誤っている 説明はどれ? 1. using Downloads

    しなくても download() 関数は利用でき る(ただし機能制限がある) 2. Printf の @printf マクロでは 動的精度(桁数等)は扱えない 3. Profiling は CPU と メモリ のプロファイリング に対応している 4. Random パッケージは ランダム文字列の生成にも対応 している
  40. 第10問: 標準ライブラリ(標準パッケージ) (2)《解答》 Julia 標準パッケージについて 誤っている 説明はどれ? 1. using Downloads

    しなくても download() 関数は利用でき る(ただし機能制限がある) 2. Printf の @printf マクロでは 動的精度(桁数等)は扱えない 3. Profiling は CPU と メモリ のプロファイリング に対応している 4. Random パッケージは ランダム文字列の生成にも対応 している
  41. • Printf の書式文字列 が Julia v1.10 から 拡張され、%*s や %*.*f

    などの書式で 動的幅/動的精度 が サポートされた。 第10問: 標準ライブラリ(標準パッケージ) (2)《解説》 using Printf let ss=["あ","いう","えおか"] maxw = maximum(textwidth.(ss)) for s=ss @printf("%*s\n", maxw, s) end end ## あ ## いう ## えおか