The Compat package is designed to ease interoperability between
older and newer versions of the Julia
language. In particular, in cases where it is
impossible to write code that works with both the latest Julia
master
branch and older Julia versions, or impossible to write code
that doesn't generate a deprecation warning in some Julia version, the
Compat package provides a macro that lets you use the latest syntax
in a backwards-compatible way.
This is primarily intended for use by other Julia packages, where it is important to maintain cross-version compatibility.
To use Compat in your Julia package, add a line Compat
to the
REQUIRE
file in your package directory. Then, in your package,
shortly after the module
statement include lines like these:
using Compat
import Compat.String
and then as needed add
@compat ...compat syntax...
wherever you want to use syntax that differs in the latest Julia
master
(the development version of Julia). The compat syntax
is usually
the syntax on Julia master
. However, in a few cases where this is not possible,
a slightly different syntax might be used.
Please check the list below for the specific syntax you need.
Currently, the @compat
macro supports the following syntaxes:
-
@compat (a::B{T}){T}(c) = d
— the Julia 0.5-style call overload -
@compat(get(io, s, false))
, withs
equal to:limit
,:compact
or:multiline
, to detect the corresponding print settings (performs useful work only on Julia 0.5, defaults tofalse
otherwise) -
@compat Nullable(value, hasvalue)
to handle the switch from theNullable
:isnull
field to:hasvalue
field (#18510) -
@compat x .= y
converts to an in-place assignment tox
(viabroadcast!
) (#17510). However, beware that.=
in Julia 0.4 has the precedence of==
, not of assignment=
, so if the right-hand-sidey
includes expressions with lower precedence than==
you should enclose it in parenthesesx .= (y)
to ensure the correct order of evaluation. Also,x .+= y
converts tox .= (x .+ y)
, and similarly for the other updating assignment operators (.*=
and so on). -
@compat Array{<:Real}
,@compat Array{>:Int}
, and similar uses of<:T
(resp.>:T
) to define a set of "covariant" (resp. "contravariant") parameterized types (#20414). In 0.5, this only works for non-nested usages (e.g. you can't defineArray{<:Array{<:Real}}
). -
@compat abstract type T end
and@compat primitive type T 8 end
to declare abstract and primitive types. #20418 This only works when@compat
is applied directly on the declaration. -
@compat A{T} = B{T}
or@compat const A{T} = B{T}
to declare type alias with free parameters. #20500. Useconst A = B{T}
orconst A = B
for type alias without free parameters (i.e. no type parameter on the left hand side). -
@compat Base.IndexStyle(::Type{<:MyArray}) = IndexLinear()
and@compat Base.IndexStyle(::Type{<:MyArray}) = IndexCartesian()
to define traits for abstract arrays, replacing the formerBase.linearindexing{T<:MyArray}(::Type{T}) = Base.LinearFast()
andBase.linearindexing{T<:MyArray}(::Type{T}) = Base.LinearSlow()
, respectively. -
Compat.collect(A)
returns anArray
, no matter what indices the arrayA
has. #21257 -
@compat foo(::CartesianRange{N})
to replace the formerfoo(::CartesianRange{CartesianIndex{N}})
(#20974). Note thatCartesianRange
now has two type parameters, so using them as fields in otherstruct
s requires manual intervention. -
using Compat.Test
,using Compat.SharedArrays
,using Compat.Mmap
, andusing Compat.DelimitedFiles
are provided on versions older than 0.7, where these are not yet part of the standard library. (#23931)
- In 0.6, some 0.5 iterator functions have been moved to the
Base.Iterators
module. Code can be written to work on both 0.5 and 0.6 byimport
ing orusing
theCompat.Iterators
module instead. (#18839)
-
@views
takes an expression and converts all slices to views (#20164), while@view
(#16564) converts a single array reference to a view (#20164). -
@__dot__
takes an expression and converts all assignments, function calls, and operators to their broadcasting "dot-call" equivalents (#20321). In Julia 0.6, this can be abbreviated@.
, but that macro name does not parse in earlier Julia versions. For this to work in older versions of Julia (prior to 0.5) that don't have dot calls, you should instead use@dotcompat
, which combines the@__dot__
and@compat
macros. -
normalize
andnormalize!
, normalizes a vector with respect to the p-norm (#13681) -
redirect_stdout
,redirect_stderr
, andredirect_stdin
take an optional function as a first argument,redirect_std*(f, stream)
, so that one may usedo
block syntax (as first available for Julia 0.6) -
unsafe_get
returns the:value
field of aNullable
object without any null-check and has a generic fallback for non-Nullable
argument (#18484) -
isnull
has a generic fallback for non-Nullable
argument -
transcode
converts between UTF-xx string encodings in Julia 0.5 (as a lightweight alternative to the LegacyStrings package) (#17323) -
∘
(typically used infix asf ∘ g
) for function composition can be used in 0.5 and earlier (#17155) -
>:
, a supertype operator for symmetry withissubtype
(A >: B
is equivalent toB <: A
), can be used in 0.5 and earlier (#20407). -
The method of
!
to negate functions (typically used as a unary operator, as in!isinteger
) can be used in 0.5 and earlier (#17155). -
iszero(x)
efficiently checks whetherx == zero(x)
(including arrays) can be used in 0.5 and earlier (#19950). -
.&
and.|
are short syntax forbroadcast(&, xs...)
andbroadcast(|, xs...)
(respectively) in Julia 0.6 (only supported on Julia 0.5 and above) (#17623) -
Compat.isapprox
withnans
keyword argument (#20022) -
Compat.readline
withchomp
keyword argument (#20203) -
take!
method forTask
s since some functions now returnChannel
s instead ofTask
s (#19841) -
The
isabstract
,parameter_upper_bound
,typename
reflection methods were added in Julia 0.6. This package re-exports these from theCompat.TypeUtils
submodule. On earlier versions of julia, that module contains the same functions, but operating on the pre-0.6 type system representation. -
broadcast
is supported on tuples of the same lengths on 0.5. (#16986) -
zeros
andones
support an interface the same assimilar
(#19635) -
convert
can convert between differentSet
types on 0.5 and below. (#18727) -
isassigned(::RefValue)
is supported on 0.5 and below. (#18082) -
unsafe_trunc(::Type{<:Integer}, ::Integer)
is supported on 0.5. (#18629) -
bswap
is supported forComplex
arguments on 0.5 and below. (#21346) -
Compat.invokelatest
is equivalent toBase.invokelatest
in Julia 0.6, but works in Julia 0.5+, and allows you to guarantee that a function call invokes the latest version of a function (#19784). -
Compat.StringVector
is supported on 0.5 and below. On 0.6 and later, it aliasesBase.StringVector
. This function allocates aVector{UInt8}
whose data can be made into aString
in constant time; that is, without copying. On 0.5 and later, useString(...)
with the vector allocated byStringVector
as an argument to create a string without copying. Note that if 0.4 support is needed,Compat.UTF8String(...)
should be used instead. (#19449) -
==(::Period, ::Period)
andisless(::Period, ::Period)
is supported for 0.5 and below. Earlier versions of Julia only supported limited comparison methods between Periods which did not support comparing custom Period subtypes. (#21378) -
@__MODULE__
is aliased tocurrent_module()
for Julia versions 0.6 and below. Versions ofBase.binding_module
,expand
,macroexpand
, andinclude_string
were added that accept a module as the first argument. (#22064) -
Cmd
elements can be accessed as if theCmd
were an array of strings for 0.6 and below (#21197). -
Val(x)
constructsVal{x}()
. (#22475) -
The
reshape
andntuple
APIs are extended to supportVal{x}()
arguments on 0.6 and below. -
chol
andchol!
forUniformScalings
(#22633). -
logdet
forNumber
s (#22629). -
fieldcount
is equivalent tonfields
for Julia versions 0.6 and below and is used to determine the number of fields in a data type (#22350). -
There are versions of
InexactError
,DomainError
, andOverflowError
that take the same arguments as introduced in Julia 0.7-DEV (#20005, #22751, #22761). -
retry
for the more flexibleretry
method introduced in 0.6 which includes support for kwargs (#19331, #21419). -
Base.rtoldefault
how takes a third parameteratol
. The two argument form is deprecated in favor of the three arguments form withatol=0
. -
The
corrected
optional argument ofcov
becomes a keyword argument. Due to conflict with 0.5 deprecation,cov(::AbstractVector; corrected=)
andcov(::AbstractVector, ::AbstractVector; corrected=)
are only available on 0.6. (#21709) -
equalto
constructs anEqualTo
object that can be used as a predicate (#23812).
-
$
is nowxor
or⊻
(#18977) -
num
andden
are nownumerator
anddenominator
(#19246) -
takebuf_array
is now a method oftake!
.takebuf_string(io)
becomesString(take!(io))
(#19088) -
is_apple
,is_bsd
,is_linux
,is_unix
, andis_windows
are nowSys.isapple
,Sys.isbsd
,Sys.islinux
,Sys.isunix
, andSys.iswindows
, respectively. These are available in theCompat.Sys
submodule. (#22182) -
readstring
is replaced by methods ofread
. (#22864)read(::IO, ::Type{String})
,read(::AbstractString, ::Type{String})
, andread(::Cmd, ::Type{String})
are defined for 0.6 and below. -
Range
is nowAbstractRange
(#23570) -
select
* functions (select
,select!
,selectperm
,selectperm!
) are renamed topartialsort
* (partialsort
,partialsort!
,partialsortperm
,partialsortperm!
) (#23051) -
ctranspose
andctranspose!
are nowadjoint
andadjoint!
(#23235) -
Math constants (
π
,pi
,e
,γ
,eulergamma
,catalan
,φ
,golden
) are moved to theMathConstants
module (available asCompat.MathConstants
). The name exported fromBase
fore
is changed toℯ
. (#23427) -
isleaftype
is nowisconcrete
(#23666)
-
@__DIR__
has been added (#18380) -
@vectorize_1arg
and@vectorize_2arg
are deprecated on Julia 0.6 in favor of the broadcast syntax (#17302).Compat.@dep_vectorize_1arg
andCompat.@dep_vectorize_2arg
are provided so that packages can still provide the deprecated definitions without causing a depwarn in the package itself before all the users are upgraded.Packages are expected to use this until all users of the deprecated vectorized function have migrated. These macros will be dropped when the support for
0.6
is dropped fromCompat
. -
@nospecialize
has been added (#22666).
-
On versions of Julia that do not contain a Base.Threads module, Compat defines a Threads module containing a no-op
@threads
macro. -
The
Expr(:macrocall)
has an extra initial argument__source__
, which can be tested for withCompat.macros_have_sourceloc
.
Currently, no new exported types are introduced by Compat.
One of the most important rules for Compat.jl
is to avoid breaking user code
whenever possible, especially on a released version.
Although the syntax used in the most recent Julia version
is the preferred compat syntax, there are cases where this shouldn't be used.
Examples include when the new syntax already has a different meaning
on previous versions of Julia, or when functions are removed from Base
Julia and the alternative cannot be easily implemented on previous versions.
In such cases, possible solutions are forcing the new feature to be used with
qualified name in Compat.jl
(e.g. use Compat.<name>
) or
reimplementing the old features on a later Julia version.
If you're adding additional compatibility code to this package, the contrib/commit-name.sh
script in the base Julia repository is useful for extracting the version number from a git commit SHA. For example, from the git repository of julia
, run something like this:
bash $ contrib/commit-name.sh a378b60fe483130d0d30206deb8ba662e93944da
0.5.0-dev+2023
This prints a version number corresponding to the specified commit of the form
X.Y.Z-aaa+NNNN
, and you can then test whether Julia
is at least this version by VERSION >= v"X.Y.Z-aaa+NNNN"
.
One of the most frequent problems package developers encounter is finding the right
version of Compat
to add to their REQUIRE. This is meant to be a guide on how to
specify the right lower bound.
-
Find the appropriate fix needed for your package from the
Compat
README. Every function or feature added toCompat
is documented in its README, so you are guaranteed to find it. -
Navigate to the blame page of the README by clicking on the README file on GitHub, and then clicking on the
blame
button which can be found in the top-right corner. -
Now find your fix, and then find the corresponding commit ID of that fix on the left-hand side. Click on the commit ID. This navigates to a page which recorded that particular commit.
-
On the top pane, you should find the list of the tagged versions of Compat that includes this fix. Find the minimum version from there.
-
Now specify the correct minimum version for Compat in your REQUIRE file by
Compat <version>