Julia 方法

为了更好的能够采用相同的概念产生不同的行为,函数就需要在不同的位置进行定义,根据不同的类和常数,产生不同的行为。函数(function)的一个可能的行为(behavior),称为一个方法(method)。选择函数执行哪种方法称为派发,Julia可以通过 函数声明个数以及声明类型来执行派发。 通过函数所有声明来选择派发,而不是通过第一个声明,称为多重派发。

方法冲突

	g(x::Float64, y) = x^2+y  # y 没有指定类
    g(x,y::Float64)=x+y  #x没有指定类
    g(3.0,2.0)  # MethodError: g(::Float64, ::Float64) is ambiguous. Candidates:
  							g(x, y::Float64) in Main at In[3]:1
  							g(x::Float64, y) in Main at In[1]:1
							Possible fix, define
  							g(::Float64, ::Float64)
  g(x::Float64, y::Float64) = x-y
  g(3.0,2.0) # 1.0

参数化方法

和类一样,方法也可以参数化

same_type(x::T,y::T) where {T} = True
same_type(x,y) = False

same_type(3,0.5) #False

刚方法通过参数化类可以实现判断两个变量属不属于相同的类。

myappend(v::Vector{T}, y::T) where{T} = [v..., y]
myappend([2,3,4],3) # 2,3,4,3

可以实现同种类型变量数组的追加。其中 … 代表任意长度数组。
比如,想实现不同长度数组和变量之间的求和,可以通过定义

	add(x...) = reduce(+, x)
	add([3,2,1]..., 1) # 7

其中reduce也是一个特别实用的函数,它提供了对某一集合itr,在初始条件init下实行运算op的功能,reduce(op, itr; dims=: ; [init])

	reduce(+,[2,3,4]) #9
	reduce(+, [2,3,4];  init=10) #19
	a=reshape(Vector(1:16), (4,4))
	reduce(max, a; dims=2) # 15,16

跑题了

通过参数化可以了解很多内部函数实现的思路,比如

mytypeof(a::T) where {T} = T
mytypeof(32) # Int64

可以实现typeof功能。
当然,在类型声明里也可以给出子类型限制条件,比如

same_type_num(x::T, y::T) where{T<:Number} = true
same_type_num(x::Number, y::Number) = false
same_type_num(3,2) #true
same_type_numeric(Int32(1), Int64(2)) #false

方法重新定义 (基本没看懂)

当重新定义一个方法或者增加一个方法时,为了稳定编译和提高效率,这些更改并非立即生效的。

function tryE()
@eval newfun2()=3
newfun2()
end
tryE # MethodError: no method matching newfun2()

直到第二次执行才会正确,如果想立即生效,可以通过

function tryeval2()
          @eval newfun2() = 2
          Base.invokelatest(newfun2)
end

另外一个例子

	f1(x) = "Origin method"
	g1(x) = f1(x)	
	t = @async f1(wait()); yield();
f1(x::Int)="A new method"
f1(x::Type{Int}) = "defination for Type{int}"
f1(1) "A new method"
g(1) "A new method"
fetch(schedule(t, 1)) #Origin method

t = @async f(wait()); yield();
fetch(schedule(t, 1)) #" A new method)

其中fetch函数是抓取 宏async 将Task中的表达式打包并放入机器列表(scheduler)里。其中Task 是执行指定函数命令,如

 a() = sum(I for I in 1:100)
 b = Task(a);

这里面b就是一个尚未运行的可执行的Task。

迭代派发

为了能够派发一个多层参数化的命令,最好的办法是将每一层放在独立的函数里进行派发。例如,派发单元类的数组,经常会出现混乱的状况。通常的做法是首先将它派发给存储类(container type)然后在循环进基于元素类(eltype)的方法里。 多数情况下,算法会自动执行这种分级操作,但某些情况可能需要自己手动执行这些规则。例如求解矩阵加法的逻辑

+(a::Matrix, b::Matrix)  = map(+, a, b) #通过map算法进行派发
+(a,b) = +(promote(a,b)...)   #将不同类型的元素进行统一

下面还有很多,看不大懂。。。 先这么多吧。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值