`def` vs `val` vs `paresseux val d'évaluation en Scala
Suis-je en droit de comprendre que
def
est évalué à chaque fois qu'il devient accessiblelazy val
est évaluée une fois qu'il est accessibleval
est évaluée une fois qu'il pénètre dans l'étendue d'exécution?
Voir stackoverflow.com/questions/4437373/...
Aussi stackoverflow.com/questions/13126104/...
Notez que
Aussi stackoverflow.com/questions/13126104/...
Notez que
val
n'a pas pu être librement étendu. Si vous avez val a = 5
, val b = a + 1
dans la base de trait et d'essayer de l'étendre à d' val a = 6
alors au lieu de 7 b
serait de jeter quelques notdefined erreur.OriginalL'auteur Ivan | 2012-02-26
Vous devez vous connecter pour publier un commentaire.
Oui, mais pour la 3ème, je dirais "que l'exécution de l'instruction", parce que, par exemple:
Cela donne
"b is null"
.b
n'est jamais évalué et son erreur est de ne jamais levée. Mais c'est dans la portée dès que le contrôle entre dans le bloc.OriginalL'auteur Owen
Oui, mais il y a une jolie astuce: si vous avez paresseux valeur, et lors de la première évaluation, il obtiendra une exception, la prochaine fois que vous essayez d'accéder à il va essayer de ré-évaluer lui-même.
Ici est un exemple:
Par la voie, ne serait-ce pas une bonne idée de définir toutes les vals paresseux, sauf si le contraire est-elle nécessaire?
Je soupçonne que cela permettrait de diminuer les performances de cause paresseux vals sont traduit dans le code avec une double vérification afin de fournir la sécurité des threads. Il pourrait y avoir d'autres raisons.
Ok. Merci. C'est une idée à propos de
lazy val
vsval
. Une autre question est delazy val
vsdef
. J'ai une immuable classe avec quelques propriétés des fonctions pures des données transmises dans le constructeur. Ne serait-il pas une bonne idée de les exposer comme des paresseux vals au lieu de defs (en considérant le résultat est un petit morceau de données (comme une valeur entière), mais prend un certain temps à calculer)?Juste il ya quelques jours, j'ai été introduit à l'affaire, lors de l'utilisation de paresseux vals introduit un blocage dans le code. Méfiez-vous de l'utilisation de paresseux vals-les-bains dans le code multithread. Comme pour vos dernières questions, je suppose que oui, il sera non seulement plus performant solution, dans certaines circonstances, mais plus lisible de l'OMI (depuis que l'homme qui va lire ce code sera awared que c'est init une fois bout de code).
OriginalL'auteur om-nom-nom
Je tiens à expliquer les différences à travers l'exemple que j'ai exécuté dans REPL.Je crois que cet exemple simple est plus facile à saisir et explique les différences conceptuelles.
Ici,je suis entrain de créer un val result1, un paresseux val result2 et un def result3 dont chacun a un type Chaîne de caractères.
Un). val
Ici, println est exécuté parce que la valeur de result1 a été calculé ici. Alors, maintenant, result1 va toujours se référer à sa valeur je.e "renvoie val".
Donc, maintenant, vous pouvez voir que result1 fait maintenant référence à sa valeur. Notez que, la println instruction n'est pas exécutée ici, car la valeur de result1 a déjà été calculée quand il a été exécuté pour la première fois. Donc, désormais, result1 retourne toujours la même valeur et println déclaration ne sera jamais exécutée à nouveau, car le calcul pour obtenir la valeur de result1 a déjà été effectué.
B). paresseux val
Comme nous pouvons le voir ici, la println instruction n'est pas exécutée ici et ni la valeur a été calculée. C'est la nature de paresse.
Maintenant, quand je me réfère à la result2 pour la première fois, println instruction sera exécutée et la valeur sera calculée et attribuée.
Maintenant, quand je me réfère à result2 de nouveau, cette fois-ci, nous allons seulement voir la valeur qu'il détient et de la println déclaration ne sera pas exécutée. À partir de maintenant, result2 va se comporter comme un val et renvoie sa valeur en cache tout le temps.
C). def
En cas de def, le résultat devra être calculée à chaque fois result3 est appelé. C'est aussi la principale raison pour laquelle nous de définir des méthodes comme def en scala, car les méthodes de calcul et de retourner une valeur à chaque fois qu'il est appelé à l'intérieur du programme.
c'est la meilleure explication ici. devrait avoir plus de place de vote.
OriginalL'auteur oblivion
Une bonne raison pour choisir
def
surval
, en particulier dans les classes abstraites (ou des caractères qui sont utilisés pour imiter Java les interfaces), est, que vous pouvez remplacer undef
avec unval
dans les sous-classes, mais pas l'inverse.Concernant
lazy
, il y a deux choses que je peux voir que l'on devrait avoir à l'esprit. La première est quelazy
introduit une certaine gestion d'exécution, mais je suppose que vous devez évaluer votre situation spécifique afin de déterminer si cette réalité a un impact significatif sur les performances d'exécution. L'autre problème aveclazy
est qu'il peut-être des retards de lever une exception, ce qui pourrait rendre plus difficile de raisonner à propos de votre programme, car l'exception est levée pas direct, mais seulement lors de la première utilisation.Alors que je conceptuellement d'accord avec votre commentaire, je ne pense pas que votre
firthElement
est un bon exemple pour l'illustrer. Si vous pensez en termes de pré- & les post-conditions, l'appelseq(5)
est évidemment qu'sûr, si la séquence contient au moins six éléments - qui n'est pas garanti, même siisEmpty
est faux. Pire encore, c'est une obligation que l'appelant defithElement
ne peut pas remplir si elles n'êtes pas celui qui a créé l'objet, en premier lieu, car ils ne sont pas au courant de la longueur de la séquence. L'ajout d'unlength
fonction de votre exemple valable.oui, c'est un exemple artificiel plein de bugs. Il a l'intention de mettre en avant les différences entre val, paresseux val, et def. Mon monde réel scénario est d'une intersection objet dans une grille hexagonale. L'intersection peut être de deux sortes: l'une en haut, en bas à gauche et en bas à droite tuiles adjacentes (c'est à dire un 'Y' intersection) ou par le bas, haut-gauche et droit-dessus les tuiles adjacentes (c'est à dire une tête en bas " Y " intersection). Une exception doit être levée lorsque vous essayez d'accéder à une case adjacente qui ne peut pas exister. En tant que tel, val ne peut pas être utilisé.
J'ai remplacé le isEmpty avec hasFifthElement.
OriginalL'auteur Malte Schwerhoff
Vous sont corrects. Pour preuve de la spécification:
De "3.3.1 Types de Méthode" (pour
def
):De "4.1 les Déclarations de Valeur et de Définitions":
OriginalL'auteur Travis Brown
def
définit une méthode. Lorsque vous appelez la méthode, la méthode bien sûr s'exécute.val
définit une valeur (un immuable variable). L'expression d'affectation est évaluée lorsque la valeur est initialisée.lazy val
définit une valeur de retard de l'initialisation. Il sera initialisé lors de sa première utilisation, de sorte que l'expression d'affectation sera ensuite évalué.OriginalL'auteur Jesper
Un nom qualifié par la def est évalué par le remplacement du nom et de son membre de droite de l'expression à chaque fois le nom apparaît dans le programme. Par conséquent, ce remplacement sera exécutée à chaque où le nom apparaît dans votre programme.
Un nom qualifié par val est évalué immédiatement lorsque le contrôle atteint son membre de droite de l'expression. Par conséquent, chaque fois que le nom apparaît dans l'expression, il sera considéré comme de la valeur de cette évaluation.
Un nom qualifié par paresse val suit la même politique que celle de val de qualification avec une exception, de son RHS sera évaluée uniquement lorsque le contrôle de la frappe le point où le nom est utilisé pour la première fois
OriginalL'auteur kmos.w
Un écueil potentiel en ce qui concerne l'utilisation de val lorsque l'on travaille avec des valeurs qui n'ont pas connu jusqu'à l'exécution.
Prenez, par exemple,
request: HttpServletRequest
Si vous disiez:
Vous obtenez une exception de pointeur null comme au moment de l'initialisation de la val, la demande n'a pas de foo (ne serait savoir au moment de l'exécution).
Ainsi, en fonction de la charge de l'accès ou de calcul, def ou paresseux val sont alors des choix appropriés pour l'exécution valeurs déterminées; que, ou un val qui est elle-même une fonction anonyme qui récupère les données d'exécution (même si ce dernier semble un peu plus de cas de bord)
OriginalL'auteur virtualeyes