Silex v0.47.1 / Docs Source canonique ↗

Copier ou transférer une valeur

Une affectation ordinaire copie compositionnellement les structures, enums, optionnels, tableaux et listes. Les références de classes qu'ils contiennent restent partagées.

struct Position {
    var x:int
    var y:int
}

func main() {
    var first = Position(x:1, y:2)
    var second = first
    second.x = 10

    print(first.x)
    print(second.x)
}

Après la copie suivante, les deux structures atteignent encore la même instance State :

var foo1 = Foo(value:10, instance:State(value:5))
var foo2 = foo1

foo2.instance.value = 8
print(foo1.instance.value) // 8

Détacher tout le graphe atteignable

var foo3 = copy foo1

foo3.instance.value = 12
print(foo1.instance.value) // 8

copy recrée récursivement les instances de classes atteintes. Des références répétées restent répétées dans le clone et les cycles restent des cycles. Aucun constructeur n'est rappelé.

Une classe déclarée nocopy représente une identité native ou externe qui ne possède pas de duplication sûre : device, buffer, fichier système ou ressource comparable. L'affectation ordinaire continue d'en partager l'identité, directement ou à travers une structure. En revanche, copy est refusé statiquement dès que la valeur atteint une telle classe : il ne duplique jamais silencieusement un handle et son nettoyage.

nocopy class DeviceHandle {}
struct Owner { var handle:DeviceHandle }

var handle = DeviceHandle()
let owner = Owner(handle:handle)
let shared = owner       // partage la même identité
// let detached = copy owner // erreur : classe non clonable atteinte

Le compilateur capture un instant logique cohérent du graphe. Une mutation Silex concurrente est ordonnée avant ou après cet instant ; la copie détachée ne peut pas mélanger deux états de la source.

Lire le champ d’une valeur temporaire

Dans make_label().text, le champ lu reste valide après la libération de la valeur temporaire renvoyée par make_label. Les autres champs possédés de cette valeur sont libérés. Une référence de classe extraite conserve son identité partagée ; elle n’est pas clonée. Cette règle s’applique aussi aux tuples nommés et à la branche présente d’un accès optionnel.

Construire un tuple à partir de valeurs existantes ou le décomposer en variables préserve les mêmes règles de copie et de transfert que les autres valeurs.

Transférer la possession

var original = Position(x:1, y:2)
let transferred = move original

original = Position()

move consomme une variable locale complète ou un paramètre ordinaire. La source ne peut plus être lue avant qu'un var consommé reçoive une valeur complète de remplacement. Un let consommé ne peut pas être réinitialisé.

La source consommée n'exécute plus drop ; la valeur transférée possède le nettoyage restant. Les champs, éléments indexés, self et expressions temporaires ne sont pas des sources acceptées pour un move explicite.

Lire une collection temporaire

make_values()[0] conserve l’élément sélectionné avant de libérer le tableau ou la liste temporaire. Un élément qui référence une classe garde son identité partagée ; les autres éléments temporaires sont libérés. Les lectures make_values().count(), make_values().is_empty() et make_label().count() libèrent leur récepteur temporaire après avoir produit le résultat scalaire. Ces opérations ne libèrent pas une collection ou une chaîne conservée dans une variable : sa durée de vie reste celle de son propriétaire.

Appels de callback

Un appel de callback suit les mêmes règles de possession qu’un appel direct. Pour un paramètre passé par valeur, un argument temporaire est transféré et un argument stocké garde son propriétaire. Un résultat possédé est transféré à son utilisation suivante.

Revenir à la possession · Emprunter sans transférer