10

I'm reading the book programming in scala, and it is said :

... in this case , its side effect is printing to the standard output stream.

and I don't see where is the side effect, since, for the same input, println will print the same output (I think )
UPDATE
for example any time we call :

println(5)

it will print 5, I don't see a case where calling println(5) will print a value other than 5 !!

aName
  • 2,751
  • 3
  • 32
  • 61
  • if this answers your question, I'll delete my answer https://softwareengineering.stackexchange.com/q/40297/271736 – joel Feb 25 '20 at 21:24
  • 3
    Answers at [What is referential transparency?](https://stackoverflow.com/q/210835/217324) seem relevant here. – Nathan Hughes Feb 25 '20 at 21:33
  • 1
    related (lol) https://stackoverflow.com/q/4865616/5986907 – joel Feb 25 '20 at 21:40
  • 2
    You confused side effect (not referential transparent) with deterministic. `println` is a deterministic function but in order to be pure it must also be RT. –  Feb 26 '20 at 08:25
  • 3
    Because it does something other than compute a result and return it. – Seth Tisue Feb 26 '20 at 08:53
  • If you can't see where the side effect is, I recommend plugging in your monitor. ;) – stefanobaghino Jun 21 '20 at 12:23

5 Answers5

8

You can tell if an expression has a side effect by replacing the expression with its result. If the program changes meaning, there's a side effect. For example,

println(5)

is a different program to

()

That is, a side effect is any observable effect that isn't encoded in the result of evaluating an expression. Here the result is (), but there's nothing in that value that encodes the fact that 5 has now appeared somewhere on your screen.

joel
  • 6,359
  • 2
  • 30
  • 55
  • 6
    Actually that is not a good definition of a _"side-effect"_ - A side effect may be defined as anything that breaks referential transparency. What you tried to show here was RT but your example is wrong. Since executing something multiple times should do the same thing mutiple times - Rather, `val a = println("hello"); val b = (a, a)` should be the same as `val b = (pritnln("hello"), println("hello"))`. – Luis Miguel Mejía Suárez Feb 25 '20 at 21:25
  • 1
    @LuisMiguelMejíaSuárez perhaps my example's not clear, but I don't think it's wrong. I'm essentially pointing out the difference between the program `println(5)` and `()`. Or did you mean the last sentence? – joel Feb 25 '20 at 21:29
  • Yeah but you weren't clear about it. Since,as I said, the problem is not calling something multiple times, the problem is if replacing a reference with its definition would have that impact. – Luis Miguel Mejía Suárez Feb 25 '20 at 21:30
  • 5
    I'd say it's wrong because it's perfectly possible for something to have a side effect and be idempotent so repeating it doesn't change the effect. E.g. assignment to a mutable variable; how can you distinguish `x = 1` and `x = 1; x = 1; x = 1`? – Alexey Romanov Feb 26 '20 at 07:38
  • @AlexeyRomanov I've edited my answer. But for your example, I don't see how the second and third assignments are side effects. Nothing's changing at all there. – joel Feb 26 '20 at 11:10
  • It's simpler to classify `x = 1` as having a side-effect, full stop, regardless of context, rather than saying "it only has a side effect if x isn't already 1". The two buckets are "never side-effects" and "sometimes/always side-effects". It isn't normally useful to distinguish the "sometimes" and "always" cases from each other. – Seth Tisue Feb 29 '20 at 14:31
6

The side effect is in the state of the computer. Each time you call println() the state of memory changes in order to display given value to the terminal. Or more generally, the state of the standard output stream is changed.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
  • 1
    Partially true, execute any operation would the state of the instruction counter, thus anything is a side effect. The definition of side-effect derivates from the definition of referential transparency, which many people define in terms of modifications to a shared mutable state. – Luis Miguel Mejía Suárez Feb 25 '20 at 21:27
  • 2
    in this way, any function, operation.... will be impure, since it change, state of memory cpu....., – aName Feb 25 '20 at 22:15
6

Consider the following analogy

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

Here myprintln is impure because beside returning value () it also mutates non-local variable out as a side-effect. Now imagine out to be the stream vanilla println mutates.

Mario Galic
  • 47,285
  • 6
  • 56
  • 98
  • 1
    thank you, for responding, it is clear that your function is impure, however, why println(), as defined in scala, is not pure – aName Feb 25 '20 at 22:15
  • 1
    @aName Because besides returning value `()` it also mutates non-local state in [`System.out`](https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#out). – Mario Galic Feb 25 '20 at 23:16
  • I think the crucial fact missing from this answer is that println adds a newline character to the input. – theberzi Feb 26 '20 at 15:23
2

Nice answers were already given to this question, but let me add my two cents.

If you will look inside println function essentially it is the same as java.lang.System.out.println() - so when you invoke Scala's standard library println method under the hood it invokes method println on PrintStream object instance which is declared as field out in System class (or more precisely outVar in Console object), which changes it internal state. This can be considered as another one explanation why println is impure function.

Hope this helps!

Ivan Kurchenko
  • 4,043
  • 1
  • 11
  • 28
2

It has to do with the concept of referential transparency. An expression is referentially transparent if you can substitute it with its evaluated result without changing the program.

When an expression is not referentially transparent we say that it has side effects.

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)

You can find a more detailed explanation here: https://typelevel.org/blog/2017/05/02/io-monad-for-cats.html

Didac Montero
  • 2,046
  • 19
  • 27