Julia – 113 – guida allo stile – 1

Continuo da qui, copio qui.

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.

Scrivi funzioni non solo scripts
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’s compiler works.

It is also worth emphasizing that functions should take arguments, instead of operating directly on global variables (aside from constants like pi).

Evitare tipi troppo specifici
Code should be as generic as possible. Instead of writing:

convert(Complex{Float64}, x)

it’s better to use available generic functions:

complex(float(x))

The second version will convert x to an appropriate type, instead of always the same type.

This style point is especially relevant to function arguments. For example, don’t declare an argument to be of type Int or Int32 if it really could be any integer, expressed with the abstract type Integer. In fact, in many cases you can omit the argument type altogether, unless it is needed to disambiguate from other method definitions, since a MethodError will be thrown anyway if a type is passed that does not support any of the requisite operations. (This is known as duck typing.)

For example, consider the following definitions of a function addone that returns one plus its argument:

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

The last definition of addone handles any type supporting oneunit (which returns 1 in the same type as x, which avoids unwanted type promotion) and the + function with those arguments. The key thing to realize is that there is no performance penalty to defining only the general addone(x) = x + oneunit(x), because Julia will automatically compile specialized versions as needed. For example, the first time you call addone(12), Julia will automatically compile a specialized addone function for x::Int arguments, with the call to oneunit replaced by its inlined value 1. Therefore, the first three definitions of addone above are completely redundant with the fourth definition.

Gestire la diversità degli argomenti nella chiamata
Instead of:

function foo(x, y)
    x = Int(x); y = Int(y)
    ...
end
foo(x, y)

use:

function foo(x::Int, y::Int)
    ...
end
foo(Int(x), Int(y))

This is better style because foo does not really accept numbers of all types; it really needs Ints.

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 “space” for future method definitions.

Aggiungere ! alle funzioni che modificano i loro argomenti
Instead of:

function double(a::AbstractArray{<:Number})
    for i = 1:endof(a)
        a[i] *= 2
    end
    return a
end

use:

function double!(a::AbstractArray{<:Number})
    for i = 1:endof(a)
        a[i] *= 2
    end
    return a
end

The Julia standard library uses this convention throughout and contains examples of functions with both copying and modifying forms (e.g., sort() and sort!()), and others which are just modifying (e.g., push!(), pop!(), splice!()). It is typical for such functions to also return the modified array for convenience.

Evitare tipi di unioni strane
Types such as Union{Function,AbstractString} are often a sign that some design could be cleaner.

Evitare tipi di unioni nei campi
When creating a type such as:

mutable struct MyType
    ...
    x::Union{Void,T}
end

ask whether the option for x to be nothing (of type Void) is really necessary. Here are some alternatives to consider:

  • Find a safe default value to initialize x with
  • Introduce another type that lacks x
  • If there are many fields like x, store them in a dictionary
  • Determine whether there is a simple rule for when x is nothing. For example, often the field will start as nothing but get initialized at some well-defined point. In that case, consider leaving it undefined at first.
  • If x really needs to hold no value at some times, define it as ::Nullable{T} instead, as this guarantees type-stability in the code accessing this field.

Evitare tipi di containers elaborati
It is usually not much help to construct arrays like the following:

a = Array{Union{Int,AbstractString,Tuple,Array}}(n)

In this case Array{Any}(n) is better. It is also more helpful to the compiler to annotate specific uses (e.g. a[i]::Int) than to try to pack many alternatives into one type.

Usare nomi consistenti con base/ di Julia

  • modules and type names use capitalization and camel case: module SparseArrays, struct UnitRange.
  • functions are lowercase (maximum(), convert()) and, when readable, with multiple words squashed together (isequal(), haskey()). When necessary, use underscores as word separators. Underscores are also used to indicate a combination of concepts (remotecall_fetch() as a more efficient implementation of fetch(remotecall(...))) or as modifiers (sum_kbn()).
  • conciseness is valued, but avoid abbreviation (indexin() rather than indxin()) as it becomes difficult to remember whether and how particular words are abbreviated.

If a function name requires multiple words, consider whether it might represent more than one concept and might be better split into pieces.

Uh! ancora tante raccomandazioni, pausa 😊

🤢

Posta un commento o usa questo indirizzo per il trackback.

Trackback

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo di WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione /  Modifica )

Google photo

Stai commentando usando il tuo account Google. Chiudi sessione /  Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione /  Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione /  Modifica )

Connessione a %s...

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.

%d blogger hanno fatto clic su Mi Piace per questo: