今天简单介绍一下:来自其他动态类型语言的Julia的新用户可能会编写如下函数。
函数foo(X)If x Isa Int x+x Else If x Isa Float64 x/2.0 Else If x Isa字符串长度(X)Else 1 End End。
Bar(x::int)=x+x bar(x::Float64)=x/2.0 bar(x::string)=length(X)bar(X)=1#or bar(x::any),具体而言。
因为它的可读性更好,并且很容易扩展到其他类型的x。从技术上讲,您可以用与bar相同的方式扩展foo,但是阅读foo的定义就会知道它的完整行为,所以这会产生误导。(=。
然而,我的观点是,实际上(可能令人惊讶的是)在运行时对代码没有危害,就像在foo中一样!Julia编译器没有那么容易上当,它仍然会为每种类型的参数生成最优的机器码:
Julia>;@code_ative debuginfo=:NONE BAR(1)。Text leaq(%rdi,%rdi),%rax retq nopw%cs:(%rax,%rax)julia>;@code_ative debuginfo=:NONE foo(1)。文本leaq(%rdi,%rdi),%rax req nopw%cs:(%rax,%rax)。
这两个函数基本上都编译成一条加法指令(leaq;retq用于从函数返回,nopw是一个什么也不做的操作,因为技术原因而存在)。可以这样想:当Julia编译foo(1)时,它知道1是Int类型,可以在编译时将x Isa Int表达式求值为true,然后毫不费力地丢弃除x+x之外的所有内容。
Julia>;@code_ative debuginfo=:NONE BAR(1.0)。文本移动$140581530607976,%rax#IMM=0x7FDBB031A168 vmulsd(%rax),%xmm0,%xmm0 retq NOP julia>;@CODE_NATIVE DEBUGINFO=:NONE FOO(1.0)。文本移动$140581530608088,%rax#IMM=0x7FDBB031A1D8 vmulsd(%rax),%xmm0,%xmm0 retq NOP julia>;@CODE_NATIVE DEBUGINO=:NONE BAR(";abc";)。文本推送%rax movabsiq$";ncodeunit;";,%rax callq*%rax popq%rcx retq nop julia>;@code_ative debuginfo=:NONE foo(";abc";)。文本推送%rax movabsiq$";ncodeunit;";,%rax callq*%rax popq%rcx retq NOP Julia>;@code_ative debuginfo=:NONE BAR([])。文本移动$1,%eax retq nopw%cs:(%rax,%rax)julia>;@code_ative debuginfo=:NONE foo([])。文本移动$1,%eax REQ NOPW%cs:(%rax,%rax)