Почему println считается нечистой функцией? - PullRequest
10 голосов
/ 26 февраля 2020

Я читаю книгу программирования на scala, и мне говорят:

... в этом случае его побочным эффектом является печать в стандартный поток вывода.

и я не вижу, где находится побочный эффект, так как для того же ввода println напечатает тот же вывод (я думаю)
ОБНОВЛЕНИЕ
например всякий раз, когда мы вызываем:

println(5)

, это напечатает 5 , я не вижу случая, когда вызов println(5) напечатает значение, отличное от 5 !!

Ответы [ 5 ]

6 голосов
/ 26 февраля 2020

Вы можете определить, имеет ли выражение побочный эффект, заменив выражение его результатом. Если программа меняет , что означает , это побочный эффект. Например,

println(5)

- это программа, отличная от

()

То есть побочным эффектом является любой наблюдаемый эффект, который не закодирован в результате вычисления выражения. Здесь результат равен (), но в этом значении нет ничего, что кодировало бы тот факт, что 5 теперь появилось где-то на вашем экране.

5 голосов
/ 26 февраля 2020

Рассмотрим следующую аналогию

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

Здесь myprintln нечисто, поскольку помимо возвращаемого значения () оно также изменяет нелокальную переменную out в качестве побочного эффекта. Теперь представьте, out - это поток ванили println мутирует.

4 голосов
/ 26 февраля 2020

Побочный эффект в состоянии компьютера. Каждый раз, когда вы вызываете println(), состояние памяти изменяется, чтобы отобразить данное значение на терминале. Или, в более общем случае, состояние стандартного выходного потока изменяется.

2 голосов
/ 26 февраля 2020

Хорошие ответы уже были даны на этот вопрос, но позвольте мне добавить мои два цента.

Если вы заглянете внутрь функции println, то по сути это то же самое, что и java.lang.System.out.println() - поэтому, когда вы вызываете метод стандартной библиотеки Scala println под капотом, он вызывает метод println on PrintStream экземпляр объекта, который объявлен как поле out в System классе (или, точнее, outVar в Console объекте), который изменяет его внутреннее состояние. Это можно рассматривать как еще одно объяснение, почему println является нечистой функцией.

Надеюсь, это поможет!

1 голос
/ 26 февраля 2020

Это связано с концепцией ссылочной прозрачности . Выражение является ссылочно прозрачным, если вы можете заменить его оцененным результатом без изменения программы .

Когда выражение не является ссылочно прозрачным, мы говорим, что оно имеет побочные эффекты .

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

while

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)

Более подробное объяснение можно найти здесь: https://typelevel.org/blog/2017/05/02/io-monad-for-cats.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...