Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Julia method


May 14, 2021 Julia


Table of contents


Method

As mentioned in the function , functions are objects that map from parameter polymethgroups to return values, throwing exceptions if there is no suitable return value. I n practice, it is often necessary to do the same operations on different types of parameters, such as addition to integers, additions to floating points, additions to integers and floating points, all of which are additions. In Julia, they all belong to the same object: +

When you make a series of implementations of the same concept, you can define the specific function behavior corresponding to a specific parameter type and number of numbers one by one. thod is a definition of a particular behavior in a function. Y ou can define more than one method in a function. When a function is called for a specific parameter polysygroup, the method that best matches this parameter polymethgroup is called.

When a function is called, choose which method to call, called overloaded. Julia overloads based on the number and type of parameters.

Define the method

All of Julia's standard functions and operators, such as the + mentioned earlier, have many methods defined for a variety of parameter types and different numbers of parameters.

When you define a function, you can selectively restrict the :: type assertion operator, as described in Composite Types:

julia> f(x::Float64, y::Float64) = 2x + y;

The parameters x and y can only be Float64 types:

    julia> f(2.0, 3.0)
    7.0

If the argument is of another type, a "no method" error is raised:

    julia> f(2.0, 3)
    ERROR: `f` has no method matching f(::Float64, ::Int64)

    julia> f(float32(2.0), 3.0)
    ERROR: `f` has no method matching f(::Float32, ::Float64)

    julia> f(2.0, "3.0")
    ERROR: `f` has no method matching f(::Float64, ::ASCIIString)

    julia> f("2.0", "3.0")
    ERROR: `f` has no method matching f(::ASCIIString, ::ASCIIString)

Sometimes you need to write some generic methods, when you should declare the parameters to be abstract types:

    julia> f(x::Number, y::Number) = 2x - y;

    julia> f(2.0, 3)
    1.0

To define more than one method for a function, you only need to define the function multiple times, with different numbers and types of arguments defined at a time. When a function is called, the most matching method is overloaded:

    julia> f(2.0, 3.0)
    7.0

    julia> f(2, 3.0)
    1.0

    julia> f(2.0, 3)
    1.0

    julia> f(2, 3)
    1

For non-numeric values, or arguments with fewer than 2, f undefined, and calling it returns a "no method" error:

    julia> f("foo", 3)
    ERROR: `f` has no method matching f(::ASCIIString, ::Int64)

    julia> f()
    ERROR: `f` has no method matching f()

By entering the function object itself in an interactive session, you can see how the function exists:

    julia> f
    f (generic function with 2 methods)

This output tells f is a function object with two methods. To find out the signature of these methods, you can do this methods function:

    julia> methods(f)
    # 2 methods for generic function "f":
    f(x::Float64,y::Float64) at none:1
    f(x::Number,y::Number) at none:1

This f that f has two methods, one with Float64 types as arguments and the other with Number type as argument. It also indicates the number of files and rows that define the method: because these methods are defined in rePL, we get the obvious line none:1

If you do not use :: type, the type of method parameter defaults to Any Define an omnibus match method for f

    julia> f(x,y) = println("Whoa there, Nelly.");

    julia> f("foo", 1)
    Whoa there, Nelly.

The method of omnibus matching is the last choice when overloading.

Overloading is Julia's most powerful and core feature. Core operations generally have dozens of methods:

    julia> methods(+)
    # 125 methods for generic function "+":
    +(x::Bool) at bool.jl:36
    +(x::Bool,y::Bool) at bool.jl:39
    +(y::FloatingPoint,x::Bool) at bool.jl:49
    +(A::BitArray{N},B::BitArray{N}) at bitarray.jl:848
    +(A::Union(DenseArray{Bool,N},SubArray{Bool,N,A<:DenseArray{T,N},I<:(Union(Range{Int64},Int64)...,)}),B::Union(DenseArray{Bool,N},SubArray{Bool,N,A<:DenseArray{T,N},I<:(Union(Range{Int64},Int64)...,)})) at array.jl:797
    +{S,T}(A::Union(SubArray{S,N,A<:DenseArray{T,N},I<:(Union(Range{Int64},Int64)...,)},DenseArray{S,N}),B::Union(SubArray{T,N,A<:DenseArray{T,N},I<:(Union(Range{Int64},Int64)...,)},DenseArray{T,N})) at array.jl:719
    +{T<:Union(Int16,Int32,Int8)}(x::T<:Union(Int16,Int32,Int8),y::T<:Union(Int16,Int32,Int8)) at int.jl:16
    +{T<:Union(Uint32,Uint16,Uint8)}(x::T<:Union(Uint32,Uint16,Uint8),y::T<:Union(Uint32,Uint16,Uint8)) at int.jl:20
    +(x::Int64,y::Int64) at int.jl:33
    +(x::Uint64,y::Uint64) at int.jl:34
    +(x::Int128,y::Int128) at int.jl:35
    +(x::Uint128,y::Uint128) at int.jl:36
    +(x::Float32,y::Float32) at float.jl:119
    +(x::Float64,y::Float64) at float.jl:120
    +(z::Complex{T<:Real},w::Complex{T<:Real}) at complex.jl:110
    +(x::Real,z::Complex{T<:Real}) at complex.jl:120
    +(z::Complex{T<:Real},x::Real) at complex.jl:121
    +(x::Rational{T<:Integer},y::Rational{T<:Integer}) at rational.jl:113
    +(x::Char,y::Char) at char.jl:23
    +(x::Char,y::Integer) at char.jl:26
    +(x::Integer,y::Char) at char.jl:27
    +(a::Float16,b::Float16) at float16.jl:132
    +(x::BigInt,y::BigInt) at gmp.jl:194
    +(a::BigInt,b::BigInt,c::BigInt) at gmp.jl:217
    +(a::BigInt,b::BigInt,c::BigInt,d::BigInt) at gmp.jl:223
    +(a::BigInt,b::BigInt,c::BigInt,d::BigInt,e::BigInt) at gmp.jl:230
    +(x::BigInt,c::Uint64) at gmp.jl:242
    +(c::Uint64,x::BigInt) at gmp.jl:246
    +(c::Union(Uint32,Uint16,Uint8,Uint64),x::BigInt) at gmp.jl:247
    +(x::BigInt,c::Union(Uint32,Uint16,Uint8,Uint64)) at gmp.jl:248
    +(x::BigInt,c::Union(Int64,Int16,Int32,Int8)) at gmp.jl:249
    +(c::Union(Int64,Int16,Int32,Int8),x::BigInt) at gmp.jl:250
    +(x::BigFloat,c::Uint64) at mpfr.jl:147
    +(c::Uint64,x::BigFloat) at mpfr.jl:151
    +(c::Union(Uint32,Uint16,Uint8,Uint64),x::BigFloat) at mpfr.jl:152
    +(x::BigFloat,c::Union(Uint32,Uint16,Uint8,Uint64)) at mpfr.jl:153
    +(x::BigFloat,c::Int64) at mpfr.jl:157
    +(c::Int64,x::BigFloat) at mpfr.jl:161
    +(x::BigFloat,c::Union(Int64,Int16,Int32,Int8)) at mpfr.jl:162
    +(c::Union(Int64,Int16,Int32,Int8),x::BigFloat) at mpfr.jl:163
    +(x::BigFloat,c::Float64) at mpfr.jl:167
    +(c::Float64,x::BigFloat) at mpfr.jl:171
    +(c::Float32,x::BigFloat) at mpfr.jl:172
    +(x::BigFloat,c::Float32) at mpfr.jl:173
    +(x::BigFloat,c::BigInt) at mpfr.jl:177
    +(c::BigInt,x::BigFloat) at mpfr.jl:181
    +(x::BigFloat,y::BigFloat) at mpfr.jl:328
    +(a::BigFloat,b::BigFloat,c::BigFloat) at mpfr.jl:339
    +(a::BigFloat,b::BigFloat,c::BigFloat,d::BigFloat) at mpfr.jl:345
    +(a::BigFloat,b::BigFloat,c::BigFloat,d::BigFloat,e::BigFloat) at mpfr.jl:352
    +(x::MathConst{sym},y::MathConst{sym}) at constants.jl:23
    +{T<:Number}(x::T<:Number,y::T<:Number) at promotion.jl:188
    +{T<:FloatingPoint}(x::Bool,y::T<:FloatingPoint) at bool.jl:46
    +(x::Number,y::Number) at promotion.jl:158
    +(x::Integer,y::Ptr{T}) at pointer.jl:68
    +(x::Bool,A::AbstractArray{Bool,N}) at array.jl:767
    +(x::Number) at operators.jl:71
    +(r1::OrdinalRange{T,S},r2::OrdinalRange{T,S}) at operators.jl:325
    +{T<:FloatingPoint}(r1::FloatRange{T<:FloatingPoint},r2::FloatRange{T<:FloatingPoint}) at operators.jl:331
    +(r1::FloatRange{T<:FloatingPoint},r2::FloatRange{T<:FloatingPoint}) at operators.jl:348
    +(r1::FloatRange{T<:FloatingPoint},r2::OrdinalRange{T,S}) at operators.jl:349
    +(r1::OrdinalRange{T,S},r2::FloatRange{T<:FloatingPoint}) at operators.jl:350
    +(x::Ptr{T},y::Integer) at pointer.jl:66
    +{S,T<:Real}(A::Union(SubArray{S,N,A<:DenseArray{T,N},I<:(Union(Range{Int64},Int64)...,)},DenseArray{S,N}),B::Range{T<:Real}) at array.jl:727
    +{S<:Real,T}(A::Range{S<:Real},B::Union(SubArray{T,N,A<:DenseArray{T,N},I<:(Union(Range{Int64},Int64)...,)},DenseArray{T,N})) at array.jl:736
    +(A::AbstractArray{Bool,N},x::Bool) at array.jl:766
    +{Tv,Ti}(A::SparseMatrixCSC{Tv,Ti},B::SparseMatrixCSC{Tv,Ti}) at sparse/sparsematrix.jl:530
    +{TvA,TiA,TvB,TiB}(A::SparseMatrixCSC{TvA,TiA},B::SparseMatrixCSC{TvB,TiB}) at sparse/sparsematrix.jl:522
    +(A::SparseMatrixCSC{Tv,Ti<:Integer},B::Array{T,N}) at sparse/sparsematrix.jl:621
    +(A::Array{T,N},B::SparseMatrixCSC{Tv,Ti<:Integer}) at sparse/sparsematrix.jl:623
    +(A::SymTridiagonal{T},B::SymTridiagonal{T}) at linalg/tridiag.jl:45
    +(A::Tridiagonal{T},B::Tridiagonal{T}) at linalg/tridiag.jl:207
    +(A::Tridiagonal{T},B::SymTridiagonal{T}) at linalg/special.jl:99
    +(A::SymTridiagonal{T},B::Tridiagonal{T}) at linalg/special.jl:98
    +{T,MT,uplo}(A::Triangular{T,MT,uplo,IsUnit},B::Triangular{T,MT,uplo,IsUnit}) at linalg/triangular.jl:10
    +{T,MT,uplo1,uplo2}(A::Triangular{T,MT,uplo1,IsUnit},B::Triangular{T,MT,uplo2,IsUnit}) at linalg/triangular.jl:11
    +(Da::Diagonal{T},Db::Diagonal{T}) at linalg/diagonal.jl:44
    +(A::Bidiagonal{T},B::Bidiagonal{T}) at linalg/bidiag.jl:92
    +{T}(B::BitArray{2},J::UniformScaling{T}) at linalg/uniformscaling.jl:26
    +(A::Diagonal{T},B::Bidiagonal{T}) at linalg/special.jl:89
    +(A::Bidiagonal{T},B::Diagonal{T}) at linalg/special.jl:90
    +(A::Diagonal{T},B::Tridiagonal{T}) at linalg/special.jl:89
    +(A::Tridiagonal{T},B::Diagonal{T}) at linalg/special.jl:90
    +(A::Diagonal{T},B::Triangular{T,S<:AbstractArray{T,2},UpLo,IsUnit}) at linalg/special.jl:89
    +(A::Triangular{T,S<:AbstractArray{T,2},UpLo,IsUnit},B::Diagonal{T}) at linalg/special.jl:90
    +(A::Diagonal{T},B::Array{T,2}) at linalg/special.jl:89
    +(A::Array{T,2},B::Diagonal{T}) at linalg/special.jl:90
    +(A::Bidiagonal{T},B::Tridiagonal{T}) at linalg/special.jl:89
    +(A::Tridiagonal{T},B::Bidiagonal{T}) at linalg/special.jl:90
    +(A::Bidiagonal{T},B::Triangular{T,S<:AbstractArray{T,2},UpLo,IsUnit}) at linalg/special.jl:89
    +(A::Triangular{T,S<:AbstractArray{T,2},UpLo,IsUnit},B::Bidiagonal{T}) at linalg/special.jl:90
    +(A::Bidiagonal{T},B::Array{T,2}) at linalg/special.jl:89
    +(A::Array{T,2},B::Bidiagonal{T}) at linalg/special.jl:90
    +(A::Tridiagonal{T},B::Triangular{T,S<:AbstractArray{T,2},UpLo,IsUnit}) at linalg/special.jl:89
    +(A::Triangular{T,S<:AbstractArray{T,2},UpLo,IsUnit},B::Tridiagonal{T}) at linalg/special.jl:90
    +(A::Tridiagonal{T},B::Array{T,2}) at linalg/special.jl:89
    +(A::Array{T,2},B::Tridiagonal{T}) at linalg/special.jl:90
    +(A::Triangular{T,S<:AbstractArray{T,2},UpLo,IsUnit},B::Array{T,2}) at linalg/special.jl:89
    +(A::Array{T,2},B::Triangular{T,S<:AbstractArray{T,2},UpLo,IsUnit}) at linalg/special.jl:90
    +(A::SymTridiagonal{T},B::Triangular{T,S<:AbstractArray{T,2},UpLo,IsUnit}) at linalg/special.jl:98
    +(A::Triangular{T,S<:AbstractArray{T,2},UpLo,IsUnit},B::SymTridiagonal{T}) at linalg/special.jl:99
    +(A::SymTridiagonal{T},B::Array{T,2}) at linalg/special.jl:98
    +(A::Array{T,2},B::SymTridiagonal{T}) at linalg/special.jl:99
    +(A::Diagonal{T},B::SymTridiagonal{T}) at linalg/special.jl:107
    +(A::SymTridiagonal{T},B::Diagonal{T}) at linalg/special.jl:108
    +(A::Bidiagonal{T},B::SymTridiagonal{T}) at linalg/special.jl:107
    +(A::SymTridiagonal{T},B::Bidiagonal{T}) at linalg/special.jl:108
    +{T<:Number}(x::AbstractArray{T<:Number,N}) at abstractarray.jl:358
    +(A::AbstractArray{T,N},x::Number) at array.jl:770
    +(x::Number,A::AbstractArray{T,N}) at array.jl:771
    +(J1::UniformScaling{T<:Number},J2::UniformScaling{T<:Number}) at linalg/uniformscaling.jl:25
    +(J::UniformScaling{T<:Number},B::BitArray{2}) at linalg/uniformscaling.jl:27
    +(J::UniformScaling{T<:Number},A::AbstractArray{T,2}) at linalg/uniformscaling.jl:28
    +(J::UniformScaling{T<:Number},x::Number) at linalg/uniformscaling.jl:29
    +(x::Number,J::UniformScaling{T<:Number}) at linalg/uniformscaling.jl:30
    +{TA,TJ}(A::AbstractArray{TA,2},J::UniformScaling{TJ}) at linalg/uniformscaling.jl:33
    +{T}(a::HierarchicalValue{T},b::HierarchicalValue{T}) at pkg/resolve/versionweight.jl:19
    +(a::VWPreBuildItem,b::VWPreBuildItem) at pkg/resolve/versionweight.jl:82
    +(a::VWPreBuild,b::VWPreBuild) at pkg/resolve/versionweight.jl:120
    +(a::VersionWeight,b::VersionWeight) at pkg/resolve/versionweight.jl:164
    +(a::FieldValue,b::FieldValue) at pkg/resolve/fieldvalue.jl:41
    +(a::Vec2,b::Vec2) at graphics.jl:60
    +(bb1::BoundingBox,bb2::BoundingBox) at graphics.jl:123
    +(a,b,c) at operators.jl:82
    +(a,b,c,xs...) at operators.jl:83

Overloading and flexible paramethy type systems together allow Julia to abstract advanced algorithms and generate efficient, runtime-specific code without paying attention to the specifics of the implementation.

Method ambiguity

The scope of application of function methods may overlap:

    julia> g(x::Float64, y) = 2x + y;

    julia> g(x, y::Float64) = x + 2y;
    Warning: New definition 
        g(Any,Float64) at none:1
    is ambiguous with: 
        g(Float64,Any) at none:1.
    To fix, define 
        g(Float64,Float64)
    before the new definition.

    julia> g(2.0, 3)
    7.0

    julia> g(2, 3.0)
    8.0

    julia> g(2.0, 3.0)
    7.0

Here g(2.0, 3.0) call g(Float64, Any) nor g(Any, Float64) methods have no priority. I n this case, Julia warns that the definition is vague, but still chooses a method to continue. Ambiguous methods should be avoided:

    julia> g(x::Float64, y::Float64) = 2x + 2y;

    julia> g(x::Float64, y) = 2x + y;

    julia> g(x, y::Float64) = x + 2y;

    julia> g(2.0, 3)
    7.0

    julia> g(2, 3.0)
    8.0

    julia> g(2.0, 3.0)
    10.0

To eliminate Julia's warnings, you should first define a clear approach.

Paramethy method

To construct a paramethy method, type parameters should be added between the method name and the parameter multiple group:

   julia> same_type(x::T, y::T) where {T} = true   same_type (generic function with 1 method)

   julia> same_type(x,y) = false
   same_type (generic function with 2 methods)

These two methods define a Boolean function that checks whether two parameters are of the same type:

    julia> same_type(1, 2)
    true

    julia> same_type(1, 2.0)
    false

    julia> same_type(1.0, 2.0)
    true

    julia> same_type("foo", 2.0)
    false

    julia> same_type("foo", "bar")
    true

    julia> same_type(int32(1), int64(2))
    false

Type parameters can be used anywhere in a function definition or function body:

    julia> myappend{T}(v::Vector{T}, x::T) = [v..., x]
    myappend (generic function with 1 method)

    julia> myappend([1,2,3],4)
    4-element Array{Int64,1}:
     1
     2
     3
     4

    julia> myappend([1,2,3],2.5)
    ERROR: `myappend` has no method matching myappend(::Array{Int64,1}, ::Float64)

    julia> myappend([1.0,2.0,3.0],4.0)
    4-element Array{Float64,1}:
     1.0
     2.0
     3.0
     4.0

    julia> myappend([1.0,2.0,3.0],4)
    ERROR: `myappend` has no method matching myappend(::Array{Float64,1}, ::Int64)

In the following example, the method type parameter T used as a return value:

    julia> mytypeof{T}(x::T) = T
    mytypeof (generic function with 1 method)

    julia> mytypeof(1)
    Int64

    julia> mytypeof(1.0)
    Float64

The type parameters of the method can also be limited in scope:

    same_type_numeric{T<:Number}(x::T, y::T) = true
    same_type_numeric(x::Number, y::Number) = false

    julia> same_type_numeric(1, 2)
    true

    julia> same_type_numeric(1, 2.0)
    false

    julia> same_type_numeric(1.0, 2.0)
    true

    julia> same_type_numeric("foo", 2.0)
    no method same_type_numeric(ASCIIString,Float64)

    julia> same_type_numeric("foo", "bar")
    no method same_type_numeric(ASCIIString,ASCIIString)

    julia> same_type_numeric(int32(1), int64(2))
    false

same_type_numeric is same_type same as the function, but only for pairs of numbers.

About optional and keyword parameters

It was briefly mentioned in the function that optional parameters are implementations that can be defined by multiple methods. For example:

    f(a=1,b=2) = a+2b

It can be translated into three methods:

    f(a,b) = a+2b
    f(a) = f(a,2)
    f() = f(1,2)

Keyword parameters are different from normal location-related parameters. T hey are not used for method overloading. Method overloading is based only on positional parameters, and the keyword parameters are processed only after a matching method has been selected.