{"id":13613828,"url":"https://github.com/JuliaDiff/BlueStyle","last_synced_at":"2025-04-13T18:31:40.456Z","repository":{"id":46224563,"uuid":"208773376","full_name":"JuliaDiff/BlueStyle","owner":"JuliaDiff","description":"A Julia style guide that lives in a blue world","archived":false,"fork":false,"pushed_at":"2024-03-08T02:31:46.000Z","size":156,"stargazers_count":499,"open_issues_count":37,"forks_count":34,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-04-04T13:13:48.345Z","etag":null,"topics":["blue","formatting","julia","julia-language","styleguide"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cc0-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JuliaDiff.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2019-09-16T10:32:52.000Z","updated_at":"2025-03-22T08:13:48.000Z","dependencies_parsed_at":"2024-03-08T03:40:11.862Z","dependency_job_id":null,"html_url":"https://github.com/JuliaDiff/BlueStyle","commit_stats":null,"previous_names":["juliadiff/bluestyle","invenia/bluestyle","invenia/blue"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JuliaDiff%2FBlueStyle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JuliaDiff%2FBlueStyle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JuliaDiff%2FBlueStyle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JuliaDiff%2FBlueStyle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JuliaDiff","download_url":"https://codeload.github.com/JuliaDiff/BlueStyle/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248760391,"owners_count":21157348,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blue","formatting","julia","julia-language","styleguide"],"created_at":"2024-08-01T20:00:53.976Z","updated_at":"2025-04-13T18:31:40.225Z","avatar_url":"https://github.com/JuliaDiff.png","language":null,"funding_links":[],"categories":["Others","Programming Languages"],"sub_categories":["Julia"],"readme":"# Blue: a Style Guide for Julia\n\n[![Code Style: Blue](https://img.shields.io/badge/code%20style-blue-4495d1.svg)](https://github.com/JuliaDiff/BlueStyle)\n\nThis document specifies style conventions for Julia code.\nThese conventions were created from a variety of sources including Python's [PEP8](http://legacy.python.org/dev/peps/pep-0008/), Julia's [Notes for Contributors](https://github.com/JuliaLang/julia/blob/master/CONTRIBUTING.md), and Julia's [Style Guide](https://docs.julialang.org/en/v1/manual/style-guide/).\n\n## A Word on Consistency\n\nWhen adhering to this style it's important to realize that these are guidelines and not rules.\nThis is [stated best in the PEP8](http://legacy.python.org/dev/peps/pep-0008/#a-foolish-consistency-is-the-hobgoblin-of-little-minds):\n\n\u003e A style guide is about consistency.\n\u003e Consistency with this style guide is important.\n\u003e Consistency within a project is more important.\n\u003e Consistency within one module or function is the most important.\n\n\u003e But most importantly: know when to be inconsistent -- sometimes the style guide just doesn't apply.\n\u003e When in doubt, use your best judgment.\n\u003e Look at other examples and decide what looks best.\n\u003e And don't hesitate to ask!\n\n## Synopsis\n\nAttempt to follow both the [Julia Contribution Guidelines](https://github.com/JuliaLang/julia/blob/master/CONTRIBUTING.md#general-formatting-guidelines-for-julia-code-contributions), the [Julia Style Guide](https://docs.julialang.org/en/v1/manual/style-guide/), and this guide.\nWhen convention guidelines conflict this guide takes precedence (known conflicts will be noted in this guide).\n\n- Use 4 spaces per indentation level, no tabs.\n- Try to adhere to a 92 character line length limit.\n- Use upper camel-case convention for [modules](https://docs.julialang.org/en/v1/manual/modules/) and [types](https://docs.julialang.org/en/v1/manual/types/).\n- Use lower case with underscores for method names (note: contrary to this, it is a common stylistic choice in the [Julia base code](https://github.com/JuliaLang/julia/tree/master/base) to use lower case without underscores).\n- Import modules with `using`, with one module per line and at the top of the file when possible.\n- Comments are good, try to explain the intentions of the code.\n- Use whitespace to make the code more readable.\n- No whitespace at the end of a line (trailing whitespace).\n- Avoid padding brackets with spaces. ex. `Int64(value)` preferred over `Int64( value )`.\n\n## Contents\n- [Code Formatting](#code-formatting)\n    - [Module Imports](#module-imports)\n    - [Function Exports](#function-exports)\n    - [Global Variables](#global-variables)\n    - [Function Naming](#function-naming)\n    - [Method Definitions](#method-definitions)\n    - [Keyword Arguments](#keyword-arguments)\n    - [Whitespace](#whitespace)\n    - [NamedTuples](#namedtuples)\n    - [Numbers](#numbers)\n    - [Ternary Operator](#ternary-operator)\n    - [For loops](#for-loops)\n    - [Modules](#modules)\n    - [Type annotation](#type-annotation)\n    - [Package version specifications](#package-version-specifications)\n    - [Comments](#comments)\n    - [Documentation](#documentation)\n- [Test Formatting](#test-formatting)\n    - [Testsets](#testsets)\n    - [Comparisons](#comparisons)\n- [Performance and Optimization](#performance-and-optimization)\n- [Editor Configuration](#editor-configuration)\n    - [Sublime Text Settings](#sublime-text-settings)\n    - [Vim Settings](#vim-settings)\n    - [Atom Settings](#atom-settings)\n    - [VS-Code Settings](#vs-code-settings)\n- [Code Style Badge](#code-style-badge)\n\n## Code Formatting\n\n### Module Imports\n\n[Module imports](https://docs.julialang.org/en/v1/manual/modules/#Summary-of-module-usage-1) should occur at the top of the file or right after a `module` declaration.\nFiles loaded via an `include` should avoid specifying their own module imports and should instead add them to the file in which they were included (e.g. \"src/Example.jl\" or \"test/runtests.jl\").\n\nA module import should only specify a single package per line.\nThe lines should be ordered alphabetically by the package/module name (note: relative imports precede absolute imports).\n\n```julia\n# Yes:\nusing A\nusing B\n\n# No:\nusing A, B\n\n# No:\nusing B\nusing A\n```\n\nImports which explicitly declare what to bring into scope should be grouped into: modules, constants, types, macros, and functions.\nThese groupings should be specified in that order and each group's contents should be sorted alphabetically, typically with modules on a separate line.\nAs pseudo-code:\n\n```julia\nusing Example: $(sort(modules)...)\nusing Example: $(sort(constants)...), $(sort(types)...), $(sort(macros)...), $(sort(functions)...)\n```\n\nIf you are only explicitly importing a few items you can alternatively use the following one-line form:\n\n```julia\nusing Example: $(sort(modules)...), $(sort(constants)...), $(sort(types)...), $(sort(macros)...), $(sort(functions)...)\n```\n\nIn some scenarios there may be alternate ordering within a group which makes more logical sense.\nFor example when explicitly importing subtypes of `Period` you may want to sort them in units largest to smallest:\n\n```julia\nusing Dates: Year, Month, Week, Day, Hour, Minute, Second, Millisecond\n```\n\nExplicit import lines which exceed the line length should use line-continuation or multiple import statements for the same package.\nUsing multiple import statements should be preferred when creating alternate groupings:\n\n```julia\n# Yes:\nusing AVeryLongPackage: AVeryLongType, AnotherVeryLongType, a_very_long_function,\n    another_very_long_function\n\n# Yes:\nusing AVeryLongPackage: AVeryLongType, AnotherVeryLongType\nusing AVeryLongPackage: a_very_long_function, another_very_long_function\n\n# No:\nusing AVeryLongPackage:\n    AVeryLongType,\n    AnotherVeryLongType,\n    a_very_long_function,\n    another_very_long_function\n\n# No:\nusing AVeryLongPackage: AVeryLongType\nusing AVeryLongPackage: AnotherVeryLongType\nusing AVeryLongPackage: a_very_long_function\nusing AVeryLongPackage: another_very_long_function\n```\n\nNote: Prefer the use of imports with explicit declarations when writing packages.\nDoing so will make maintaining the package easier by knowing what functionality the package is importing and when dependencies can safely be dropped.\n\nPrefer the use of `using` over `import` to ensure that extension of a function is always explicit and on purpose:\n\n```julia\n# Yes:\nusing Example\n\nExample.hello(x::Monster) = \"Aargh! It's a Monster!\"\nBase.isreal(x::Ghost) = false\n\n# No:\nimport Base: isreal\nimport Example: hello\n\nhello(x::Monster) = \"Aargh! It's a Monster!\"\nisreal(x::Ghost) = false\n```\n\nIf you do require the use of `import` then create separate groupings for `import` and `using` statements divided by a blank line:\n\n```julia\n# Yes:\nimport A: a\nimport C\n\nusing B\nusing D: d\n\n# No:\nimport A: a\nusing B\nimport C\nusing D: d\n```\n\n### Function Exports\n\nAll functions that are intended to be part of the public API should be exported.\nAll function exports should occur at the top of the main module file, after module imports.\nAvoid splitting a single export over multiple lines; either define one export per line, or group them by theme.\n\n```julia\n# Yes:\nexport foo\nexport bar\nexport qux\n\n# Yes:\nexport get_foo, get_bar\nexport solve_foo, solve_bar\n\n# No:\nexport foo,\n    bar,\n    qux\n```\n\n### Global Variables\n\nGlobal variables should be avoided whenever possible. When required, global variables should be `const`s and have an all uppercase name separated with underscores (e.g. `MY_CONSTANT`).\nThey should be defined at the top of the file, immediately after imports and exports but before an `__init__` function.\nIf you truly want mutable global style behaviour you may want to look into mutable containers or closures.\n\n### Function Naming\n\nNames of functions should describe an action or property irrespective of the type of the argument; the argument's type provides this information instead.\nFor example, `submit_bid(bid)` should be `submit(bid::Bid)` and `bids_in_batch(batch)` should be `bids(batch::Batch)`.\n\nNames of functions should usually be limited to one or two lowercase words separated by underscores.\nIf you find it hard to shorten your function names without losing information, you may need to factor more information into the type signature or split the function's responsibilities into two or more functions.\nIn general, shorter functions with clearly-defined responsibilities are preferred.\n\n**NOTE**: Functions that are only intended for internal use should be marked with a leading underscore (e.g., `_internal_utility_function(X, y)`).\nAlthough it should be much less common, the same naming convention can be used for internal types and constants as well (e.g., `_MyInternalType`, `_MY_CONSTANT`).\nMarking a function as internal or private lets other people know that they shouldn't expect any kind of API stability from that functionality.\n\n### Method Definitions\n\nOnly use short-form function definitions when they fit on a single line:\n\n```julia\n# Yes:\nfoo(x::Int64) = abs(x) + 3\n\n# No:\nfoobar(array_data::AbstractArray{T}, item::T) where {T\u003c:Int64} = T[\n    abs(x) * abs(item) + 3 for x in array_data\n]\n```\n```julia\n# Yes:\nfunction foobar(array_data::AbstractArray{T}, item::T) where T\u003c:Int64\n    return T[abs(x) * abs(item) + 3 for x in array_data]\nend\n\n# No:\nfoobar(\n    array_data::AbstractArray{T},\n    item::T,\n) where {T\u003c:Int64} = T[abs(x) * abs(item) + 3 for x in array_data]\n```\n\nWhen using long-form functions [always use the `return` keyword](https://groups.google.com/forum/#!topic/julia-users/4RVR8qQDrUg):\n\n```julia\n# Yes:\nfunction fnc(x::T) where T\n    result = zero(T)\n    result += fna(x)\n    return result\nend\n\n# No:\nfunction fnc(x::T) where T\n    result = zero(T)\n    result += fna(x)\nend\n```\n```julia\n# Yes:\nfunction Foo(x, y)\n    return new(x, y)\nend\n\n# No:\nfunction Foo(x, y)\n    new(x, y)\nend\n```\n\nWhen using the `return` keyword always explicitly return a value, even if it is `return nothing`.\n```julia\n# Yes:\nfunction maybe_do_thing()\n    # code\n    return nothing\nend\n\n# No:\nfunction maybe_do_thing()\n    # code\n    return\nend\n```\n\nFunctions definitions with parameter lines which exceed 92 characters should separate each parameter by a newline and indent by one-level:\n\n```julia\n# Yes:\nfunction foobar(\n    df::DataFrame,\n    id::Symbol,\n    variable::Symbol,\n    value::AbstractString,\n    prefix::AbstractString=\"\",\n)\n    # code\nend\n\n# Ok:\nfunction foobar(df::DataFrame, id::Symbol, variable::Symbol, value::AbstractString, prefix::AbstractString=\"\")\n    # code\nend\n\n# No: Don't put any args on the same line as the open parenthesis if they won't all fit.\nfunction foobar(df::DataFrame, id::Symbol, variable::Symbol, value::AbstractString,\n    prefix::AbstractString=\"\")\n\n    # code\nend\n\n# No: All args should be on a new line in this case.\nfunction foobar(\n    df::DataFrame, id::Symbol, variable::Symbol, value::AbstractString,\n    prefix::AbstractString=\"\"\n)\n    # code\nend\n\n# No: Indented too much.\nfunction foobar(\n        df::DataFrame,\n        id::Symbol,\n        variable::Symbol,\n        value::AbstractString,\n        prefix::AbstractString=\"\",\n    )\n    # code\nend\n```\n\nIf all of the arguments fit inside the 92 character limit then you can place them on 1 line.\nSimilarly, you can follow the same rule if you break up positional and keyword arguments\nacross two lines.\n\n```julia\n# Ok:\nfunction foobar(\n    df::DataFrame, id::Symbol, variable::Symbol, value::AbstractString; prefix::String=\"\"\n)\n    # code\nend\n\n# Ok: Putting all args and all kwargs on separate lines is fine.\nfunction foobar(\n    df::DataFrame, id::Symbol, variable::Symbol, value::AbstractString;\n    prefix::String=\"\"\n)\n    # code\nend\n\n# Ok: Putting all positional args on 1 line and each kwarg on separate lines.\nfunction foobar(\n    df::DataFrame, id::Symbol, variable::Symbol, value::AbstractString;\n    prefix=\"I'm a long default setting that probably shouldn't exist\",\n    msg=\"I'm another long default setting that probably shouldn't exist\",\n)\n    # code\nend\n\n# No: Because the separate line is more than 92 characters.\nfunction foobar(\n    df::DataFrame, id::Symbol, variable::Symbol, value::AbstractString; prefix::AbstractString=\"\"\n)\n    # code\nend\n\n# No: The args and kwargs should be split up.\nfunction foobar(\n    df::DataFrame, id::Symbol, variable::Symbol,\n    value::AbstractString; prefix::AbstractString=\"\"\n)\n    # code\nend\n\n# No: The kwargs are more than 92 characters.\nfunction foobar(\n    df::DataFrame, id::Symbol, variable::Symbol, value::AbstractString;\n    prefix=\"I'm a long default setting that probably shouldn't exist\", msg=\"I'm another long default settings that probably shouldn't exist\",\n)\n    # code\nend\n```\n### Keyword Arguments\n\nWhen calling a function always separate your keyword arguments from your positional arguments with a semicolon.\nThis avoids mistakes in ambiguous cases (such as splatting a `Dict`).\n\n```julia\n# Yes:\nxy = foo(x; y=3)\nab = foo(; a=1, b=2)\n\n# Ok:\nab = foo(a=1, b=2)\n\n# No:\nxy = foo(x, y=3)\n```\n\n### Whitespace\n\n- Avoid extraneous whitespace immediately inside parentheses, square brackets or braces.\n\n    ```julia\n    # Yes:\n    spam(ham[1], [eggs])\n    \n    # No:\n    spam( ham[ 1 ], [ eggs ] )\n    ```\n\n- Avoid extraneous whitespace immediately before a comma or semicolon:\n\n    ```julia\n    # Yes:\n    if x == 4 @show(x, y); x, y = y, x end\n    \n    # No:\n    if x == 4 @show(x , y) ; x , y = y , x end\n    ```\n\n- Avoid whitespace around `:` in ranges. Use brackets to clarify expressions on either side.\n\n    ```julia\n    # Yes:\n    ham[1:9]\n    ham[9:-3:0]\n    ham[1:step:end]\n    ham[lower:upper-1]\n    ham[lower:upper - 1]\n    ham[lower:(upper + offset)]\n    ham[(lower + offset):(upper + offset)]\n\n    # No:\n    ham[1: 9]\n    ham[9 : -3: 1]\n    ham[lower : upper - 1]\n    ham[lower + offset:upper + offset]  # Avoid as it is easy to read as `ham[lower + (offset:upper) + offset]`\n    ```\n\n- Avoid using more than one space around an assignment (or other) operator to align it with another:\n\n    ```julia\n    # Yes:\n    x = 1\n    y = 2\n    long_variable = 3\n\n    # No:\n    x             = 1\n    y             = 2\n    long_variable = 3\n    ```\n\n- Surround most binary operators with a single space on either side: assignment (`=`), [updating operators](https://docs.julialang.org/en/v1/manual/mathematical-operations/#Updating-operators-1) (`+=`, `-=`, etc.), [numeric comparisons operators](https://docs.julialang.org/en/v1/manual/mathematical-operations/#Numeric-Comparisons-1) (`==`, `\u003c`, `\u003e`, `!=`, etc.), [lambda operator](https://docs.julialang.org/en/v1/manual/functions/#man-anonymous-functions-1) (`-\u003e`). Binary operators that may be excluded from this guideline include: the [range operator](https://docs.julialang.org/en/v1/base/math/#Base.::) (`:`), [rational operator](https://docs.julialang.org/en/v1/base/math/#Base.://) (`//`), [exponentiation operator](https://docs.julialang.org/en/v1/base/math/#Base.:^-Tuple{Number,Number}) (`^`), [optional arguments/keywords](https://docs.julialang.org/en/v1/manual/functions/#Optional-Arguments-1) (e.g. `f(x=1; y=2)`).\n\n    ```julia\n    # Yes:\n    i = j + 1\n    submitted += 1\n    x^2 \u003c y\n\n    # No:\n    i=j+1\n    submitted +=1\n    x^2\u003cy\n    ```\n\n- Avoid using whitespace between unary operands and the expression:\n\n    ```julia\n    # Yes:\n    -1\n    [1 0 -1]\n\n    # No:\n    - 1\n    [1 0 - 1]  # Note: evaluates to `[1 -1]`\n    ```\n\n- Avoid extraneous empty lines. Avoid empty lines between single line method definitions\n    and otherwise separate functions with one empty line, plus a comment if required:\n\n    ```julia\n    # Yes:\n    # Note: an empty line before the first long-form `domaths` method is optional.\n    domaths(x::Number) = x + 5\n    domaths(x::Int) = x + 10\n    function domaths(x::String)\n        return \"A string is a one-dimensional extended object postulated in string theory.\"\n    end\n\n    dophilosophy() = \"Why?\"\n\n    # No:\n    domath(x::Number) = x + 5\n\n    domath(x::Int) = x + 10\n\n\n\n    function domath(x::String)\n        return \"A string is a one-dimensional extended object postulated in string theory.\"\n    end\n\n\n    dophilosophy() = \"Why?\"\n    ```\n\n- Function calls which cannot fit on a single line within the line limit should be broken up such that the lines containing the opening and closing brackets are indented to the same level while the parameters of the function are indented one level further.\n  In most cases the arguments and/or keywords should each be placed on separate lines.\n  Note that this rule conflicts with the typical Julia convention of indenting the next line to align with the open bracket in which the parameter is contained.\n  If working in a package with a different convention follow the convention used in the package over using this guideline.\n\n    ```julia\n    # Yes:\n    f(a, b)\n    constraint = conic_form!(\n        SOCElemConstraint(temp2 + temp3, temp2 - temp3, 2 * temp1),\n        unique_conic_forms,\n    )\n\n    # No:\n    # Note: `f` call is short enough to be on a single line\n    f(\n        a,\n        b,\n    )\n    constraint = conic_form!(SOCElemConstraint(temp2 + temp3,\n                                               temp2 - temp3, 2 * temp1),\n                             unique_conic_forms)\n    ```\n\n- Assignments using expanded notation for arrays or tuples, or function calls should have the first open bracket on the same line assignment operator and the closing bracket should match the indentation level of the assignment.\n  Alternatively you can perform assignments on a single line when they are short:\n\n    ```julia\n    # Yes:\n    arr = [\n        1,\n        2,\n        3,\n    ]\n    arr = [\n        1, 2, 3,\n    ]\n    result = func(\n        arg1,\n        arg2,\n    )\n    arr = [1, 2, 3]\n\n    # No:\n    arr =\n    [\n        1,\n        2,\n        3,\n    ]\n    arr =\n    [\n        1, 2, 3,\n    ]\n    arr = [\n        1,\n        2,\n        3,\n        ]\n    ```\n\n- Nested arrays or tuples that are in expanded notation should have the opening and closing brackets at the same indentation level:\n\n    ```julia\n    # Yes:\n    x = [\n        [\n            1, 2, 3,\n        ],\n        [\n            \"hello\",\n            \"world\",\n        ],\n        ['a', 'b', 'c'],\n    ]\n\n    # No:\n    y = [\n        [\n            1, 2, 3,\n        ], [\n            \"hello\",\n            \"world\",\n        ],\n    ]\n    z = [[\n            1, 2, 3,\n        ], [\n            \"hello\",\n            \"world\",\n        ],\n    ]\n    ```\n\n- Always include the trailing comma when working with expanded arrays, tuples or functions notation.\n  This allows future edits to easily move elements around or add additional elements.\n  The trailing comma should be excluded when the notation is only on a single-line:\n\n    ```julia\n    # Yes:\n    arr = [\n        1,\n        2,\n        3,\n    ]\n    result = func(\n        arg1,\n        arg2,\n    )\n    arr = [1, 2, 3]\n\n    # No:\n    arr = [\n        1,\n        2,\n        3\n    ]\n    result = func(\n        arg1,\n        arg2\n    )\n    arr = [1, 2, 3,]\n    ```\n\n- Triple-quotes and triple-backticks written over multiple lines should be indented.\n  As triple-quotes use the indentation of the lowest indented line (excluding the opening quotes) the least indented line in the string or ending quotes should be indented once.\n  Triple-backticks should also follow this style even though the indentation does not matter for them.\n\n    ```julia\n    # Yes:\n    str = \"\"\"\n        hello\n        world!\n        \"\"\"\n    cmd = ```\n        program\n            --flag value\n            parameter\n        ```\n\n    # No:\n    str = \"\"\"\n    hello\n    world!\n    \"\"\"\n    cmd = ```\n          program\n              --flag value\n              parameter\n          ```\n    ```\n\n- Assignments using triple-quotes or triple-backticks should have the opening quotes on the same line as the assignment operator.\n\n    ```julia\n    # Yes:\n    str2 = \"\"\"\n           hello\n       world!\n       \"\"\"\n\n    # No:\n    str2 =\n       \"\"\"\n           hello\n       world!\n       \"\"\"\n    ```\n\n- Group similar one line statements together.\n\n    ```julia\n    # Yes:\n    foo = 1\n    bar = 2\n    baz = 3\n\n    # No:\n    foo = 1\n\n    bar = 2\n\n    baz = 3\n    ```\n\n- Use blank-lines to separate different multi-line blocks.\n\n    ```julia\n    # Yes:\n    if foo\n        println(\"Hi\")\n    end\n\n    for i in 1:10\n        println(i)\n    end\n\n    # No:\n    if foo\n        println(\"Hi\")\n    end\n    for i in 1:10\n        println(i)\n    end\n    ```\n\n- After a function definition, and before an end statement do not include a blank line.\n\n    ```julia\n    # Yes:\n    function foo(bar::Int64, baz::Int64)\n        return bar + baz\n    end\n\n    # No:\n    function foo(bar::Int64, baz::Int64)\n\n        return bar + baz\n    end\n\n    # No:\n    function foo(bar::In64, baz::Int64)\n        return bar + baz\n\n    end\n    ```\n\n- Use line breaks between control flow statements and returns.\n\n    ```julia\n    # Yes:\n    function foo(bar; verbose=false)\n        if verbose\n            println(\"baz\")\n        end\n\n        return bar\n    end\n\n    # Ok:\n    function foo(bar; verbose=false)\n        if verbose\n            println(\"baz\")\n        end\n        return bar\n    end\n    ```\n\n### NamedTuples\n\nThe `=` character in `NamedTuple`s should be spaced as in keyword arguments.\nNo space should be put between the name and its value.\n`NamedTuple`s should not be prefixed with `;` at the start.\nThe empty `NamedTuple` should be written `NamedTuple()` not `(;)`\n\n```julia\n# Yes:\nxy = (x=1, y=2)\nx = (x=1,)  # Trailing comma required for correctness.\nx = (; kwargs...)  # Semicolon required to splat correctly.\n\n# No:\nxy = (x = 1, y = 2)\nxy = (;x=1,y=2)\nx = (; x=1)\n```\n\n### Numbers\n\nFloating-point numbers should always include a leading and/or trailing zero:\n\n```julia\n# Yes:\n0.1\n2.0\n3.0f0\n\n# No:\n.1\n2.\n3.f0\n```\n\n### Ternary Operator\n\nTernary operators (`?:`) should generally only consume a single line.\nDo not chain multiple ternary operators.\nIf chaining many conditions, consider using an `if`-`elseif`-`else` conditional, dispatch, or a dictionary.\n\n```julia\n# Yes:\nfoobar = foo == 2 ? bar : baz\n\n# No:\nfoobar = foo == 2 ?\n    bar :\n    baz\nfoobar = foo == 2 ? bar : foo == 3 ? qux : baz\n```\n\nAs an alternative, you can use a compound boolean expression:\n\n```julia\n# Yes:\nfoobar = if foo == 2\n    bar\nelse\n    baz\nend\n\nfoobar = if foo == 2\n    bar\nelseif foo == 3\n    qux\nelse\n    baz\nend\n```\n\n### For loops\nFor loops should always use `in`, never `=` or `∈`.\nThis also applies to list and generator comprehensions\n\n```julia\n# Yes\nfor i in 1:10\n    #...\nend\n\n[foo(x) for x in xs]\n\n# No:\nfor i = 1:10\n    #...\nend\n\n[foo(x) for x ∈ xs]\n```\n\n### Modules\n\nNormally a file that includes the definition of a module, should not include any other code that runs outside that module.\ni.e. the module should be declared at the top of the file with the `module` keyword and `end` at the bottom of the file.\nNo other code before, or after (except for module docstring before).\nIn this case the code with in the module block should **not** be indented.\n\nSometimes, e.g. for tests, or for namespacing an enumeration, it *is* desirable to declare a submodule midway through a file.\nIn this case the code within the submodule **should** be indented.\n\n### Type annotation\n\nAnnotations for function definitions should be as general as possible.\n\n```julia\n# Yes:\nsplicer(arr::AbstractArray, step::Integer) = arr[begin:step:end]\n\n# No:\nsplicer(arr::Array{Int}, step::Int) = arr[begin:step:end]\n```\n\nUsing as generic types as possible allows for a variety of inputs and allows your code to be more general:\n\n```julia\njulia\u003e splicer(1:10, 2)\n1:2:9\n\njulia\u003e splicer([3.0, 5, 7, 9], 2)\n2-element Array{Float64,1}:\n 3.0\n 7.0\n```\n\nAnnotations on type fields need to be given a little more thought.\nUsing specific concrete types for fields allows Julia to optimize the memory layout but can reduce flexibility.\nFor example lets take a look at the type `MySubString` which allows us to work with a\nsubsection of a string without having to copy the data:\n\n```julia\nmutable struct MySubString \u003c: AbstractString\n    string::AbstractString\n    offset::Integer\n    endof::Integer\nend\n```\n\nWe want the type to be able to hold any subtype of `AbstractString` but do we need to have `offset` and `endof` to be able to hold any subtype of `Integer`?\nReally, no, we should be ok to use `Int` here (`Int64` on 64-bit systems and `Int32` on 32-bit systems).\nNote that even though we're using `Int` a user can still do things like `MySubString(\"foobar\", 0x4, 0x6);` as provided `offset` and `endof` values will be converted to an `Int`.\n\n```julia\nmutable struct MySubString \u003c: AbstractString\n    string::AbstractString\n    offset::Int\n    endof::Int\nend\n```\n\nIf we truly care about performance there is one more thing we can do by making our type parametric.\nThe current definition of `MySubString` allows us to modify the `string` field at any time with any subtype of `AbstractString`.\nUsing a parametric type allows us to use any subtype of `AbstractString` upon construction but the field type will be set to something concrete (like `String`) and cannot be changed for the lifetime of the instance.\n\n```julia\nmutable struct MySubString{T\u003c:AbstractString} \u003c: AbstractString\n    string::T\n    offset::Integer\n    endof::Integer\nend\n```\n\nOverall, it is best to keep the types general to start with and later optimize them using parametric types.\nOptimizing too early in the code design process can impact your ability to refactor the code early on.\n\n### Package version specifications\n\nFor simplicity and consistency with the wider Julia community, avoid including the default caret specifier when specifying package version requirements.\n\n```julia\n# Yes:\nDataFrames = \"0.17\"\n\n# No:\nDataFrames = \"^0.17\"\n```\n\n### Comments\n\nComments should be used to state the intended behaviour of code.\nThis is especially important when the code is doing something clever that may not be obvious upon first inspection.\nAvoid writing comments that state exactly what the code obviously does.\n\n```julia\n# Yes:\nx = x + 1      # Compensate for border\n\n# No:\nx = x + 1      # Increment x\n```\n\nComments that contradict the code are much worse than no comments.\nAlways make a priority of keeping the comments up-to-date with code changes!\n\nComments should be complete sentences.\nIf a comment is a phrase or sentence, its first word should be capitalized, unless it is an identifier that begins with a lower case letter (never alter the case of identifiers!).\n\nIf a comment is short, the period at the end can be omitted.\nBlock comments generally consist of one or more paragraphs built out of complete sentences, and each sentence should end in a period.\n\nComments should be separated by at least two spaces from the expression and have a single space after the `#`.\n\nWhen referencing Julia in documentation note that \"Julia\" refers to the programming language while \"julia\" (typically in backticks, e.g. `julia`) refers to the executable.\n\nOnly use inline comments if they fit within the line length limit. If your comment cannot be fitted inline then place the comment above the content to which it refers:\n\n```julia\n# Yes:\n\n# Number of nodes to predict. Again, an issue with the workflow order. Should be updated\n# after data is fetched.\np = 1\n\n# No:\n\np = 1  # Number of nodes to predict. Again, an issue with the workflow order. Should be\n# updated after data is fetched.\n```\n\n### Documentation\n\nIt is recommended that most modules, types and functions should have [docstrings](http://docs.julialang.org/en/v1/manual/documentation/).\nThat being said, only exported functions are required to be documented.\nAvoid documenting methods like `==` as the built in docstring for the function already covers the details well.\nTry to document a function and not individual methods where possible as typically all methods will have similar docstrings.\nIf you are adding a method to a function which already has a docstring only add a docstring if the behaviour of your function deviates from the existing docstring.\n\nDocstrings are written in [Markdown](https://en.wikipedia.org/wiki/Markdown) and should be concise.\nDocstring lines should be wrapped at 92 characters.\n\n```julia\n\"\"\"\n    bar(x[, y])\n\nCompute the Bar index between `x` and `y`. If `y` is missing, compute the Bar index between\nall pairs of columns of `x`.\n\"\"\"\nfunction bar(x, y) ...\n```\n\nWhen types or methods have lots of parameters it may not be feasible to write a concise docstring.\nIn these cases it is recommended you use the templates below.\nNote if a section doesn't apply or is overly verbose (for example \"Throws\" if your function doesn't throw an exception) it can be excluded.\nIt is recommended that you have a blank line between the headings and the content when the content is of sufficient length.\nTry to be consistent within a docstring whether you use this additional whitespace.\nNote that the additional space is only for reading raw markdown and does not affect the rendered version.\n\nType Template (should be skipped if is redundant with the constructor(s) docstring):\n\n```julia\n\"\"\"\n    MyArray{T,N}\n\nMy super awesome array wrapper!\n\n# Fields\n- `data::AbstractArray{T,N}`: stores the array being wrapped\n- `metadata::Dict`: stores metadata about the array\n\"\"\"\nstruct MyArray{T,N} \u003c: AbstractArray{T,N}\n    data::AbstractArray{T,N}\n    metadata::Dict\nend\n```\n\nFunction Template (only required for exported functions):\n\n```julia\n\"\"\"\n    mysearch(array::MyArray{T}, val::T; verbose=true) where {T} -\u003e Int\n\nSearches the `array` for the `val`. For some reason we don't want to use Julia's\nbuiltin search :)\n\n# Arguments\n- `array::MyArray{T}`: the array to search\n- `val::T`: the value to search for\n\n# Keywords\n- `verbose::Bool=true`: print out progress details\n\n# Returns\n- `Int`: the index where `val` is located in the `array`\n\n# Throws\n- `NotFoundError`: I guess we could throw an error if `val` isn't found.\n\"\"\"\nfunction mysearch(array::AbstractArray{T}, val::T) where T\n    ...\nend\n```\n\nIf your method contains lots of arguments or keywords you may want to exclude them from the method signature on the first line and instead use `args...` and/or `kwargs...`.\n\n```julia\n\"\"\"\n    Manager(args...; kwargs...) -\u003e Manager\n\nA cluster manager which spawns workers.\n\n# Arguments\n\n- `min_workers::Integer`: The minimum number of workers to spawn or an exception is thrown\n- `max_workers::Integer`: The requested number of workers to spawn\n\n# Keywords\n\n- `definition::AbstractString`: Name of the job definition to use. Defaults to the\n    definition used within the current instance.\n- `name::AbstractString`: ...\n- `queue::AbstractString`: ...\n\"\"\"\nfunction Manager(...)\n    ...\nend\n```\n\nFeel free to document multiple methods for a function within the same docstring.\nBe careful to only do this for functions you have defined.\n\n```julia\n\"\"\"\n    Manager(max_workers; kwargs...)\n    Manager(min_workers:max_workers; kwargs...)\n    Manager(min_workers, max_workers; kwargs...)\n\nA cluster manager which spawns workers.\n\n# Arguments\n\n- `min_workers::Int`: The minimum number of workers to spawn or an exception is thrown\n- `max_workers::Int`: The requested number of workers to spawn\n\n# Keywords\n\n- `definition::AbstractString`: Name of the job definition to use. Defaults to the\n    definition used within the current instance.\n- `name::AbstractString`: ...\n- `queue::AbstractString`: ...\n\"\"\"\nfunction Manager end\n\n```\n\nIf the documentation for bullet-point exceeds 92 characters the line should be wrapped and slightly indented.\nAvoid aligning the text to the `:`.\n\n```julia\n\"\"\"\n...\n\n# Keywords\n- `definition::AbstractString`: Name of the job definition to use. Defaults to the\n    definition used within the current instance.\n\"\"\"\n```\n\nFor additional details on documenting in Julia see the [official documentation](https://docs.julialang.org/en/v1/manual/documentation/).\n\nFor documentation written in Markdown files such as `README.md` or `docs/src/index.md` use exactly one sentence per line.\n\n## Test Formatting\n\n### Testsets\n\nJulia provides [test sets](https://docs.julialang.org/en/v1/stdlib/Test/#Working-with-Test-Sets-1) which allows developers to group tests into logical groupings.\nTest sets can be nested and ideally packages should only have a single \"root\" test set.\nIt is recommended that the \"runtests.jl\" file contains the root test set which contains the remainder of the tests:\n\n```julia\n@testset \"PkgExtreme\" begin\n    include(\"arithmetic.jl\")\n    include(\"utils.jl\")\nend\n```\n\n### Comparisons\n\nMost tests are written in the form `@test x == y`.\nSince the `==` function doesn't take types into account tests like the following are valid: `@test 1.0 == 1`.\nAvoid adding visual noise into test comparisons:\n\n```julia\n# Yes:\n@test value == 0\n\n# No:\n@test value == 0.0\n```\n\n## Performance and Optimization\n\nSeveral of these tips are contained within Julia's [Performance Tips](https://docs.julialang.org/en/v1/manual/performance-tips/).\n\nMuch of Julia's performance gains come from being able to specialize functions on their input types.\nPutting variables and functionality in the global namespace or module's namespace thwarts this.\nOne consequence of this is that conventional MATLAB-style scripts will result in surprisingly slow code.\nThere are two ways to mitigate this:\n\n- Move as much functionality into functions as possible.\n- Declare global variables as constants using `const`.\n\nRemember that the first time you call a function with a certain type signature it will compile that function for the given input types.\nCompilation is sometimes a significant portion of time, so avoid profiling/timing functions on their first run. Note that the `@benchmark` and `@btime` macros from the [BenchmarkTools](https://github.com/JuliaCI/BenchmarkTools.jl) package can be useful as they run the function many times and report summary statistics of time and memory allocation, alleviating the need to run the function first before benchmarking.\n\n## Editor Configuration\n\n### Sublime Text Settings\n\nIf you are a user of Sublime Text we recommend that you have the following options in your Julia syntax specific settings.\nTo modify these settings first open any Julia file (`*.jl`) in Sublime Text.\nThen navigate to: `Preferences \u003e Settings - More \u003e Syntax Specific - User`\n\n```json\n{\n    \"translate_tabs_to_spaces\": true,\n    \"tab_size\": 4,\n    \"trim_trailing_white_space_on_save\": true,\n    \"ensure_newline_at_eof_on_save\": true,\n    \"rulers\": [92]\n}\n```\n\n### Vim Settings\n\nIf you are a user of Vim we recommend that you add to your `.vim/vimrc` file:\n\n```\n\" ~/.vim/vimrc\nset tabstop=4       \" Set tabstops to a width of four columns.\nset softtabstop=4   \" Determine the behaviour of TAB and BACKSPACE keys with expandtab.\nset shiftwidth=4    \" Determine the results of \u003e\u003e, \u003c\u003c, and ==.\n\n\" Identify .jl files as Julia. If using julia-vim plugin, this is redundant.\nautocmd BufRead,BufNewFile *.jl set filetype=julia\n```\n\nThen create or edit `.vim/after/ftplugin/julia.vim`, adding the Julia-specific configuration:\n\n```\n\" ~/.vim/after/ftplugin/julia.vim\nsetlocal expandtab       \" Replace tabs with spaces.\nsetlocal textwidth=92    \" Limit lines according to Julia's CONTRIBUTING guidelines.\nsetlocal colorcolumn=+1  \" Highlight first column beyond the line limit.\n```\n\nAdditionally, you may find is useful to use the\n[julia-vim plugin](https://github.com/JuliaEditorSupport/julia-vim)\nwhich adds Julia-aware syntax highlighting and a few cool other features.\n\n### Atom Settings\n\nAtom defaults preferred line length to 80 characters. We want that at 92 for julia.\nTo change it:\n\n1. Go to `Atom -\u003e Preferences -\u003e Packages`.\n2. Search for the \"language-julia\" package and open the settings for it.\n3. Find preferred line length (under \"Julia Grammar\") and change it to 92.\n\n\n### VS-Code Settings\n\nIf you are a user of VS Code we recommend that you have the following options in your Julia syntax specific settings.\nTo modify these settings open your VS Code Settings with \u003ckbd\u003eCMD\u003c/kbd\u003e+\u003ckbd\u003e,\u003c/kbd\u003e (Mac OS) or \u003ckbd\u003eCTRL\u003c/kbd\u003e+\u003ckbd\u003e,\u003c/kbd\u003e (other OS), and add to your `settings.json`:\n\n```json\n{\n    \"[julia]\": {\n        \"editor.detectIndentation\": false,\n        \"editor.insertSpaces\": true,\n        \"editor.tabSize\": 4,\n        \"files.insertFinalNewline\": true,\n        \"files.trimFinalNewlines\": true,\n        \"files.trimTrailingWhitespace\": true,\n        \"editor.rulers\": [92],\n    },\n}\n```\nAdditionally you may find the [Julia VS-Code plugin](https://github.com/julia-vscode/julia-vscode) useful.\n\n## Code Style Badge\n\nLet contributors know your project is following the Blue style guide by adding the badge to your `README.md`.\n```md\n[![Code Style: Blue](https://img.shields.io/badge/code%20style-blue-4495d1.svg)](https://github.com/JuliaDiff/BlueStyle)\n```\nThe badge is blue:\n[![Code Style: Blue](https://img.shields.io/badge/code%20style-blue-4495d1.svg)](https://github.com/JuliaDiff/BlueStyle)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJuliaDiff%2FBlueStyle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FJuliaDiff%2FBlueStyle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJuliaDiff%2FBlueStyle/lists"}