Julia快速入門(2)

lt發表於2017-03-27
####################################################
## 3. 控制流
####################################################

# 宣告一個變數
some_var = 5

# 這是一個 if 語句,縮排不是必要的
if some_var > 10
    println("some_var is totally bigger than 10.")
elseif some_var < 10    # elseif 是可選的.
    println("some_var is smaller than 10.")
else                    # else 也是可選的.
    println("some_var is indeed 10.")
end
# => prints "some var is smaller than 10"


# For 迴圈遍歷
# Iterable 型別包括 Range, Array, Set, Dict, 以及 String.
for animal=["dog", "cat", "mouse"]
    println("$animal is a mammal")
    # 可用 $ 將 variables 或 expression 轉換為字串into strings
end
# prints:
#    dog is a mammal
#    cat is a mammal
#    mouse is a mammal

# You can use 'in' instead of '='.
for animal in ["dog", "cat", "mouse"]
    println("$animal is a mammal")
end
# prints:
#    dog is a mammal
#    cat is a mammal
#    mouse is a mammal

for a in ["dog"=>"mammal","cat"=>"mammal","mouse"=>"mammal"]
    println("$(a[1]) is a $(a[2])")
end
# prints:
#    dog is a mammal
#    cat is a mammal
#    mouse is a mammal

for (k,v) in ["dog"=>"mammal","cat"=>"mammal","mouse"=>"mammal"]
    println("$k is a $v")
end
# prints:
#    dog is a mammal
#    cat is a mammal
#    mouse is a mammal

# While 迴圈
x = 0
while x < 4
    println(x)
    x += 1  # x = x + 1
end
# prints:
#   0
#   1
#   2
#   3

# 用 try/catch 處理異常
try
   error("help")
catch e
   println("caught it $e")
end
# => caught it ErrorException("help")


####################################################
## 4. 函式
####################################################

# 用關鍵字 'function' 可建立一個新函式
#function name(arglist)
#  body...
#end
function add(x, y)
    println("x is $x and y is $y")

    # 最後一行語句的值為返回
    x + y
end

add(5, 6) # => 在 "x is 5 and y is 6" 後會列印 11

# 還可以定義接收可變長引數的函式
function varargs(args...)
    return args
    # 關鍵字 return 可在函式內部任何地方返回
end
# => varargs (generic function with 1 method)

varargs(1,2,3) # => (1,2,3)

# 省略號 ... 被稱為 splat.
# 剛剛用在了函式定義中
# 還可以用在函式的呼叫
# Array 或者 Tuple 的內容會變成引數列表
Set([1,2,3])    # => Set{Array{Int64,1}}([1,2,3]) # 獲得一個 Array 的 Set
Set([1,2,3]...) # => Set{Int64}(1,2,3) # 相當於 Set(1,2,3)

x = (1,2,3)     # => (1,2,3)
Set(x)          # => Set{(Int64,Int64,Int64)}((1,2,3)) # 一個 Tuple 的 Set
Set(x...)       # => Set{Int64}(2,3,1)


# 可定義可選引數的函式
function defaults(a,b,x=5,y=6)
    return "$a $b and $x $y"
end

defaults('h','g') # => "h g and 5 6"
defaults('h','g','j') # => "h g and j 6"
defaults('h','g','j','k') # => "h g and j k"
try
    defaults('h') # => ERROR: no method defaults(Char,)
    defaults() # => ERROR: no methods defaults()
catch e
    println(e)
end

# 還可以定義鍵值對的引數
function keyword_args(;k1=4,name2="hello") # note the ;
    return ["k1"=>k1,"name2"=>name2]
end

keyword_args(name2="ness") # => ["name2"=>"ness","k1"=>4]
keyword_args(k1="mine") # => ["k1"=>"mine","name2"=>"hello"]
keyword_args() # => ["name2"=>"hello","k1"=>4]

# 可以組合各種型別的引數在同一個函式的引數列表中
function all_the_args(normal_arg, optional_positional_arg=2; keyword_arg="foo")
    println("normal arg: $normal_arg")
    println("optional arg: $optional_positional_arg")
    println("keyword arg: $keyword_arg")
end

all_the_args(1, 3, keyword_arg=4)
# prints:
#   normal arg: 1
#   optional arg: 3
#   keyword arg: 4

# Julia 有一等函式
function create_adder(x)
    adder = function (y)
        return x + y
    end
    return adder
end

# 這是用 "stabby lambda syntax" 建立的匿名函式
(x -> x > 2)(3) # => true

# 這個函式和上面的 create_adder 一模一樣
function create_adder(x)
    y -> x + y
end

# 你也可以給內部函式起個名字
function create_adder(x)
    function adder(y)
        x + y
    end
    adder
end

add_10 = create_adder(10)
add_10(3) # => 13


# 內建的高階函式有
map(add_10, [1,2,3]) # => [11, 12, 13]
filter(x -> x > 5, [3, 4, 5, 6, 7]) # => [6, 7]

# 還可以使用 list comprehensions 替代 map
[add_10(i) for i=[1, 2, 3]] # => [11, 12, 13]
[add_10(i) for i in [1, 2, 3]] # => [11, 12, 13]

####################################################
## 5.  型別
####################################################

# Julia 有型別系統
# 所有的值都有型別;但變數本身沒有型別
# 你可以用 `typeof` 函式獲得值的型別
typeof(5) # => Int64

# 型別是一等值
typeof(Int64) # => DataType
typeof(DataType) # => DataType
# DataType 是代表型別的型別,也代表他自己的型別

# 型別可用作文件化,優化,以及排程
# 並不是靜態檢查型別

# 使用者還可以自定義型別
# 跟其他語言的 records 或 structs 一樣
# 用 `type` 關鍵字定義新的型別

# type Name
#   field::OptionalType
#   ...
# end
type Tiger
  taillength::Float64
  coatcolor # 不附帶型別標註的相當於 `::Any`
end

# 建構函式引數是型別的屬性
tigger = Tiger(3.5,"orange") # => Tiger(3.5,"orange")

# 用新型別作為建構函式還會建立一個型別
sherekhan = typeof(tigger)(5.6,"fire") # => Tiger(5.6,"fire")

# struct 類似的型別被稱為具體型別
# 他們可被例項化但不能有子型別
# 另一種型別是抽象型別

# abstract Name
abstract Cat # just a name and point in the type hierarchy

# 抽象型別不能被例項化,但是可以有子型別
# 例如,Number 就是抽象型別
subtypes(Number) # => 6-element Array{Any,1}:
                 #     Complex{Float16}
                 #     Complex{Float32}
                 #     Complex{Float64}
                 #     Complex{T<:Real}
                 #     ImaginaryUnit
                 #     Real
subtypes(Cat) # => 0-element Array{Any,1}

# 所有的型別都有父型別; 可以用函式 `super` 得到父型別.
typeof(5) # => Int64
super(Int64) # => Signed
super(Signed) # => Real
super(Real) # => Number
super(Number) # => Any
super(super(Signed)) # => Number
super(Any) # => Any
# 所有這些型別,除了 Int64, 都是抽象型別.

# <: 是型別整合操作符
type Lion <: Cat # Lion 是 Cat 的子型別
  mane_color
  roar::String
end

# 可以繼續為你的型別定義建構函式
# 只需要定義一個同名的函式
# 並呼叫已有的建構函式設定一個固定引數
Lion(roar::String) = Lion("green",roar)
# 這是一個外部建構函式,因為他再型別定義之外

type Panther <: Cat # Panther 也是 Cat 的子型別
  eye_color
  Panther() = new("green")
  # Panthers 只有這個建構函式,沒有預設建構函式
end
# 使用內建建構函式,如 Panther,可以讓你控制
# 如何構造型別的值
# 應該儘可能使用外部建構函式而不是內部建構函式