Pourquoi println est-il considéré comme une fonction impure?

10

Je lis la programmation du livre en scala, et il est dit:

... dans ce cas, son effet secondaire est l'impression sur le flux de sortie standard.

et je ne vois pas où est l'effet secondaire, car, pour la même entrée, println imprimera la même sortie (je pense)
UPDATE
par exemple chaque fois que nous appelons:

println(5)

il affichera 5 , je ne vois pas de cas où appeler println(5)affichera une valeur autre que 5 !!

un nom
la source
si cela répond à votre question, je supprimerai ma réponse softwareengineering.stackexchange.com/q/40297/271736
joelb
3
Réponses à Qu'est-ce que la transparence référentielle? semblent pertinents ici.
Nathan Hughes
1
connexes (lol) stackoverflow.com/q/4865616/5986907
joelb
2
Vous confondez effet secondaire (non référentiel transparent) avec déterministe. printlnest une fonction déterministe mais pour être pure elle doit aussi être RT.
bob
2
Parce qu'il fait autre chose que calculer un résultat et le renvoyer.
Seth Tisue

Réponses:

6

Vous pouvez savoir si une expression a un effet secondaire en remplaçant l'expression par son résultat. Si le programme change de sens , il y a un effet secondaire. Par exemple,

println(5)

est un programme différent de

()

Autrement dit, un effet secondaire est tout effet observable qui n'est pas codé dans le résultat de l'évaluation d'une expression. Voici le résultat (), mais il n'y a rien dans cette valeur qui code le fait que 5 est maintenant apparu quelque part sur votre écran.

joelb
la source
6
En fait, ce n'est pas une bonne définition d'un «effet secondaire» - Un effet secondaire peut être défini comme tout ce qui rompt la transparence référentielle. Ce que vous avez essayé de montrer ici était RT mais votre exemple est faux. Puisque l'exécution de quelque chose plusieurs fois devrait faire la même chose plusieurs fois - Plutôt, val a = println("hello"); val b = (a, a)devrait être la même chose que val b = (pritnln("hello"), println("hello")).
Luis Miguel Mejía Suárez
1
@ LuisMiguelMejíaSuárez peut-être que mon exemple n'est pas clair, mais je ne pense pas que ce soit faux. Je souligne essentiellement la différence entre le programme println(5)et (). Ou vouliez-vous dire la dernière phrase?
joelb
Ouais mais tu n'étais pas clair à ce sujet. Comme, comme je l'ai dit, le problème n'appelle pas quelque chose plusieurs fois, le problème est de savoir si le remplacement d'une référence par sa définition aurait cet impact.
Luis Miguel Mejía Suárez
Je ne comprends pas clairement votre exemple
aName
5
Je dirais que c'est faux car il est parfaitement possible que quelque chose ait un effet secondaire et soit idempotent, donc le répéter ne change pas l'effet. Par exemple, affectation à une variable mutable; comment pouvez-vous distinguer x = 1et x = 1; x = 1; x = 1?
Alexey Romanov
5

Considérez l'analogie suivante

var out: String = ""
def myprintln(s: String) = {
  out += s // this non-local mutation makes me impure
  ()
}

Voici myprintlnimpur car en plus de renvoyer une valeur, ()il mute également une variable non locale outcomme effet secondaire. Imaginez maintenant que outle flux de vanille printlnmute.

Mario Galic
la source
1
merci d'avoir répondu, il est clair que votre fonction est impure, cependant, pourquoi println (), tel que défini dans scala, n'est pas pur
aName
1
@aName Parce qu'en plus de renvoyer de la valeur, ()il mute également l'état non local dans System.out.
Mario Galic
Je pense que le fait crucial qui manque à cette réponse est que println ajoute un caractère de nouvelle ligne à l'entrée.
Federico S
4

L'effet secondaire est dans l'état de l'ordinateur. Chaque fois que vous appelez, println()l'état de la mémoire change afin d'afficher la valeur donnée au terminal. Ou plus généralement, l'état du flux de sortie standard est modifié.

Code-Apprenti
la source
1
En partie vrai, exécuter n'importe quelle opération serait l'état du compteur d'instructions, donc tout est un effet secondaire. La définition de l'effet secondaire dérive de la définition de la transparence référentielle, que de nombreuses personnes définissent en termes de modifications d'un état mutable partagé.
Luis Miguel Mejía Suárez
2
de cette façon, toute fonction, opération .... sera impure, car elle change, état de la mémoire cpu .....,
aName
2

De bonnes réponses ont déjà été données à cette question, mais permettez-moi d'ajouter mes deux cents.

Si vous regardez à l'intérieur de la printlnfonction, c'est essentiellement la même chose java.lang.System.out.println()- donc lorsque vous appelez la printlnméthode de bibliothèque standard de Scala sous le capot, elle appelle la méthode printlnsur l' PrintStreaminstance d'objet qui est déclarée comme champ outdans la Systemclasse (ou plus précisément outVardans Consoleobjet), ce qui change son état interne . Cela peut être considéré comme une autre explication de la printlnfonction impure.

J'espère que cela t'aides!

Ivan Kurchenko
la source
1

Il s'agit du concept de transparence référentielle . Une expression est référentiellement transparente si vous pouvez la remplacer par son résultat évalué sans changer le programme .

Lorsqu'une expression n'est pas référentiellement transparente, nous disons qu'elle a des effets secondaires .

f(println("effect"), println("effect"))
// isn't really equivalent to!
val x = println("effect")
f(x, x)

tandis que

import cats.effect.IO

def printlnIO(line: String): IO[Unit] = IO(println(line))

f(printlnIO("effect"), printlnIO("effect"))
// is equivalent to
val x = printlnIO("effect")
f(x, x)

Vous pouvez trouver une explication plus détaillée ici: https://typelevel.org/blog/2017/05/02/io-monad-for-cats.html

Didac Montero
la source
Je ne vois pas pourquoi f (x, x) est différent de f (println ("effect"), println ("effect")) !!
aName
f(println("effect"), println("effect"))va imprimer deux fois dans la console "effet" tandis que val x = println("effect");f(x,x)va imprimer une fois.
Didac Montero
quelle est la définition de la fonction f
aName