mollusk 0e4acfb8f2 fix incorrect folder name for julia-0.6.x
Former-commit-id: ef2c7401e0876f22d2f7762d182cfbcd5a7d9c70
2018-06-11 03:28:36 -07:00

70 lines
31 KiB
HTML

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><title>Style Guide · The Julia Language</title><script>(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-28835595-6', 'auto');
ga('send', 'pageview');
</script><link href="https://cdnjs.cloudflare.com/ajax/libs/normalize/4.2.0/normalize.min.css" rel="stylesheet" type="text/css"/><link href="https://fonts.googleapis.com/css?family=Lato|Roboto+Mono" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css" rel="stylesheet" type="text/css"/><script>documenterBaseURL=".."</script><script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.2.0/require.min.js" data-main="../assets/documenter.js"></script><script src="../siteinfo.js"></script><script src="../../versions.js"></script><link href="../assets/documenter.css" rel="stylesheet" type="text/css"/><link href="../assets/julia-manual.css" rel="stylesheet" type="text/css"/></head><body><nav class="toc"><a href="../index.html"><img class="logo" src="../assets/logo.png" alt="The Julia Language logo"/></a><h1>The Julia Language</h1><select id="version-selector" onChange="window.location.href=this.value" style="visibility: hidden"></select><form class="search" id="search-form" action="../search.html"><input id="search-query" name="q" type="text" placeholder="Search docs"/></form><ul><li><a class="toctext" href="../index.html">Home</a></li><li><span class="toctext">Manual</span><ul><li><a class="toctext" href="introduction.html">Introduction</a></li><li><a class="toctext" href="getting-started.html">Getting Started</a></li><li><a class="toctext" href="variables.html">Variables</a></li><li><a class="toctext" href="integers-and-floating-point-numbers.html">Integers and Floating-Point Numbers</a></li><li><a class="toctext" href="mathematical-operations.html">Mathematical Operations and Elementary Functions</a></li><li><a class="toctext" href="complex-and-rational-numbers.html">Complex and Rational Numbers</a></li><li><a class="toctext" href="strings.html">Strings</a></li><li><a class="toctext" href="functions.html">Functions</a></li><li><a class="toctext" href="control-flow.html">Control Flow</a></li><li><a class="toctext" href="variables-and-scoping.html">Scope of Variables</a></li><li><a class="toctext" href="types.html">Types</a></li><li><a class="toctext" href="methods.html">Methods</a></li><li><a class="toctext" href="constructors.html">Constructors</a></li><li><a class="toctext" href="conversion-and-promotion.html">Conversion and Promotion</a></li><li><a class="toctext" href="interfaces.html">Interfaces</a></li><li><a class="toctext" href="modules.html">Modules</a></li><li><a class="toctext" href="documentation.html">Documentation</a></li><li><a class="toctext" href="metaprogramming.html">Metaprogramming</a></li><li><a class="toctext" href="arrays.html">Multi-dimensional Arrays</a></li><li><a class="toctext" href="linear-algebra.html">Linear algebra</a></li><li><a class="toctext" href="networking-and-streams.html">Networking and Streams</a></li><li><a class="toctext" href="parallel-computing.html">Parallel Computing</a></li><li><a class="toctext" href="dates.html">Date and DateTime</a></li><li><a class="toctext" href="interacting-with-julia.html">Interacting With Julia</a></li><li><a class="toctext" href="running-external-programs.html">Running External Programs</a></li><li><a class="toctext" href="calling-c-and-fortran-code.html">Calling C and Fortran Code</a></li><li><a class="toctext" href="handling-operating-system-variation.html">Handling Operating System Variation</a></li><li><a class="toctext" href="environment-variables.html">Environment Variables</a></li><li><a class="toctext" href="embedding.html">Embedding Julia</a></li><li><a class="toctext" href="packages.html">Packages</a></li><li><a class="toctext" href="profile.html">Profiling</a></li><li><a class="toctext" href="stacktraces.html">Stack Traces</a></li><li><a class="toctext" href="performance-tips.html">Performance Tips</a></li><li><a class="toctext" href="workflow-tips.html">Workflow Tips</a></li><li class="current"><a class="toctext" href="style-guide.html">Style Guide</a><ul class="internal"><li><a class="toctext" href="#Write-functions,-not-just-scripts-1">Write functions, not just scripts</a></li><li><a class="toctext" href="#Avoid-writing-overly-specific-types-1">Avoid writing overly-specific types</a></li><li><a class="toctext" href="#Handle-excess-argument-diversity-in-the-caller-1">Handle excess argument diversity in the caller</a></li><li><a class="toctext" href="#Append-!-to-names-of-functions-that-modify-their-arguments-1">Append <code>!</code> to names of functions that modify their arguments</a></li><li><a class="toctext" href="#Avoid-strange-type-Unions-1">Avoid strange type <code>Union</code>s</a></li><li><a class="toctext" href="#Avoid-type-Unions-in-fields-1">Avoid type Unions in fields</a></li><li><a class="toctext" href="#Avoid-elaborate-container-types-1">Avoid elaborate container types</a></li><li><a class="toctext" href="#Use-naming-conventions-consistent-with-Julia&#39;s-base/-1">Use naming conventions consistent with Julia&#39;s <code>base/</code></a></li><li><a class="toctext" href="#Don&#39;t-overuse-try-catch-1">Don&#39;t overuse try-catch</a></li><li><a class="toctext" href="#Don&#39;t-parenthesize-conditions-1">Don&#39;t parenthesize conditions</a></li><li><a class="toctext" href="#Don&#39;t-overuse-...-1">Don&#39;t overuse <code>...</code></a></li><li><a class="toctext" href="#Don&#39;t-use-unnecessary-static-parameters-1">Don&#39;t use unnecessary static parameters</a></li><li><a class="toctext" href="#Avoid-confusion-about-whether-something-is-an-instance-or-a-type-1">Avoid confusion about whether something is an instance or a type</a></li><li><a class="toctext" href="#Don&#39;t-overuse-macros-1">Don&#39;t overuse macros</a></li><li><a class="toctext" href="#Don&#39;t-expose-unsafe-operations-at-the-interface-level-1">Don&#39;t expose unsafe operations at the interface level</a></li><li><a class="toctext" href="#Don&#39;t-overload-methods-of-base-container-types-1">Don&#39;t overload methods of base container types</a></li><li><a class="toctext" href="#Avoid-type-piracy-1">Avoid type piracy</a></li><li><a class="toctext" href="#Be-careful-with-type-equality-1">Be careful with type equality</a></li><li><a class="toctext" href="#Do-not-write-x-f(x)-1">Do not write <code>x-&gt;f(x)</code></a></li><li><a class="toctext" href="#Avoid-using-floats-for-numeric-literals-in-generic-code-when-possible-1">Avoid using floats for numeric literals in generic code when possible</a></li></ul></li><li><a class="toctext" href="faq.html">Frequently Asked Questions</a></li><li><a class="toctext" href="noteworthy-differences.html">Noteworthy Differences from other Languages</a></li><li><a class="toctext" href="unicode-input.html">Unicode Input</a></li></ul></li><li><span class="toctext">Standard Library</span><ul><li><a class="toctext" href="../stdlib/base.html">Essentials</a></li><li><a class="toctext" href="../stdlib/collections.html">Collections and Data Structures</a></li><li><a class="toctext" href="../stdlib/math.html">Mathematics</a></li><li><a class="toctext" href="../stdlib/numbers.html">Numbers</a></li><li><a class="toctext" href="../stdlib/strings.html">Strings</a></li><li><a class="toctext" href="../stdlib/arrays.html">Arrays</a></li><li><a class="toctext" href="../stdlib/parallel.html">Tasks and Parallel Computing</a></li><li><a class="toctext" href="../stdlib/linalg.html">Linear Algebra</a></li><li><a class="toctext" href="../stdlib/constants.html">Constants</a></li><li><a class="toctext" href="../stdlib/file.html">Filesystem</a></li><li><a class="toctext" href="../stdlib/io-network.html">I/O and Network</a></li><li><a class="toctext" href="../stdlib/punctuation.html">Punctuation</a></li><li><a class="toctext" href="../stdlib/sort.html">Sorting and Related Functions</a></li><li><a class="toctext" href="../stdlib/pkg.html">Package Manager Functions</a></li><li><a class="toctext" href="../stdlib/dates.html">Dates and Time</a></li><li><a class="toctext" href="../stdlib/iterators.html">Iteration utilities</a></li><li><a class="toctext" href="../stdlib/test.html">Unit Testing</a></li><li><a class="toctext" href="../stdlib/c.html">C Interface</a></li><li><a class="toctext" href="../stdlib/libc.html">C Standard Library</a></li><li><a class="toctext" href="../stdlib/libdl.html">Dynamic Linker</a></li><li><a class="toctext" href="../stdlib/profile.html">Profiling</a></li><li><a class="toctext" href="../stdlib/stacktraces.html">StackTraces</a></li><li><a class="toctext" href="../stdlib/simd-types.html">SIMD Support</a></li></ul></li><li><span class="toctext">Developer Documentation</span><ul><li><a class="toctext" href="../devdocs/reflection.html">Reflection and introspection</a></li><li><span class="toctext">Documentation of Julia&#39;s Internals</span><ul><li><a class="toctext" href="../devdocs/init.html">Initialization of the Julia runtime</a></li><li><a class="toctext" href="../devdocs/ast.html">Julia ASTs</a></li><li><a class="toctext" href="../devdocs/types.html">More about types</a></li><li><a class="toctext" href="../devdocs/object.html">Memory layout of Julia Objects</a></li><li><a class="toctext" href="../devdocs/eval.html">Eval of Julia code</a></li><li><a class="toctext" href="../devdocs/callconv.html">Calling Conventions</a></li><li><a class="toctext" href="../devdocs/compiler.html">High-level Overview of the Native-Code Generation Process</a></li><li><a class="toctext" href="../devdocs/functions.html">Julia Functions</a></li><li><a class="toctext" href="../devdocs/cartesian.html">Base.Cartesian</a></li><li><a class="toctext" href="../devdocs/meta.html">Talking to the compiler (the <code>:meta</code> mechanism)</a></li><li><a class="toctext" href="../devdocs/subarrays.html">SubArrays</a></li><li><a class="toctext" href="../devdocs/sysimg.html">System Image Building</a></li><li><a class="toctext" href="../devdocs/llvm.html">Working with LLVM</a></li><li><a class="toctext" href="../devdocs/stdio.html">printf() and stdio in the Julia runtime</a></li><li><a class="toctext" href="../devdocs/boundscheck.html">Bounds checking</a></li><li><a class="toctext" href="../devdocs/locks.html">Proper maintenance and care of multi-threading locks</a></li><li><a class="toctext" href="../devdocs/offset-arrays.html">Arrays with custom indices</a></li><li><a class="toctext" href="../devdocs/libgit2.html">Base.LibGit2</a></li><li><a class="toctext" href="../devdocs/require.html">Module loading</a></li></ul></li><li><span class="toctext">Developing/debugging Julia&#39;s C code</span><ul><li><a class="toctext" href="../devdocs/backtraces.html">Reporting and analyzing crashes (segfaults)</a></li><li><a class="toctext" href="../devdocs/debuggingtips.html">gdb debugging tips</a></li><li><a class="toctext" href="../devdocs/valgrind.html">Using Valgrind with Julia</a></li><li><a class="toctext" href="../devdocs/sanitizers.html">Sanitizer support</a></li></ul></li></ul></li></ul></nav><article id="docs"><header><nav><ul><li>Manual</li><li><a href="style-guide.html">Style Guide</a></li></ul><a class="edit-page" href="https://github.com/JuliaLang/julia/blob/master/doc/src/manual/style-guide.md"><span class="fa"></span> Edit on GitHub</a></nav><hr/><div id="topbar"><span>Style Guide</span><a class="fa fa-bars" href="#"></a></div></header><h1><a class="nav-anchor" id="Style-Guide-1" href="#Style-Guide-1">Style Guide</a></h1><p>The following sections explain a few aspects of idiomatic Julia coding style. None of these rules are absolute; they are only suggestions to help familiarize you with the language and to help you choose among alternative designs.</p><h2><a class="nav-anchor" id="Write-functions,-not-just-scripts-1" href="#Write-functions,-not-just-scripts-1">Write functions, not just scripts</a></h2><p>Writing code as a series of steps at the top level is a quick way to get started solving a problem, but you should try to divide a program into functions as soon as possible. Functions are more reusable and testable, and clarify what steps are being done and what their inputs and outputs are. Furthermore, code inside functions tends to run much faster than top level code, due to how Julia&#39;s compiler works.</p><p>It is also worth emphasizing that functions should take arguments, instead of operating directly on global variables (aside from constants like <a href="../stdlib/numbers.html#Base.pi"><code>pi</code></a>).</p><h2><a class="nav-anchor" id="Avoid-writing-overly-specific-types-1" href="#Avoid-writing-overly-specific-types-1">Avoid writing overly-specific types</a></h2><p>Code should be as generic as possible. Instead of writing:</p><pre><code class="language-julia">convert(Complex{Float64}, x)</code></pre><p>it&#39;s better to use available generic functions:</p><pre><code class="language-julia">complex(float(x))</code></pre><p>The second version will convert <code>x</code> to an appropriate type, instead of always the same type.</p><p>This style point is especially relevant to function arguments. For example, don&#39;t declare an argument to be of type <code>Int</code> or <a href="../stdlib/numbers.html#Core.Int32"><code>Int32</code></a> if it really could be any integer, expressed with the abstract type <a href="../stdlib/numbers.html#Core.Integer"><code>Integer</code></a>. In fact, in many cases you can omit the argument type altogether, unless it is needed to disambiguate from other method definitions, since a <a href="../stdlib/base.html#Base.MethodError"><code>MethodError</code></a> will be thrown anyway if a type is passed that does not support any of the requisite operations. (This is known as <a href="https://en.wikipedia.org/wiki/Duck_typing">duck typing</a>.)</p><p>For example, consider the following definitions of a function <code>addone</code> that returns one plus its argument:</p><pre><code class="language-julia">addone(x::Int) = x + 1 # works only for Int
addone(x::Integer) = x + oneunit(x) # any integer type
addone(x::Number) = x + oneunit(x) # any numeric type
addone(x) = x + oneunit(x) # any type supporting + and oneunit</code></pre><p>The last definition of <code>addone</code> handles any type supporting <a href="../stdlib/numbers.html#Base.oneunit"><code>oneunit</code></a> (which returns 1 in the same type as <code>x</code>, which avoids unwanted type promotion) and the <a href="../stdlib/math.html#Base.:+"><code>+</code></a> function with those arguments. The key thing to realize is that there is <em>no performance penalty</em> to defining <em>only</em> the general <code>addone(x) = x + oneunit(x)</code>, because Julia will automatically compile specialized versions as needed. For example, the first time you call <code>addone(12)</code>, Julia will automatically compile a specialized <code>addone</code> function for <code>x::Int</code> arguments, with the call to <code>oneunit</code> replaced by its inlined value <code>1</code>. Therefore, the first three definitions of <code>addone</code> above are completely redundant with the fourth definition.</p><h2><a class="nav-anchor" id="Handle-excess-argument-diversity-in-the-caller-1" href="#Handle-excess-argument-diversity-in-the-caller-1">Handle excess argument diversity in the caller</a></h2><p>Instead of:</p><pre><code class="language-julia">function foo(x, y)
x = Int(x); y = Int(y)
...
end
foo(x, y)</code></pre><p>use:</p><pre><code class="language-julia">function foo(x::Int, y::Int)
...
end
foo(Int(x), Int(y))</code></pre><p>This is better style because <code>foo</code> does not really accept numbers of all types; it really needs <code>Int</code> s.</p><p>One issue here is that if a function inherently requires integers, it might be better to force the caller to decide how non-integers should be converted (e.g. floor or ceiling). Another issue is that declaring more specific types leaves more &quot;space&quot; for future method definitions.</p><h2><a class="nav-anchor" id="Append-!-to-names-of-functions-that-modify-their-arguments-1" href="#Append-!-to-names-of-functions-that-modify-their-arguments-1">Append <code>!</code> to names of functions that modify their arguments</a></h2><p>Instead of:</p><pre><code class="language-julia">function double(a::AbstractArray{&lt;:Number})
for i = 1:endof(a)
a[i] *= 2
end
return a
end</code></pre><p>use:</p><pre><code class="language-julia">function double!(a::AbstractArray{&lt;:Number})
for i = 1:endof(a)
a[i] *= 2
end
return a
end</code></pre><p>The Julia standard library uses this convention throughout and contains examples of functions with both copying and modifying forms (e.g., <a href="../stdlib/sort.html#Base.sort"><code>sort()</code></a> and <a href="../stdlib/sort.html#Base.sort!"><code>sort!()</code></a>), and others which are just modifying (e.g., <a href="../stdlib/collections.html#Base.push!"><code>push!()</code></a>, <a href="../stdlib/collections.html#Base.pop!-Tuple{Any,Any,Any}"><code>pop!()</code></a>, <a href="../stdlib/collections.html#Base.splice!"><code>splice!()</code></a>). It is typical for such functions to also return the modified array for convenience.</p><h2><a class="nav-anchor" id="Avoid-strange-type-Unions-1" href="#Avoid-strange-type-Unions-1">Avoid strange type <code>Union</code>s</a></h2><p>Types such as <code>Union{Function,AbstractString}</code> are often a sign that some design could be cleaner.</p><h2><a class="nav-anchor" id="Avoid-type-Unions-in-fields-1" href="#Avoid-type-Unions-in-fields-1">Avoid type Unions in fields</a></h2><p>When creating a type such as:</p><pre><code class="language-julia">mutable struct MyType
...
x::Union{Void,T}
end</code></pre><p>ask whether the option for <code>x</code> to be <code>nothing</code> (of type <code>Void</code>) is really necessary. Here are some alternatives to consider:</p><ul><li><p>Find a safe default value to initialize <code>x</code> with</p></li><li><p>Introduce another type that lacks <code>x</code></p></li><li><p>If there are many fields like <code>x</code>, store them in a dictionary</p></li><li><p>Determine whether there is a simple rule for when <code>x</code> is <code>nothing</code>. For example, often the field will start as <code>nothing</code> but get initialized at some well-defined point. In that case, consider leaving it undefined at first.</p></li><li><p>If <code>x</code> really needs to hold no value at some times, define it as <code>::Nullable{T}</code> instead, as this guarantees type-stability in the code accessing this field (see <a href="types.html#man-nullable-types-1">Nullable types</a>).</p></li></ul><h2><a class="nav-anchor" id="Avoid-elaborate-container-types-1" href="#Avoid-elaborate-container-types-1">Avoid elaborate container types</a></h2><p>It is usually not much help to construct arrays like the following:</p><pre><code class="language-julia">a = Array{Union{Int,AbstractString,Tuple,Array}}(n)</code></pre><p>In this case <code>Array{Any}(n)</code> is better. It is also more helpful to the compiler to annotate specific uses (e.g. <code>a[i]::Int</code>) than to try to pack many alternatives into one type.</p><h2><a class="nav-anchor" id="Use-naming-conventions-consistent-with-Julia&#39;s-base/-1" href="#Use-naming-conventions-consistent-with-Julia&#39;s-base/-1">Use naming conventions consistent with Julia&#39;s <code>base/</code></a></h2><ul><li><p>modules and type names use capitalization and camel case: <code>module SparseArrays</code>, <code>struct UnitRange</code>.</p></li><li><p>functions are lowercase (<a href="../stdlib/collections.html#Base.maximum-Tuple{Any}"><code>maximum()</code></a>, <a href="../stdlib/base.html#Base.convert"><code>convert()</code></a>) and, when readable, with multiple words squashed together (<a href="../stdlib/base.html#Base.isequal-Tuple{Any,Any}"><code>isequal()</code></a>, <a href="../stdlib/collections.html#Base.haskey"><code>haskey()</code></a>). When necessary, use underscores as word separators. Underscores are also used to indicate a combination of concepts (<a href="../stdlib/parallel.html#Base.Distributed.remotecall_fetch-Tuple{Any,Integer,Vararg{Any,N} where N}"><code>remotecall_fetch()</code></a> as a more efficient implementation of <code>fetch(remotecall(...))</code>) or as modifiers (<a href="../stdlib/arrays.html#Base.sum_kbn"><code>sum_kbn()</code></a>).</p></li><li><p>conciseness is valued, but avoid abbreviation (<a href="../stdlib/collections.html#Base.indexin"><code>indexin()</code></a> rather than <code>indxin()</code>) as it becomes difficult to remember whether and how particular words are abbreviated.</p></li></ul><p>If a function name requires multiple words, consider whether it might represent more than one concept and might be better split into pieces.</p><h2><a class="nav-anchor" id="Don&#39;t-overuse-try-catch-1" href="#Don&#39;t-overuse-try-catch-1">Don&#39;t overuse try-catch</a></h2><p>It is better to avoid errors than to rely on catching them.</p><h2><a class="nav-anchor" id="Don&#39;t-parenthesize-conditions-1" href="#Don&#39;t-parenthesize-conditions-1">Don&#39;t parenthesize conditions</a></h2><p>Julia doesn&#39;t require parens around conditions in <code>if</code> and <code>while</code>. Write:</p><pre><code class="language-julia">if a == b</code></pre><p>instead of:</p><pre><code class="language-julia">if (a == b)</code></pre><h2><a class="nav-anchor" id="Don&#39;t-overuse-...-1" href="#Don&#39;t-overuse-...-1">Don&#39;t overuse <code>...</code></a></h2><p>Splicing function arguments can be addictive. Instead of <code>[a..., b...]</code>, use simply <code>[a; b]</code>, which already concatenates arrays. <a href="../stdlib/collections.html#Base.collect-Tuple{Any}"><code>collect(a)</code></a> is better than <code>[a...]</code>, but since <code>a</code> is already iterable it is often even better to leave it alone, and not convert it to an array.</p><h2><a class="nav-anchor" id="Don&#39;t-use-unnecessary-static-parameters-1" href="#Don&#39;t-use-unnecessary-static-parameters-1">Don&#39;t use unnecessary static parameters</a></h2><p>A function signature:</p><pre><code class="language-julia">foo(x::T) where {T&lt;:Real} = ...</code></pre><p>should be written as:</p><pre><code class="language-julia">foo(x::Real) = ...</code></pre><p>instead, especially if <code>T</code> is not used in the function body. Even if <code>T</code> is used, it can be replaced with <a href="../stdlib/base.html#Core.typeof"><code>typeof(x)</code></a> if convenient. There is no performance difference. Note that this is not a general caution against static parameters, just against uses where they are not needed.</p><p>Note also that container types, specifically may need type parameters in function calls. See the FAQ <a href="performance-tips.html#Avoid-fields-with-abstract-containers-1">Avoid fields with abstract containers</a> for more information.</p><h2><a class="nav-anchor" id="Avoid-confusion-about-whether-something-is-an-instance-or-a-type-1" href="#Avoid-confusion-about-whether-something-is-an-instance-or-a-type-1">Avoid confusion about whether something is an instance or a type</a></h2><p>Sets of definitions like the following are confusing:</p><pre><code class="language-julia">foo(::Type{MyType}) = ...
foo(::MyType) = foo(MyType)</code></pre><p>Decide whether the concept in question will be written as <code>MyType</code> or <code>MyType()</code>, and stick to it.</p><p>The preferred style is to use instances by default, and only add methods involving <code>Type{MyType}</code> later if they become necessary to solve some problem.</p><p>If a type is effectively an enumeration, it should be defined as a single (ideally immutable struct or primitive) type, with the enumeration values being instances of it. Constructors and conversions can check whether values are valid. This design is preferred over making the enumeration an abstract type, with the &quot;values&quot; as subtypes.</p><h2><a class="nav-anchor" id="Don&#39;t-overuse-macros-1" href="#Don&#39;t-overuse-macros-1">Don&#39;t overuse macros</a></h2><p>Be aware of when a macro could really be a function instead.</p><p>Calling <a href="../stdlib/base.html#Core.eval"><code>eval()</code></a> inside a macro is a particularly dangerous warning sign; it means the macro will only work when called at the top level. If such a macro is written as a function instead, it will naturally have access to the run-time values it needs.</p><h2><a class="nav-anchor" id="Don&#39;t-expose-unsafe-operations-at-the-interface-level-1" href="#Don&#39;t-expose-unsafe-operations-at-the-interface-level-1">Don&#39;t expose unsafe operations at the interface level</a></h2><p>If you have a type that uses a native pointer:</p><pre><code class="language-julia">mutable struct NativeType
p::Ptr{UInt8}
...
end</code></pre><p>don&#39;t write definitions like the following:</p><pre><code class="language-julia">getindex(x::NativeType, i) = unsafe_load(x.p, i)</code></pre><p>The problem is that users of this type can write <code>x[i]</code> without realizing that the operation is unsafe, and then be susceptible to memory bugs.</p><p>Such a function should either check the operation to ensure it is safe, or have <code>unsafe</code> somewhere in its name to alert callers.</p><h2><a class="nav-anchor" id="Don&#39;t-overload-methods-of-base-container-types-1" href="#Don&#39;t-overload-methods-of-base-container-types-1">Don&#39;t overload methods of base container types</a></h2><p>It is possible to write definitions like the following:</p><pre><code class="language-julia">show(io::IO, v::Vector{MyType}) = ...</code></pre><p>This would provide custom showing of vectors with a specific new element type. While tempting, this should be avoided. The trouble is that users will expect a well-known type like <code>Vector()</code> to behave in a certain way, and overly customizing its behavior can make it harder to work with.</p><h2><a class="nav-anchor" id="Avoid-type-piracy-1" href="#Avoid-type-piracy-1">Avoid type piracy</a></h2><p>&quot;Type piracy&quot; refers to the practice of extending or redefining methods in Base or other packages on types that you have not defined. In some cases, you can get away with type piracy with little ill effect. In extreme cases, however, you can even crash Julia (e.g. if your method extension or redefinition causes invalid input to be passed to a <code>ccall</code>). Type piracy can complicate reasoning about code, and may introduce incompatibilities that are hard to predict and diagnose.</p><p>As an example, suppose you wanted to define multiplication on symbols in a module:</p><pre><code class="language-julia">module A
import Base.*
*(x::Symbol, y::Symbol) = Symbol(x,y)
end</code></pre><p>The problem is that now any other module that uses <code>Base.*</code> will also see this definition. Since <code>Symbol</code> is defined in Base and is used by other modules, this can change the behavior of unrelated code unexpectedly. There are several alternatives here, including using a different function name, or wrapping the <code>Symbol</code>s in another type that you define.</p><p>Sometimes, coupled packages may engage in type piracy to separate features from definitions, especially when the packages were designed by collaborating authors, and when the definitions are reusable. For example, one package might provide some types useful for working with colors; another package could define methods for those types that enable conversions between color spaces. Another example might be a package that acts as a thin wrapper for some C code, which another package might then pirate to implement a higher-level, Julia-friendly API.</p><h2><a class="nav-anchor" id="Be-careful-with-type-equality-1" href="#Be-careful-with-type-equality-1">Be careful with type equality</a></h2><p>You generally want to use <a href="../stdlib/base.html#Core.isa"><code>isa()</code></a> and <code>&lt;:</code> (<a href="../stdlib/base.html#Core.issubtype"><code>issubtype()</code></a>) for testing types, not <code>==</code>. Checking types for exact equality typically only makes sense when comparing to a known concrete type (e.g. <code>T == Float64</code>), or if you <em>really, really</em> know what you&#39;re doing.</p><h2><a class="nav-anchor" id="Do-not-write-x-f(x)-1" href="#Do-not-write-x-f(x)-1">Do not write <code>x-&gt;f(x)</code></a></h2><p>Since higher-order functions are often called with anonymous functions, it is easy to conclude that this is desirable or even necessary. But any function can be passed directly, without being &quot;wrapped&quot; in an anonymous function. Instead of writing <code>map(x-&gt;f(x), a)</code>, write <a href="../stdlib/collections.html#Base.map"><code>map(f, a)</code></a>.</p><h2><a class="nav-anchor" id="Avoid-using-floats-for-numeric-literals-in-generic-code-when-possible-1" href="#Avoid-using-floats-for-numeric-literals-in-generic-code-when-possible-1">Avoid using floats for numeric literals in generic code when possible</a></h2><p>If you write generic code which handles numbers, and which can be expected to run with many different numeric type arguments, try using literals of a numeric type that will affect the arguments as little as possible through promotion.</p><p>For example,</p><pre><code class="language-julia-repl">julia&gt; f(x) = 2.0 * x
f (generic function with 1 method)
julia&gt; f(1//2)
1.0
julia&gt; f(1/2)
1.0
julia&gt; f(1)
2.0</code></pre><p>while</p><pre><code class="language-julia-repl">julia&gt; g(x) = 2 * x
g (generic function with 1 method)
julia&gt; g(1//2)
1//1
julia&gt; g(1/2)
1.0
julia&gt; g(1)
2</code></pre><p>As you can see, the second version, where we used an <code>Int</code> literal, preserved the type of the input argument, while the first didn&#39;t. This is because e.g. <code>promote_type(Int, Float64) == Float64</code>, and promotion happens with the multiplication. Similarly, <a href="../stdlib/numbers.html#Base.Rational"><code>Rational</code></a> literals are less type disruptive than <a href="../stdlib/numbers.html#Core.Float64"><code>Float64</code></a> literals, but more disruptive than <code>Int</code>s:</p><pre><code class="language-julia-repl">julia&gt; h(x) = 2//1 * x
h (generic function with 1 method)
julia&gt; h(1//2)
1//1
julia&gt; h(1/2)
1.0
julia&gt; h(1)
2//1</code></pre><p>Thus, use <code>Int</code> literals when possible, with <code>Rational{Int}</code> for literal non-integer numbers, in order to make it easier to use your code.</p><footer><hr/><a class="previous" href="workflow-tips.html"><span class="direction">Previous</span><span class="title">Workflow Tips</span></a><a class="next" href="faq.html"><span class="direction">Next</span><span class="title">Frequently Asked Questions</span></a></footer></article></body></html>