Although MATLAB users may find Julia's syntax familiar, Julia is not a MATLAB clone. There are major syntactic and functional differences. The following are some noteworthy differences that may trip up Julia users accustomed to MATLAB:
A[i,j]
.A = B
, changing elements ofB
will modifyA
as well. To avoid this, useA = copy(B)
.a(4) = 3.2
can create the arraya = [0 0 0 3.2]
anda(5) = 7
can grow it intoa = [0 0 0 3.2 7]
, the corresponding Julia statementa[5] = 7
throws an error if the length ofa
is less than 5 or if this statement is the first use of the identifiera
. Julia haspush!
andappend!
, which growVector
s much more efficiently than MATLAB'sa(end+1) = val
.sqrt(-1)
is represented in Julia asim
, noti
orj
as in MATLAB.42
) create integers instead of floating point numbers. As a result, some operations can throw a domain error if they expect a float; for example,julia> a = -1; 2^a
throws a domain error, as the result is not an integer (seethe FAQ entry on domain errors for details).(a, b) = (1, 2)
ora, b = 1, 2
. MATLAB'snargout
, which is often used in MATLAB to do optional work based on the number of returned values, does not exist in Julia. Instead, users can use optional and keyword arguments to achieve similar capabilities.N
, notNx1
. For example,rand(N)
makes a 1-dimensional array.[x,y,z]
will always construct a 3-element array containingx
,y
andz
.vcat(x,y,z)
or separate with semicolons ([x; y; z]
).hcat(x,y,z)
or separate with spaces ([x y z]
).hvcat
or combine spaces and semicolons ([a b; c d]
).a:b
anda:b:c
constructAbstractRange
objects. To construct a full vector like in MATLAB, usecollect(a:b)
. Generally, there is no need to callcollect
though. AnAbstractRange
object will act like a normal array in most cases but is more efficient because it lazily computes its values. This pattern of creating specialized objects instead of full arrays is used frequently, and is also seen in functions such asrange
, or with iterators such asenumerate
, andzip
. The special objects can mostly be used as if they were normal arrays.return
keyword instead of listing the names of variables to return in the function definition (seeThe return Keyword for details).sum
,prod
, andmaximum
are performed over every element of an array when called with a single argument, as insum(A)
, even ifA
has more than one dimension.rand()
.println
or@printf
can be used to print specific output.A
andB
are arrays, logical comparison operations likeA == B
do not return an array of booleans. Instead, useA .== B
, and similarly for the other boolean operators like<
,>
.&
,|
, and⊻
(xor
) perform the bitwise operations equivalent toand
,or
, andxor
respectively in MATLAB, and have precedence similar to Python's bitwise operators (unlike C). They can operate on scalars or element-wise across arrays and can be used to combine logical arrays, but note the difference in order of operations: parentheses may be required (e.g., to select elements ofA
equal to 1 or 2 use(A .== 1) .| (A .== 2)
)....
, as inxs=[1,2]; f(xs...)
.svd
returns singular values as a vector instead of as a dense diagonal matrix....
is not used to continue lines of code. Instead, incomplete expressions automatically continue onto the next line.ans
is set to the value of the last expression issued in an interactive session. In Julia, unlike MATLAB,ans
is not set when Julia code is run in non-interactive mode.struct
s do not support dynamically adding fields at runtime, unlike MATLAB'sclass
es. Instead, use aDict
. Dict in Julia isn't ordered.x(x>3)
or in the statementx(x>3) = []
to modifyx
in-place. In contrast, Julia provides the higher order functionsfilter
andfilter!
, allowing users to writefilter(z->z>3, x)
andfilter!(z->z>3, x)
as alternatives to the corresponding transliterationsx[x.>3]
andx = x[x.>3]
. Usingfilter!
reduces the use of temporary arrays.vertcat(A{:})
in MATLAB, is written using the splat operator in Julia, e.g. asvcat(A...)
.adjoint
function performs conjugate transposition; in MATLAB,adjoint
provides the "adjugate" or classical adjoint, which is the transpose of the matrix of cofactors.One of Julia's goals is to provide an effective language for data analysis and statistical programming. For users coming to Julia from R, these are some noteworthy differences:
Julia's single quotes enclose characters, not strings.
Julia can create substrings by indexing into strings. In R, strings must be converted into character vectors before creating substrings.
In Julia, like Python but unlike R, strings can be created with triple quotes""" ... """
. This syntax is convenient for constructing strings that contain line breaks.
In Julia, varargs are specified using the splat operator...
, which always follows the name of a specific variable, unlike R, for which...
can occur in isolation.
In Julia, modulus ismod(a, b)
, nota %% b
.%
in Julia is the remainder operator.
Julia constructs vectors using brackets. Julia's[1, 2, 3]
is the equivalent of R'sc(1, 2, 3)
.
In Julia, not all data structures support logical indexing. Furthermore, logical indexing in Julia is supported only with vectors of length equal to the object being indexed. For example:
c(1, 2, 3, 4)[c(TRUE, FALSE)]
is equivalent toc(1, 3)
.c(1, 2, 3, 4)[c(TRUE, FALSE, TRUE, FALSE)]
is equivalent toc(1, 3)
.[1, 2, 3, 4][[true, false]]
throws aBoundsError
.[1, 2, 3, 4][[true, false, true, false]]
produces[1, 3]
.Like many languages, Julia does not always allow operations on vectors of different lengths, unlike R where the vectors only need to share a common index range. For example,c(1, 2, 3, 4) + c(1, 2)
is valid R but the equivalent[1, 2, 3, 4] + [1, 2]
will throw an error in Julia.
Julia allows an optional trailing comma when that comma does not change the meaning of code. This can cause confusion among R users when indexing into arrays. For example,x[1,]
in R would return the first row of a matrix; in Julia, however, the comma is ignored, sox[1,] == x[1]
, and will return the first element. To extract a row, be sure to use:
, as inx[1,:]
.
Julia'smap
takes the function first, then its arguments, unlikelapply(<structure>, function, ...)
in R. Similarly Julia's equivalent ofapply(X, MARGIN, FUN, ...)
in R ismapslices
where the function is the first argument.
Multivariate apply in R, e.g.mapply(choose, 11:13, 1:3)
, can be written asbroadcast(binomial, 11:13, 1:3)
in Julia. Equivalently Julia offers a shorter dot syntax for vectorizing functionsbinomial.(11:13, 1:3)
.
Julia usesend
to denote the end of conditional blocks, likeif
, loop blocks, likewhile
/for
, and functions. In lieu of the one-lineif ( cond ) statement
, Julia allows statements of the formif cond; statement; end
,cond && statement
and!cond || statement
. Assignment statements in the latter two syntaxes must be explicitly wrapped in parentheses, e.g.cond && (x = value)
.
In Julia,<-
,<<-
and->
are not assignment operators.
Julia's->
creates an anonymous function.
Julia's*
operator can perform matrix multiplication, unlike in R. IfA
andB
are matrices, thenA * B
denotes a matrix multiplication in Julia, equivalent to R'sA %*% B
. In R, this same notation would perform an element-wise (Hadamard) product. To get the element-wise multiplication operation, you need to writeA .* B
in Julia.
Julia performs matrix transposition using thetranspose
function and conjugated transposition using the'
operator or theadjoint
function. Julia'stranspose(A)
is therefore equivalent to R'st(A)
. Additionally a non-recursive transpose in Julia is provided by thepermutedims
function.
Julia does not require parentheses when writingif
statements orfor
/while
loops: usefor i in [1, 2, 3]
instead offor (i in c(1, 2, 3))
andif i == 1
instead ofif (i == 1)
.
Julia does not treat the numbers0
and1
as Booleans. You cannot writeif (1)
in Julia, becauseif
statements accept only booleans. Instead, you can writeif true
,if Bool(1)
, orif 1==1
.
Julia does not providenrow
andncol
. Instead, usesize(M, 1)
fornrow(M)
andsize(M, 2)
forncol(M)
.
Julia is careful to distinguish scalars, vectors and matrices. In R,1
andc(1)
are the same. In Julia, they cannot be used interchangeably.
Julia cannot assign to the results of function calls on the left hand side of an assignment operation: you cannot writediag(M) = fill(1, n)
.
Julia discourages populating the main namespace with functions. Most statistical functionality for Julia is found inpackages under theJuliaStats organization. For example:
Julia provides tuples and real hash tables, but not R-style lists. When returning multiple items, you should typically use a tuple or a named tuple: instead oflist(a = 1, b = 2)
, use(1, 2)
or(a=1, b=2)
.
Julia encourages users to write their own types, which are easier to use than S3 or S4 objects in R. Julia's multiple dispatch system means thattable(x::TypeA)
andtable(x::TypeB)
act like R'stable.TypeA(x)
andtable.TypeB(x)
.
In Julia, values are not copied when assigned or passed to a function. If a function modifies an array, the changes will be visible in the caller. This is very different from R and allows new functions to operate on large data structures much more efficiently.
In Julia, vectors and matrices are concatenated usinghcat
,vcat
andhvcat
, notc
,rbind
andcbind
like in R.
In Julia, a range likea:b
is not shorthand for a vector like in R, but is a specializedAbstractRange
object that is used for iteration. To convert a range into a vector, usecollect(a:b)
.
The:
operator has a different precedence in R and Julia. In particular, in Julia arithmetic operators have higher precedence than the:
operator, whereas the reverse is true in R. For example,1:n-1
in Julia is equivalent to1:(n-1)
in R.
Julia'smax
andmin
are the equivalent ofpmax
andpmin
respectively in R, but both arguments need to have the same dimensions. Whilemaximum
andminimum
replacemax
andmin
in R, there are important differences.
Julia'ssum
,prod
,maximum
, andminimum
are different from their counterparts in R. They all accept an optional keyword argumentdims
, which indicates the dimensions, over which the operation is carried out. For instance, letA = [1 2; 3 4]
in Julia andB <- rbind(c(1,2),c(3,4))
be the same matrix in R. Thensum(A)
gives the same result assum(B)
, butsum(A, dims=1)
is a row vector containing the sum over each column andsum(A, dims=2)
is a column vector containing the sum over each row. This contrasts to the behavior of R, where separatecolSums(B)
androwSums(B)
functions provide these functionalities. If thedims
keyword argument is a vector, then it specifies all the dimensions over which the sum is performed, while retaining the dimensions of the summed array, e.g.sum(A, dims=(1,2)) == hcat(10)
. It should be noted that there is no error checking regarding the second argument.
Julia has several functions that can mutate their arguments. For example, it has bothsort
andsort!
.
In R, performance requires vectorization. In Julia, almost the opposite is true: the best performing code is often achieved by using devectorized loops.
Julia is eagerly evaluated and does not support R-style lazy evaluation. For most users, this means that there are very few unquoted expressions or column names.
Julia does not support theNULL
type. The closest equivalent isnothing
, but it behaves like a scalar value rather than like a list. Usex === nothing
instead ofis.null(x)
.
In Julia, missing values are represented by themissing
object rather than byNA
. Useismissing(x)
(orismissing.(x)
for element-wise operation on vectors) instead ofis.na(x)
. Theskipmissing
function is generally used instead ofna.rm=TRUE
(though in some particular cases functions take askipmissing
argument).
Julia lacks the equivalent of R'sassign
orget
.
In Julia,return
does not require parentheses.
In R, an idiomatic way to remove unwanted values is to use logical indexing, like in the expressionx[x>3]
or in the statementx = x[x>3]
to modifyx
in-place. In contrast, Julia provides the higher order functionsfilter
andfilter!
, allowing users to writefilter(z->z>3, x)
andfilter!(z->z>3, x)
as alternatives to the corresponding transliterationsx[x.>3]
andx = x[x.>3]
. Usingfilter!
reduces the use of temporary arrays.
for
,if
,while
, etc. blocks are terminated by theend
keyword. Indentation level is not significant as it is in Python. Unlike Python, Julia has nopass
keyword."text"
) in Julia (with three double quotation marks for multi-line strings), whereas in Python they can be denoted either by single ('text'
) or double quotation marks ("text"
). Single quotation marks are used for characters in Julia ('c'
).*
in Julia, not+
like in Python. Analogously, string repetition is done with^
, not*
. Implicit string concatenation of string literals like in Python (e.g.'ab' 'cd' == 'abcd'
) is not done in Julia.Vector{Any}
type or more generallyVector{T}
whereT
is some non-concrete element type. "Fast" arrays like NumPy arrays that store elements in-place (i.e.,dtype
isnp.float64
,[('f1', np.uint64), ('f2', np.int32)]
, etc.) can be represented byArray{T}
whereT
is a concrete, immutable element type. This includes built-in types likeFloat64
,Int32
,Int64
but also more complex types likeTuple{UInt64,Float64}
and many user-defined types as well.a[2:3]
in Julia isa[1:3]
in Python.a[-1]
anda[-2]
, should be writtena[end]
anda[end-1]
in Julia.end
for indexing until the last element.x[1:]
in Python is equivalent tox[2:end]
in Julia.:
before any object creates aSymbol
orquotes an expression; so,x[:5]
is same asx[5]
. If you want to get the firstn
elements of an array, then use range indexing.x[start:step:stop]
, whereas Python's format isx[start:(stop+1):step]
. Hence,x[0:10:2]
in Python is equivalent tox[1:2:10]
in Julia. Similarly,x[::-1]
in Python, which refers to the reversed array, is equivalent tox[end:-1:1]
in Julia.start:step:stop
, the same syntax it uses in array-indexing. Therange
function is also supported.X[[1,2], [1,3]]
refers to a sub-matrix that contains the intersections of the first and second rows with the first and third columns. In Python,X[[1,2], [1,3]]
refers to a vector that contains the values of cell[1,1]
and[2,3]
in the matrix.X[[1,2], [1,3]]
in Julia is equivalent withX[np.ix_([0,1],[0,2])]
in Python.X[[0,1], [0,2]]
in Python is equivalent withX[[CartesianIndex(1,1), CartesianIndex(2,3)]]
in Julia.+=
,-=
, ...) arenot in-place whereas NumPy's are. This meansA = [1, 1]; B = A; B += [3, 3]
doesn't change values inA
, it rather rebinds the nameB
to the result of the right-hand sideB = B + 3
, which is a new array. For in-place operation, useB .+= 3
(see alsodot operators), explicit loops, orInplaceOps.jl
.f(x=rand()) = x
returns a new random number every time it is invoked without argument. On the other hand, the functiong(x=[1,2]) = push!(x,3)
returns[1,2,3]
every time it is called asg()
.MethodError
or calling of the wrong method.%
is the remainder operator, whereas in Python it is the modulus.Int
type corresponds to the machine integer type (Int32
orInt64
), unlike in Python, whereint
is an arbitrary length integer. This means in Julia theInt
type will overflow, such that2^64 == 0
. If you need larger values use another appropriate type, such asInt128
,BigInt
or a floating point type likeFloat64
.sqrt(-1)
is represented in Julia asim
, notj
as in Python.^
, not**
as in Python.nothing
of typeNothing
to represent a null value, whereas Python usesNone
of typeNoneType
.A
andB
are matrices,A * B
in Julia performs matrix multiplication, not element-wise multiplication as in Python.A * B
in Julia is equivalent withA @ B
in Python, whereasA * B
in Python is equivalent withA .* B
in Julia.'
in Julia returns an adjoint of a vector (a lazy representation of row vector), whereas the transpose operator.T
over a vector in Python returns the original vector (non-op).x = MyClass(*args); x.f(y)
) corresponds to a function call in Julia, e.g.x = MyType(args...); f(x, y)
. In general, multiple dispatch is more flexible and powerful than the Python class system.include
. While the Python equivalent (exec
) is not typical for this use (it will silently clobber prior definitions), Julia programs are defined as a unit at themodule
level withusing
orimport
, which will only get executed once when first needed–likeinclude
in Python. Within those modules, the individual files that make up that module are loaded withinclude
by listing them once in the intended order.x > 0 ? 1 : -1
in Julia corresponds to a conditional expression in Python1 if x > 0 else -1
.@
symbol refers to a macro, whereas in Python it refers to a decorator.try
—catch
—finally
, instead oftry
—except
—finally
. In contrast to Python, it is not recommended to use exception handling as part of the normal workflow in Julia (compared with Python, Julia is faster at ordinary control flow but slower at exception-catching).int(3.7)
should befloor(Int, 3.7)
orInt(floor(3.7))
and is distinguished fromround(Int, 3.7)
.floor(x)
andround(x)
on their own return an integer value of the same type asx
rather than always returningInt
.float("3.7")
would beparse(Float64, "3.7")
in Julia.if "a":
means the following block is executed, andif "":
means it is not). In Julia, you need explicit conversion toBool
(e.g.if "a"
throws an exception). If you want to test for a non-empty string in Julia, you would explicitly writeif !isempty("")
. Perhaps surprisingly, in Pythonif "False"
andbool("False")
both evaluate toTrue
(because"False"
is a non-empty string); in Julia,parse(Bool, "false")
returnsfalse
.try
—catch
—finally
. Note that comprehensions (list, generator, etc.) introduce a new local scope both in Python and Julia, whereasif
blocks do not introduce a new local scope in both languages.A[i,j]
. This syntax is not just syntactic sugar for a reference to a pointer or address as in C/C++. Seethe manual entry about array construction.A = B
, changing elements ofB
will modifyA
as well. Updating operators like+=
do not operate in-place, they are equivalent toA = A + B
which rebinds the left-hand side to the result of the right-hand side expression.42
) create signed integers, of typeInt
, but literals too large to fit in the machine word size will automatically be promoted to a larger size type, such asInt64
(ifInt
isInt32
),Int128
, or the arbitrarily largeBigInt
type. There are no numeric literal suffixes, such asL
,LL
,U
,UL
,ULL
to indicate unsigned and/or signed vs. unsigned. Decimal literals are always signed, and hexadecimal literals (which start with0x
like C/C++), are unsigned, unless when they encode more than 128 bits, in which case they are of typeBigInt
. Hexadecimal literals also, unlike C/C++/Java and unlike decimal literals in Julia, have a type based on thelength of the literal, including leading 0s. For example,0x0
and0x00
have typeUInt8
,0x000
and0x0000
have typeUInt16
, then literals with 5 to 8 hex digits have typeUInt32
, 9 to 16 hex digits typeUInt64
, 17 to 32 hex digits typeUInt128
, and more that 32 hex digits typeBigInt
. This needs to be taken into account when defining hexadecimal masks, for example~0xf == 0xf0
is very different from~0x000f == 0xfff0
. 64 bitFloat64
and 32 bitFloat32
bit literals are expressed as1.0
and1.0f0
respectively. Floating point literals are rounded (and not promoted to theBigFloat
type) if they can not be exactly represented. Floating point literals are closer in behavior to C/C++. Octal (prefixed with0o
) and binary (prefixed with0b
) literals are also treated as unsigned (orBigInt
for more than 128 bits)./
returns a floating point number when both operands are of integer type. To perform integer division, usediv
or÷
.Array
with floating point types is generally an error in Julia. The Julia equivalent of the C expressiona[i / 2]
isa[i ÷ 2 + 1]
, wherei
is of integer type."
or"""
,"""
delimited literals can contain"
characters without quoting it like"\""
. String literals can have values of other variables or expressions interpolated into them, indicated by$variablename
or$(expression)
, which evaluates the variable name or the expression in the context of the function.//
indicates aRational
number, and not a single-line comment (which is#
in Julia)#=
indicates the start of a multiline comment, and=#
ends it.return
keyword. Multiple values can be returned from functions and assigned as tuples, e.g.(a, b) = myfunction()
ora, b = myfunction()
, instead of having to pass pointers to values as one would have to do in C/C++ (i.e.a = myfunction(&b)
.println
or@printf
can be used to print specific output. In the REPL,;
can be used to suppress output.;
also has a different meaning within[ ]
, something to watch out for.;
can be used to separate expressions on a single line, but are not strictly necessary in many cases, and are more an aid to readability.⊻
(xor
) performs the bitwise XOR operation, i.e.^
in C/C++. Also, the bitwise operators do not have the same precedence as C/C++, so parenthesis may be required.^
is exponentiation (pow), not bitwise XOR as in C/C++ (use⊻
, orxor
, in Julia)>>
and>>>
.>>
performs an arithmetic shift,>>>
always performs a logical shift, unlike C/C++, where the meaning of>>
depends on the type of the value being shifted.->
creates an anonymous function, it does not access a member via a pointer.if
statements orfor
/while
loops: usefor i in [1, 2, 3]
instead offor (int i=1; i <= 3; i++)
andif i == 1
instead ofif (i == 1)
.0
and1
as Booleans. You cannot writeif (1)
in Julia, becauseif
statements accept only booleans. Instead, you can writeif true
,if Bool(1)
, orif 1==1
.end
to denote the end of conditional blocks, likeif
, loop blocks, likewhile
/for
, and functions. In lieu of the one-lineif ( cond ) statement
, Julia allows statements of the formif cond; statement; end
,cond && statement
and!cond || statement
. Assignment statements in the latter two syntaxes must be explicitly wrapped in parentheses, e.g.cond && (x = value)
, because of the operator precedence.@
character, and have both a function-like syntax,@mymacro(arg1, arg2, arg3)
, and a statement-like syntax,@mymacro arg1 arg2 arg3
. The forms are interchangeable; the function-like form is particularly useful if the macro appears within another expression, and is often clearest. The statement-like form is often used to annotate blocks, as in the distributedfor
construct:@distributed for i in 1:n; #= body =#; end
. Where the end of the macro construct may be unclear, use the function-like form.@enum(name, value1, value2, ...)
For example:@enum(Fruit, banana=1, apple, pear)
!
at the end of the name, for examplepush!
.this
, using the most-specific-declaration rule).namespace
s correspond roughly to Juliamodule
s.using MyNamespace::myfun
(C++) corresponds roughly toimport MyModule: myfun
(Julia).using namespace MyNamespace
(C++) corresponds roughly tousing MyModule
(Julia)export
ed symbols are made available to the calling module.import
/using
keywords (Julia) alsoload modules (see below).import
/using
(Julia) works only at the global scope level (module
s)using namespace X
works within arbitrary scopes (ex: function scope).module
s are global scopes (not necessarily "software modules").make
scripts, Julia uses "Project Environments" (sometimes called either "Project" or "Environment").Pkg.add()
function or Pkg REPL mode. (This does notload said package, however).Project.toml
file.Manifest.toml
file byPkg.resolve()
.import
orusing
.#include <moduleheader>
to get object/function declarations, and link in libraries when you build the executable.#pragma once
to C/C++).Base.LOAD_PATH
array.Pkg.add()
tool prior to being loaded withimport
orusing
. They are simply available to the project..c
/.cpp
files are compiled & added to a library with build/make
scripts.import [PkgName]
/using [PkgName]
statements load[PkgName].jl
located in a package's[PkgName]/src/
subdirectory.[PkgName].jl
typically loads associated source files with calls toinclude "[someotherfile].jl"
.include "./path/to/somefile.jl"
(Julia) is very similar to#include "./path/to/somefile.jl"
(C/C++).include "..."
(Julia) is not used to include header files (not required).include "..."
(Julia) to load code from other "software modules" (useimport
/using
instead).include "path/to/some/module.jl"
(Julia) would instantiate multiple versions of the same code in different modules (creatingdistinct types (etc.) with thesame names).include "somefile.jl"
is typically used to assemble multiple fileswithin the same Julia package ("software module"). It is therefore relatively straightforward to ensure file areinclude
d only once (No#ifdef
confusion)..h
/.hpp
files whereas Juliamodule
s mark specific symbols that are intended for their users aspublic
orexport
ed.module
s simply add functionality by generating new "methods" to existing functions (ex:Base.push!
).export
all symbols required to use their package/module, but should still mark unexported user facing symbols aspublic
.MyModule.run_this_task(...)
).Software Concept | Julia | C/C++ |
---|---|---|
unnamed scope | begin ...end | { ...} |
function scope | function x() ...end | int x() { ...} |
global scope | module MyMod ...end | namespace MyNS { ...} |
software module | A Julia "package" | .h /.hpp files<br>+compiledsomelib.a |
assembling<br>software modules | SomePkg.jl : ...<br>import("subfile1.jl") <br>import("subfile2.jl") <br>... | $(AR) *.o ⇒somelib.a |
import<br>software module | import SomePkg | #include <somelib> <br>+link insomelib.a |
module library | LOAD_PATH[] , *Git repository,<br>**custom package registry | more.h /.hpp files<br>+bigger compiledsomebiglib.a |
* The Julia package manager supports registering multiple packages from a single Git repository.<br> * This allows users to house a library of related packages in a single repository.<br> ** Julia registries are primarily designed to provide versioning \& distribution of packages.<br> ** Custom package registries can be used to create a type of module library.
Julia uses 1-based indexing for arrays by default, and it can also handle arbitraryindex offsets.
Functions and variables share the same namespace (“Lisp-1”).
There is aPair
type, but it is not meant to be used as aCOMMON-LISP:CONS
. Various iterable collections can be used interchangeably in most parts of the language (eg splatting, tuples, etc).Tuple
s are the closest to Common Lisp lists forshort collections of heterogeneous elements. UseNamedTuple
s in place of alists. For larger collections of homogeneous types,Array
s andDict
s should be used.
The typical Julia workflow for prototyping also uses continuous manipulation of the image, implemented with theRevise.jl package.
For performance, Julia prefers that operations havetype stability. Where Common Lisp abstracts away from the underlying machine operations, Julia cleaves closer to them. For example:
/
always returns a floating-point result, even if the computation is exact.//
always returns a rational result÷
always returns a (truncated) integer resultModules (namespaces) can be hierarchical.import
andusing
have a dual role: they load the code and make it available in the namespace.import
for only the module name is possible (roughly equivalent toASDF:LOAD-OP
). Slot names don't need to be exported separately. Global variables can't be assigned to from outside the module (except witheval(mod, :(var = val))
as an escape hatch).
Macros start with@
, and are not as seamlessly integrated into the language as Common Lisp; consequently, macro usage is not as widespread as in the latter. A form of hygiene formacros is supported by the language. Because of the different surface syntax, there is no equivalent toCOMMON-LISP:&BODY
.
All functions are generic and use multiple dispatch. Argument lists don't have to follow the same template, which leads to a powerful idiom (seedo
). Optional and keyword arguments are handled differently. Method ambiguities are not resolved like in the Common Lisp Object System, necessitating the definition of a more specific method for the intersection.
Symbols do not belong to any package, and do not contain any valuesper se.M.var
evaluates the symbolvar
in the moduleM
.
A functional programming style is fully supported by the language, including closures, but isn't always the idiomatic solution for Julia. Someworkarounds may be necessary for performance when modifying captured variables.
Settings
This document was generated withDocumenter.jl version 1.8.0 onWednesday 9 July 2025. Using Julia version 1.11.6.