web-dev-qa-db-fra.com

Existe-t-il un moyen dans Swift pour déclarer une fonction en ligne?

Je suis très nouveau dans la langue Swift

Je voulais déclarer une fonction en ligne comme en c ++ donc ma déclaration amusante est comme

func MyFunction(param: Int) -> Int {
...
...
...
}

et je veux faire quelque chose comme

inline func MyFunction(param: Int) -> Int {
...
...
...
}

J'ai essayé de rechercher sur le Web mais je n'ai rien trouvé de pertinent peut-être qu'il n'y a pas de mot-clé en ligne mais peut-être qu'il y a une autre façon d'inclure la fonction

Merci beaucoup :)

34
Gibnem

Swift 1.2 inclura l'attribut @inline, Avec never et __always Comme paramètres. Pour plus d'informations, voir ici .

Comme indiqué précédemment, vous devez rarement déclarer une fonction explicitement en tant que @inline(__always) car Swift est assez intelligent pour savoir quand incorporer une fonction. Cependant, ne pas avoir de fonction en ligne, peut être nécessaire dans certains codes.

45
MaddTheSane

Tout crédit à la réponse , résumant simplement les informations de la lien .

Pour rendre une fonction en ligne, ajoutez simplement @inline(__always) avant la fonction:

@inline(__always) func myFunction() {

}

Cependant, cela vaut la peine d'envisager et d'en apprendre davantage sur les différentes possibilités. Il existe trois façons possibles de s'aligner:

  • parfois - s'assurera parfois d'inline la fonction. C'est le comportement par défaut, vous n'avez rien à faire! Swift peut automatiquement intégrer les fonctions en tant qu'optimisation.
  • toujours - s'assurera de toujours aligner la fonction. Obtenez ce comportement en ajoutant @inline(__always) avant la fonction. Utilisez "si votre fonction est plutôt petite et que vous préférez que votre application s'exécute plus rapidement".
  • jamais - s'assurera de ne jamais intégrer la fonction. Ceci peut être réalisé en ajoutant @inline(never) avant la fonction. Utilisez "si votre fonction est assez longue et que vous souhaitez éviter d'augmenter la taille de votre segment de code".
14
kgaidis

Je suis tombé sur un problème que j'avais besoin d'utiliser les attributs @inlinable Et @usableFromInline Qui ont été introduits dans Swift 4.2, donc je voudrais partager mon expérience avec vous.

Permettez-moi de passer directement au problème, notre base de code a un module Analytics Facade qui relie d'autres modules.

Cible d'application -> module Analytics Facade -> module de création de rapports X.

Le module Analytics Facade possède une fonction appelée report(_ rawReport: EventSerializable) qui déclenche les appels de rapport. Cette fonction utilise une instance du module de rapport X pour envoyer les appels de rapport pour ce module de rapport spécifique X.

Le fait est que le fait d'appeler cette fonction report(_ rawReport: EventSerializable) plusieurs fois pour envoyer les appels de rapport une fois que les utilisateurs lancent l'application crée des frais généraux inévitables qui nous ont causé beaucoup de plantages.

De plus, il n'est pas facile de reproduire ces plantages si vous définissez Optimisation level Sur None en mode débogage. Dans mon cas, je n'ai pu le reproduire que lorsque j'ai défini le Optimisation level Sur Fastest, Smalles T ou même plus.

La solution consistait à utiliser @inlinable Et @usableFromInline.

L'utilisation de @inlinable Et @usableFromInline Exporte le corps d'une fonction dans le cadre de l'interface d'un module, le rendant disponible pour l'optimiseur lorsqu'il est référencé à partir d'autres modules.

L'attribut @usableFromInline Marque une déclaration interne comme faisant partie de l'interface binaire d'un module, lui permettant d'être utilisée à partir du code @inlinable Sans l'exposer comme faisant partie de l'interface source du module.

À travers les limites des modules, les génériques d'exécution introduisent une surcharge inévitable, car les métadonnées de type réifié doivent être transmises entre les fonctions, et divers modèles d'accès indirect doivent être utilisés pour manipuler les valeurs de type générique. Pour la plupart des applications, cette surcharge est négligeable par rapport au travail réel effectué par le code lui-même.

Un binaire client construit par rapport à ce cadre peut appeler ces fonctions génériques et bénéficier d'une amélioration possible des performances lorsqu'il est construit avec des optimisations activées, en raison de l'élimination de la surcharge d'abstraction.

Exemple de code:

@inlinable public func allEqual<T>(_ seq: T) -> Bool
    where T : Sequence, T.Element : Equatable {
        var iter = seq.makeIterator()
        guard let first = iter.next() else { return true }

        func rec(_ iter: inout T.Iterator) -> Bool {
            guard let next = iter.next() else { return true }
            return next == first && rec(&iter)
        }

        return rec(&iter)
}

Plus d'informations - Inline et spécialisation inter-modules

1
Shady Ghalab