Julia體驗 語言基礎

之前據說過Julia,不過那時候官網還處於時不時宕機狀態,最近Julia發佈了1.0 released版本處處都是它的資訊,官網良心自帶簡體中文,趁着熱度我也來試試,順便聊記一二。git

關於Julia

Julia源於用戶需求。用戶但願有一門開源的腳本編程語言,有C的高性能,Ruby的靈活,Lisp的宏,Matlab那樣親切的數學表達式符號。它既能夠像Python同樣做爲通用編程語言,也能夠像R同樣用於統計分析,像Perl同樣天然的處理字符串,像Matlab同樣強大的線性代數,像Shell同樣的膠着其餘程序。
簡而言之,它什麼都想,什麼都像...
官方給出的Julia有如下特性(省略了一些):github

  • 快速:Julia能夠經過LLVM而跨平臺被編譯成高效的本地代碼。
  • 通用:Julia使用多分派做爲編程範式,使其很容易表達面向對象和函數式編程範式。
  • 動態:Julia是動態類型的,與腳本語言相似
  • 數值計算:Julia擅長於數值計算,它的語法適用於數學計算,支持多種數值類型,而且支持並行計算。
  • 可選的類型標註:Julia擁有豐富的數據類型描述
  • 可組合:Julia的包能夠很天然的組合運行。單位數量的矩陣或數據表一列中的貨幣和顏色能夠一塊兒組合使用而且擁有良好的性能。

變量和字符串

Julia內建支持大數運算,不須要調用函數。同時也支持unicode正則表達式

julia> 83275689127389671289376897238976*895623897689127389068912376897289/3487689234768972893+28358923785-23895728937
-3.4911515696355016e18

julia> unicode_var = "你好,中國"
"你好,中國"

julia> 'g'
'g': ASCII/Unicode U+0067 (category Ll: Letter, lowercase)

julia> λ =  "special_variable_name"
"special_variable_name"

julia> λ =  "redefine its value since it's a variable"
"redefine its value since it's a variable"

字符串會處理轉義字符,若是想保留它們須要在前面加上raw編程

julia> println("hello\nworld")
hello
world

julia> println(raw"hello\nworld")
hello\nworld

還能夠經過下標運算取到對應字符,最後一個字符用end指代,這可是下標竟然不是從0開始的!app

julia> welcome[0]
ERROR: BoundsError: attempt to access "hello world"
  at index [0]

julia> welcome[1]
  'h': ASCII/Unicode U+0068 (category Ll: Letter, lowercase)

julia> welcome[end]
'd': ASCII/Unicode U+0064 (category Ll: Letter, lowercase)

還可使用切片操做welcome[2:4]獲取子字符串ello
拼接字符串須要用string(str1,str2.,..)或者*,不能使用+編程語言

若是要對字符串進行內部求值(官方術語interpolation),須要使用$(xx)的語法:ide

julia> "3+2-5=$(3+2-5)"
"3+2-5=0"

julia> name = "yang"
"yang"

julia> "hello, $name"
"hello, yang"

Julia目標稱但願有Perl同樣強大的字符串處理能力,那麼內建正則表達式算是言出必行的表現。它的正則表達式是Perl兼容的,由PCRE提供,下面示例來自官方文檔:函數式編程

julia> r"^\s*(?:#|$)"
r"^\s*(?:#|$)"

julia> typeof(ans)
Regex

julia> m = match(r"(a|b)(c)?(d)", "acd")
RegexMatch("acd", 1="a", 2="c", 3="d")

julia> m.match
"acd"

julia> m.captures
3-element Array{Union{Nothing, SubString{String}},1}:
 "a"
 "c"
 "d"

常量

常量經過const關鍵字指定,不過常量還能重定義,REPL只顯示warning並不阻止這樣的作法,只有當重定義不一樣類型值的時候纔會提示Error。文檔強烈不建議重定義常量值。函數

julia> const a,b = 2,3
(2, 3)

julia> const a,b = 3,2
WARNING: redefining constant a
WARNING: redefining constant b
(3, 2)

julia> a,b
(3, 2)

julia> const a,b = 3.0,2
ERROR: invalid redefinition of constant a

類型

整型和浮點類型值不依賴於平臺,有明確的範圍:性能

Type Signed? Number of bits Smallest value Largest value
Int8 8 -2^7 2^7 - 1
UInt8 8 0 2^8 - 1
Int16 16 -2^15 2^15 - 1
UInt16 16 0 2^16 - 1
Int32 32 -2^31 2^31 - 1
UInt32 32 0 2^32 - 1
Int64 64 -2^63 2^63 - 1
UInt64 64 0 2^64 - 1
Int128 128 -2^127 2^127 - 1
UInt128 128 0 2^128 - 1
Bool N/A 8 false (0) true (1)
Type Precision Number of bits
Float16 half 16
Float32 single 32
Float64 double 64

變量的類型能夠經過typeof()獲取,大小可使用sizeof()獲取,二者能夠參數能夠是值也能夠是數據類型。

julia> typeof([1,2,4])
Array{Int64,1}

julia> typeof(0xcafebabe)
UInt32

julia> λ =  "special_variable_name"
"special_variable_name"

julia> typeof(λ)
String

julia> typeof(2e-2)
Float64

julia> typeof(Int)
DataType

julia> typeof(String)
DataType

julia> typeof(true)
Bool
julia> sizeof(2e-2)
8

julia> sizeof(Float16)
2

julia> sizeof(Int16(1024))
2

julia> sizeof("hello")
5

julia> sizeof([1,2,3])
24

運算

Julia主要用於數值優化,科學計算等,表達式貼近數學符號。除了平常四則運算外還有平方運算2^10,以及一些新奇的運算符:

julia> √4
2.0

julia> √√16
2.0

julia> typeof(√) #看起來開根號是個sqrt的語法糖
typeof(sqrt)

julia> sqrt(4)
2.0

julia> 2(3+2)
10

julia> x=1
julia> x(x+1)#x放到前面會被解析爲可調用對象致使出錯
ERROR: MethodError: objects of type Int64 are not callable
julia> (x+1)x
2

運算符不少,官方文檔已有總結,這裏直接複製翻譯一下:

算術運算符 名稱 描述
+x unary plus 恆等運算
-x unary minus 求相反數
x + y binary plus 加法
x - y binary minus 減法
x * y times 乘法
x / y divide 除法
x ÷ y integer divide 整數除法,結果保留整數
x \ y inverse divide 等價於 y / x
x ^ y power 平方
x % y remainder 求餘
!x negation !true==false,反之亦然。 只用於bool
位運算符 Name
~x
x & y
x \| y
x ⊻ y 異或(⊻這個符號打出來不容易...)
x >>> y 邏輯 右移
x >> y 算術 右移
x << y 邏輯/算術左移 left
數值比較運算符 Name
== 相等
!=, 不相等
< 小於
<=, 小於等於
> 大於
>=, 大於等於

另外Julia有一個特性,能夠進行鏈式比較

julia> 1 < x < 6
true

不用像大多數語言x>1 && x<6那樣手動邏輯組合。

以前介紹說Julia但願有像Matlab同樣強大的線性代數處理表達能力,固然少不了線性代數運算了。可使用.Operator進行向量運算

julia> [1,2,3].^ 2
3-element Array{Int64,1}:
 1
 4
 9

julia> [1,2,3].+ 2
3-element Array{Int64,1}:
 3
 4
 5

julia> [1,2,3].÷ 2
3-element Array{Int64,1}:
 0
 1
 1

最後Julia還支持分數和複數表示,這裏就不贅述了,感興趣的請參見Complex and Rational Numbers

函數和方法

Julia認爲函數是一個關聯實參tuple和一個返回值的對象。
第一種形式是完整的函數定義:

function add(a,b)
    x = a+b
    #return x 若是沒有return默認返回最後一個表達式求得的值
end

第二種是賦值形式的函數定義

add2(a,b) = a+b

函數在Julia被視做一等公民,能夠賦值給變量,能夠作參數,也能夠返回。

julia> apply = function(func,arg)
        func(arg)
        end
#269 (generic function with 1 method)

julia> apply(!,false)
true

上面例子中定義了一個匿名函數,即lambda,而後函數!做爲參數傳遞。lambda還能夠arg -> expr_body進行定義:

julia> lambda = val ->( "$val" * "$val","$val","...")
#317 (generic function with 1 method)

julia> lambda("wow")
("wowwow", "wow", "...")

注意lambda函數體的()表示tuple,它可讓函數返回多個值。

Julia支持指定參數類型,默認值以及關鍵字形參

julia> misc = function(a::Int,b::Int=2;flag=true)
       a+1,b+2,!flag
       end
#341 (generic function with 2 methods)

julia> misc(1,2,flag=false)
(2, 4, true)

這個小標題是函數和方法,那麼方法呢?其實在其餘不少語言中,方法是面向對象領域的函數的別稱。這裏Julia給了另外一種定義:

It is common for the same conceptual function or operation to be implemented quite differently for different types of arguments: adding two integers is very different from adding two floating-point numbers, both of which are distinct from adding an integer to a floating-point number. Despite their implementation differences, these operations all fall under the general concept of "addition". Accordingly, in Julia, these behaviors all belong to a single object: the + function. To facilitate using many different implementations of the same concept smoothly, functions need not be defined all at once, but can rather be defined piecewise by providing specific behaviors for certain combinations of argument types and counts. A definition of one possible behavior for a function is called a method.

方法是函數更具體的表現形式。若是學過C++那徹底能夠類比,函數就是模板函數,方法就是特化的函數模板。

控制流

Julia的控制流和其餘高級語言基本相似,這裏就直接給例子了。

  1. 複合表達式
julia> z = begin
    a=1
    b=2
    (a+b,a/b)
end
julia> z
(3, 0.5)
  1. 條件運算
#julia也提供  ?:  三元運算符
if flag && a<b
    println("a <b")
elseif flag && a==b
    println("a==b")
elseif flag && a<b
    println("a>b")
end
  1. while循環
julia> let i=0,res=0
           while i<=100
               res +=i
               i+=1
           end
           println(res)
       end
5050
  1. for循環
julia> for i=1:10
           print(i," ")
       end
1 2 3 4 5 6 7 8 9 10

julia> for name in ["Alice","Andrew","Jane"]
            print(name*" ")
       end
Alice Andrew Jane

julia> while true
       println(i)
       global i+=1
       if i<5
              continue
       else
              break
       end
end
5
  1. 異常處理
julia> throw("exception")
ERROR: "exception"
Stacktrace:
 [1] top-level scope at none:0
 ...


 julia> try
            sqrt(-1)
        catch y
            println(y)
           end
DomainError(-1.0, "sqrt will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).")

關於Julia的Task後面我可能會再寫一篇文章詳細說說。

做用域

模塊是現代軟件開發必不可少的成分,Julia也提供了對它的支持。使用module end便可建立一個模塊,import進行導入:

julia> module warehouse
       x = 1
       y = (arg,val) -> arg(arg(val))
       end
WARNING: replacing module warehouse.
Main.warehouse

julia> import .warehouse

julia> warehouse.y(+,2)
2

複合類型

使用struct ... end進行能夠建立一個複合類型,這就是Julia提供的面向對象的方法

struct Novel
       name::String
       author::String
       price::Float64

       # 構造函數
       Novel(name::String,author::String,price::Float64) = new(name,author,price)
end

function stringify(val::Novel)
       print("Novel{",val.name,",",val.author,",",val.price,"}")
end
ff = Novel("Gobacktoearth","yy",56.4)
stringify(ff)

Novel{Gobacktoearth,yy,56.4}

個人博客即將搬運同步至騰訊雲+社區,邀請你們一同入駐:https://cloud.tencent.com/developer/support-plan?invite_code=wsp9wvpm612x

相關文章
相關標籤/搜索