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 foo.:bar
—foo.(:bar)
in 0.4 (#15032) -
@compat f.(args...)
—broadcast(f, args...)
in 0.4 (#15032) -
@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 import Base.show
and@compat function show(args...)
for handling the deprecation ofwritemime
in Julia 0.5 (#16563). See JuliaLang#219. -
@compat @boundscheck checkbounds(...)
rewrites to unconditionally callcheckbounds(...)
in 0.4. The 0.4-style two-argument form of@boundscheck
is left unchanged. -
@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.4 and 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
for type alias without free parameters. -
@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.
-
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) -
The
Compat.Iterators
module is also available on 0.4, including the iterator functionspartition
,product
, andflatten
, which were introduced in Julia 0.5. However, because of a variety of other changes to the iterator system between 0.4 and 0.5, these functions behave slightly differently. For example, theIterators.product
function on 0.4 does not return objects with shapes. (#14596, #14805, #15409)
-
In 0.5,
ASCIIString
andByteString
were deprecated, andUTF8String
was renamed to the (now concrete) typeString
.Compat provides unexported
Compat.UTF8String
andCompat.ASCIIString
type aliases which are equivalent to the same types from Base on Julia 0.4, but toString
on Julia 0.5. In most cases, using these types by callingimport Compat: UTF8String, ASCIIString
should be enough. Note thatCompat.ASCIIString
does not guarantee that the string only contains ASCII characters on Julia 0.5: callisascii
to check if the string is pure ASCII if needed.Compat also provides an unexported
Compat.String
type which is equivalent toByteString
on Julia 0.4, and toString
on Julia 0.5. This type should be used only in places whereByteString
was used on Julia 0.4, i.e. where eitherASCIIString
orUTF8String
should be accepted. It should not be used as the default type for variables or fields holding strings, as it introduces type-instability in Julia 0.4: useCompat.UTF8String
orCompat.ASCIIString
instead. -
bytestring
has been replaced in most cases with additionalString
construction methods; for 0.4 compatibility, the usage involves replacingbytestring(args...)
withCompat.String(args...)
. However, for converting aPtr{UInt8}
to a string, use the newunsafe_string(...)
method to make a copy orunsafe_wrap(String, ...)
to avoid a copy.
-
@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. -
foreach
, similar tomap
but when the return value is not needed (#13744) -
walkdir
, returns an iterator that walks the directory tree of a directory (#13707) -
allunique
, checks whether all elements in an iterable appear only once (#15914) -
Base.promote_eltype_op
is available asCompat.promote_eltype_op
-
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)
-
pointer_to_array
andpointer_to_string
have been replaced withunsafe_wrap(Array, ...)
andunsafe_wrap(String, ...)
respectively -
bytestring(::Ptr, ...)
has been replaced withunsafe_string
-
super
is nowsupertype
(#14338) -
qr(A, pivot=b)
is nowqr(A, Val{b})
, likewise forqrfact
andqrfact!
-
readall
andreadbytes
are nowreadstring
andread
(#14660) -
get_bigfloat_precision
is nowprecision(BigFloat)
,set_precision
issetprecision
andwith_bigfloat_precision
is now alsosetprecision
(#13232) -
get_rounding
is nowrounding
.set_rounding
andwith_rounding
are nowsetrounding
(#13232) -
Base.tty_size
(which was not exported) is nowdisplaysize
in Julia 0.5 -
Compat.LinAlg.checksquare
(#14601) -
issym
is nowissymmetric
(#15192) -
istext
is nowistextmime
(#15708) -
symbol
is nowSymbol
(#16154) -
write(::IO, ::Ptr, len)
is nowunsafe_write
(#14766) -
slice
is nowview
(#16972); doimport Compat.view
and then useview
normally without the@compat
macro -
fieldoffsets
has been deprecated in favor offieldoffset
(#14777) -
print_escaped
is now another method ofescape_string
,print_unescaped
a method ofunescape_string
, andprint_joined
a method ofjoin
(#16603) -
writemime
has been merged intoshow
(#16563). Note that to extend this function requires@compat
; see the Supported Syntax section for more information -
$
is nowxor
or⊻
(#18977) -
num
andden
are nownumerator
anddenominator
(#19246) -
takebuf_array
is now a method oftake!
.takebuf_string(io)
becomesString(take!(io))
(#19088)
-
@static
has been added (#16219) -
@functorize
(not present in any Julia version) takes a function (or operator) and turns it into a functor object if one is available in the used Julia version. E.g. something likemapreduce(Base.AbsFun(), Base.MulFun(), x)
can now be written asmapreduce(@functorize(abs), @functorize(*), x)
, andf(::Base.AbsFun())
asf(::typeof(@functorize(abs)))
, to work across different Julia versions.Func{1}
can be written assupertype(typeof(@functorize(abs)))
(and so on forFunc{2}
), which will fall back toFunction
on Julia 0.5. -
Compat.@blasfunc
makes functionality ofBase.LinAlg.BLAS.@blasfunc
available on older Julia versions -
@__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
.
-
remotecall
,remotecall_fetch
,remotecall_wait
, andremote_do
have the function to be executed remotely as the first argument in Julia 0.5. LoadingCompat
defines the same methods in older versions of Julia (#13338) -
Base.FS
is nowBase.Filesystem
(#12819) Compat provides an unexportedCompat.Filesystem
module that is aliased toBase.FS
on Julia 0.4 andBase.Filesystem
on Julia 0.5. -
cov
andcor
don't allow keyword arguments anymore. Loading Compat defines compatibility methods for the new API (#13465) -
On versions of Julia that do not contain a Base.Threads module, Compat defines a Threads module containing a no-op
@threads
macro. -
Base.SingleAsyncWork
is nowBase.AsyncCondition
Compat provides an unexportedCompat.AsyncCondition
type that is aliased toBase.SingleAsyncWork
on Julia 0.4 andBase.AsyncCondition
on Julia 0.5. -
repeat
now accepts anyAbstractArray
(#14082):Compat.repeat
supports this new API on Julia 0.4, and callsBase.repeat
on 0.5. -
OS_NAME
is nowSys.KERNEL
. OS information available asis_apple
,is_bsd
,is_linux
,is_unix
, andis_windows
(#16219) -
cholfact
,cholfact!
, andchol
require that input is eitherHermitian
,Symmetric
or that the elements are perfectly symmetric or Hermitian on 0.5. Compat now defines methods forHermOrSym
such that using the new methods are backward compatible. -
Diagonal
and*
methods supportSubArray
s even on 0.4. -
Single-argument
min
,max
andminmax
are defined on 0.4.
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>