2019/05/27

Control Flow in Julia

conditional evaluation

compound expression,將一連串的 code 合併起來,確保會依照順序運算,除了換行的方式,還可以用 ; 區隔,寫在同一行

julia> volume = begin
          len = 10
          breadth = 20
          height = 30
          len * breadth * height
       end
6000

julia> volume = (length = 10; breadth = 20; height = 30; length * breadth * height)
6000

conditional evaluation

FizzBuzz algorithm,用 if, elseif, else 撰寫條件

for i in 1:30
   if i % 3 == 0 && i % 5 == 0
       println("FizzBuzz")
   elseif i % 3 == 0
       println("Fizz")
   elseif i % 5 == 0
       println("Buzz")
   else
       println(i)
   end
end

計算是否為質數的 function

function factors(num::Int64)
   factors = []
   for i in 1:num
       if rem(num, i) == 0
           push!(factors, i)
       end
   end
   return factors
end

function is_prime(num::Int64)
   factors_array = factors(num)
   if length(factors_array) == 2
       true
   else
       false
   end
end

if 區塊裡面的變數,在區塊外面還可以使用,這表示 if block 並沒有 local scope

function f(n)
   if n % 2 == 0
       parity = "even"
   else
       parity = "odd"
   end
   println("the number is $parity")
end

if block 結束時,會 return value

julia> x = if true
               2
       end
2

julia> x = if true
               println("test")
       end
test

julia> x == nothing
true

ternary operators

condition ? do this, if true : do this, if false

julia> name = "julia"
"julia"

julia> isa(name, String) ? "its a string" : "nopes, not a string"
"its a string"

short circuit evalation

  • var1 && var2,只有在 var1 為 true,才會運算 var2
  • var1 || var2,當 var1 為 false,才會運算 var2
julia> all(isdigit, "10") && println("reached me")
reached me

julia> all(isdigit, "ten") && println("reached me")
false

julia> all(isdigit, "ten") || println("reached me")
reached me

repeated evaluation

有兩種: while, for

collection = [1,2,3,4,5,6,7,8,9]
while length(collection) > 1
   pop!(collection)
   println(collection)
end

for

statement = "This is a great example!"
for word in split(statement)
   println(word)
end

# split 後,取第 2~4 個元素
for word in split(statement)[2:4]
   println(word)
end

for word in split(statement)[2:3:4]
   println(word)
end
# is

defining range

range expression 1:5

julia> for i in 1:5
          print("*",i,"\n", "\t"^i)
       end
*1
    *2
        *3
            *4
                *5

5:-1:1表示為 5 到 1,每一次 減1

julia> for i in 1:5
          for j in 1:i
              print("*")
          end
          println("")
       end
*
**
***
****
*****

julia> for i in 5:-1:1
          for j in 1:i
              print("*")
          end
          println("")
       end
*****
****
***
**
*

reverse a string

julia> my_string = "This is a great thing to do!"
"This is a great thing to do!"

julia> my_string[length(my_string):-1:1]
"!od ot gniht taerg a si sihT"

break and continue

word="julia"
for letter in word
   if letter == 'i'
       break
   end
   println(letter)
end

# continue 跳過此次迴圈,繼續下一個
for letter in word
   if letter == 'l'
       continue
   end
   println(letter)
end

Exception handling

error 跟 exception 的差異

error 是應該要避免的問題,程式不應該 catch error。程式已經知道可能會發生 exception,故在發生 exception 的條件中,可以 catch exception。

julia 提供多種 errors:

  • ArgumentError: 傳入 function 的參數,不是原本 function 期待的參數形式
  • AssertionError: 發生錯誤 (false) 的 assertion 檢查 statement
  • BoundsError: 嘗試存取 arrary 的 out-of-bounds element
  • DivideError: 除數為 0
  • DomainError: 參數在 valid domain 之外
  • EOFError: 已經到了 end of file,無法再讀取資料
  • InexactError: 再處理 exact type conversion 發生 failure
  • KeyError: 存取不存在的 key element
  • LoadError: loading file 發生 error
  • MethodError: 嘗試使用不存在的 methods
  • OutOfMemoryError: 記憶體不足
  • ReadOnlyMemoryError: 嘗試寫入 read-only memory
  • OverflowError: 當某個 operation 的 result 太大
  • ParseError: parsing expression 發生問題
  • StackOverflowError: function call 超過 call stack
  • SystemError: system call 發生 error
  • TypeError: type checking 發生 error, 傳給 function 錯誤資料型別的參數
  • UndefRefError: Unknown reference made
  • UndefVarError: Unknown reference made to a 不存在的 variable
  • InitError: 呼叫 module 的 __init__ 發生錯誤

julia 的 exception

  • ErrorException: 發生 error
  • InterruptException: 運算時發生 external interruption
  • NullException: 嘗試存取 Null
  • ProcessExitedException: process 已結束,使用 process 就會發生錯誤
julia> typeof(Exception)
DataType

julia> struct CustomException <: Exception
          var::Symbol
       end

julia> typeof(CustomException)
DataType

julia> supertype(CustomException)
Exception

throw(e)

呼叫時,會立即 throws an error

julia> throw("")
ERROR: ""
Stacktrace:
 [1] top-level scope at none:0

julia> throw(3+3)
ERROR: 6
Stacktrace:
 [1] top-level scope at none:0

julia> throw(ErrorException("error"))
ERROR: error
Stacktrace:
 [1] top-level scope at none:0

產生 TypeError

julia> function say_hi(name)
          try
              if typeof(name) != String
                  throw(TypeError(:say_hi, "printing name", String, name))
              else
                  println("hi $name")
              end
          catch e
              println(typeof(e))
          end
       end
say_hi (generic function with 1 method)

julia> say_hi('n')
TypeError

julia> say_hi("name")
hi name

error()

會產生 ErrorException

julia> function say_hi(name :: String)
               if length(name) < 5
                       error("Name less than 5!!!")
               else
                       println("hi $name")
               end
       end
say_hi (generic function with 2 methods)

julia> say_hi("joe")
ERROR: Name less than 5!!!
Stacktrace:
 [1] error(::String) at ./error.jl:33
 [2] say_hi(::String) at ./REPL[59]:3
 [3] top-level scope at none:0

try/catch/finally block

用 try-catch block 封裝程式碼,攔截任何可能發生的 error

julia> try
          exponent("alpha")
       catch e
          println(e)
       finally
          print("Goodbye")
       end
MethodError(exponent, ("alpha",), 0x00000000000061d2)
Goodbye

tasks in julia

Tasks 類似 coroutines 的功能,可 suspend an operation 並在需要時 resume

julia> function producer(c::Channel)
          put!(c, "start")
          for n=1:2
              put!(c, 2n)
          end
          put!(c, "stop")
       end;

julia> chnl = Channel(producer);

julia> take!(chnl)
"start"

julia> take!(chnl)
2

julia> take!(chnl)
4

julia> take!(chnl)
"stop"

julia> take!(chnl)
ERROR: InvalidStateException("Channel is closed.", :closed)

References

Learning Julia

沒有留言:

張貼留言