82 votes

Quelle est la motivation de l’attribution de Scala à l’unité plutôt qu’à la valeur attribuée?

Quelle est la motivation de l’attribution de Scala à l’unité plutôt qu’à la valeur attribuée?

Un schéma courant dans la programmation d'E / S consiste à effectuer les opérations suivantes:

 while ((bytesRead = in.read(buffer)) != -1) { ...
 

Mais ce n'est pas possible à Scala parce que ...

 bytesRead = in.read(buffer)
 

.. renvoie Unit, pas la nouvelle valeur de bytesRead.

Cela semble être une chose intéressante à laisser en dehors d'un langage fonctionnel. Je me demande pourquoi cela a été fait?

83voto

David Pollak Points 5756

J'ai préconisé que les affectations renvoient la valeur attribuée plutôt que l'unité. Martin et moi sommes allés de l'avant, mais son argument était que mettre une valeur sur la pile pour la faire disparaître 95% du temps était un gaspillage de codes octets et avait un impact négatif sur les performances.

20voto

Daniel C. Sobral Points 159554

Je ne suis pas au courant de l'intérieur de l'information sur les raisons, mais mon soupçon est très simple. Scala sur le côté-effectful boucles difficile à utiliser, de sorte que les programmeurs vont préférer pour des compréhensions.

Il le fait dans beaucoup de façons. Par exemple, vous n'avez pas de for boucle où vous déclarez et muter en une variable. Vous ne pouvez pas (facilement) muter état sur un while boucle dans le même temps, de tester la condition, ce qui signifie que vous avez souvent à répéter la mutation juste avant, et à la fin de celui-ci. Les Variables déclarées à l'intérieur d'un while bloc ne sont pas visibles de l' while condition de test, ce qui rend do { ... } while (...) beaucoup moins utile. Et ainsi de suite.

Solution de contournement:

while ({bytesRead = in.read(buffer); bytesRead != -1}) { ... 

Pour ce qu'il vaut.

Comme une autre explication, peut-être Martin Odersky avait à faire face à quelques très laid bugs découlant d'une telle utilisation, et a décidé d'interdire à partir de sa langue.

MODIFIER

David Pollack a répondu avec certains faits réels, qui sont clairement approuvé par le fait que Martin Odersky lui-même commenté sa réponse, de donner du crédit à des aspects liés à la performance de l'argument mis de l'avant par Pollack.

11voto

Daniel Spiewak Points 30706

Ce qui s'est passé dans le cadre de la Scala de plus "formellement correct" type de système. Formellement parlant, l'affectation est purement côte-d'effectuer la déclaration et, par conséquent, devrait revenir en Unit. Cela ne veut avoir de bons conséquences; par exemple:

class MyBean {
  private var internalState: String = _

  def state = internalState

  def state_=(state: String) = internalState = state
}

L' state_= méthode renvoie Unit (comme il est attendu d'un setter), précisément parce que l'affectation des retours Unit.

Je suis d'accord que pour le C-modes comme la copie d'un ruisseau ou similaire, cette décision de conception peut être un peu ennuyeux. Cependant, c'est en fait relativement peu de problèmes en général et contribue vraiment à la cohérence globale du système de type.

7voto

C. A. McCann Points 56834

Peut-être cela est dû à la commande de requête de séparation de principe?

CQS a tendance à être populaire à l'intersection de l'OO et fonctionnelle styles de programmation, car elle crée une distinction évidente entre les méthodes de l'objet qui ne sont ou n'ont pas d'effets secondaires (c'est à dire, qui modifient l'objet). L'application de CQS à des assignations de variables est aller plus loin que d'habitude, mais la même idée s'applique.

Une brève illustration de pourquoi CQS est utile: Envisager une hypothétique hybride F/OO de la langue avec un List de la classe qui possède des méthodes Sort, Append, First, et Length. En impératif OO style, on peut avoir envie d'écrire une fonction comme ceci:

func foo(x):
    var list = new List(4, -2, 3, 1)
    list.Append(x)
    list.Sort()
    # list now holds a sorted, five-element list
    var smallest = list.First()
    return smallest + list.Length()

Alors que dans la plus fonctionnelle de style, on serait plus à même d'écrire quelque chose comme ceci:

func bar(x):
    var list = new List(4, -2, 3, 1)
    var smallest = list.Append(x).Sort().First()
    # list still holds an unsorted, four-element list
    return smallest + list.Length()

Ceux-ci semblent être d'essayer de faire la même chose, mais à l'évidence l'un des deux est incorrect, et sans en savoir plus sur le comportement des méthodes, on ne peut pas dire lequel.

À l'aide de CQS, cependant, nous voudrions insister que si Append et Sort modifier la liste, il doit retourner le type d'unité, ce qui nous empêche de créer des bugs en utilisant la deuxième forme lorsque nous ne devrions pas. La présence d'effets secondaires, par conséquent, devient également implicite dans la signature de la méthode.

4voto

Jens Schauder Points 23468

J'imagine que c'est dans le but de garder le programme / la langue sans effets secondaires.

Ce que vous décrivez est l’utilisation intentionnelle d’un effet secondaire qui, dans le cas général, est considéré comme une mauvaise chose.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X