98

If a function doesn't have any side effects and it doesn't return anything, then the function is useless. It is as simple as that. But I guess you can use some cheats if you want to follow the letter of the rules and ignore the underlying reasoning. For example using an out parameter is strictly speaking not using a return. But it still does precisely the ...


85

I'm not sure about universal definitions of purity, but from the point of view of Haskell (a language where programmers tend to care about things such as purity and referential transparency), only the first of your functions is "pure". The second version of add isn't pure. So in answer to your question, I'd call it "impure" ;) According to this definition, ...


35

Tell, Don't Ask comes with some fundamental assumptions: You're using objects. Your objects have state. The state of your objects affects their behavior. None of these things apply to pure functions. So let's review why we have the rule "Tell, Don't Ask." This rule is a warning and a reminder. It can be summarized like this: Allow your class to ...


30

When I deal with an object I don't ask it about its internal state. I tell it what I need to be done and it uses its internal state to figure out what to do with what I've told it to do. You don't only ask for its internal state, you don't ask if it has an internal state at all either. Also tell, don't ask! does not imply not getting a result in form of a ...


27

If the memory you access can change, then it is indeed a side effect. For example, in Haskell, the function to access a mutable array (IOArray) has type Ix i => IOArray i e -> i -> IO e (slightly simplified for our purposes). While accessing an immutable array has type Ix i => Array i e -> i -> e The first version returns something of ...


27

Functional programming includes many different techniques. Some techniques are fine with side effects. But one important aspect is equational reasoning: If I call a function on the same value, I always get the same result. So I can substitute a function call with the return value, and get equivalent behaviour. This makes it easier to reason about the program,...


23

There is one semi-conditional side effect I can think of that is okay: while(iter.MoveNext()) That said, I think this falls mostly into the "never is a really big qualifier" category. I can think of a few rare cases where I've seen it be acceptable, but in general this is vile and to be avoided. I also cannot think of a scenario where that particular ...


22

What do you call a function [for which] the same input will always return the same output, but also has side effects? Such a function is called deterministic An algorithm whose behavior can be completely predicted from the input. termwiki.com Regarding state: Depending on whose definition of a function you use, a function has no state. If you come from ...


20

Let's begin with a definition for referential transparency: An expression is said to be referentially transparent if it can be replaced with its value without changing the behavior of a program (in other words, yielding a program that has the same effects and output on the same input). What that means is that (for example) you can replace 2 + 5 ...


17

Referential Transparency means that you can replace an expression with the result of evaluating that expression everywhere in the program without changing the result of the program. So, take the following program: a = foo(1, 2) + foo(1, 2) b = a + global_variable Referential Transparency says that I can replace every occurrence of foo(1, 2) with the ...


17

If you consider return as "harmful" (to stay in your picture), then instead of making a function like ResultType f(InputType inputValue) { // ... return result; } build it in a message-passing manner: void f(InputType inputValue, Action<ResultType> g) { // ... g(result); } As long as f and g are side-effect free, chaining them ...


16

You have described an effect system. It’s true that there are other effect systems than monads, but in practice monads give you a lot of expressive power that you would need to reinvent in any practical effect system you might devise. For example: I start by tagging my I/O procedures with an io effect. My pure functions can still throw exceptions, but ...


16

The Haskell optimizer is allowed to freely manipulate calls to pure functions as long as the result remains the same. For example, if it can see that you are calling sqrt on the same number 100 times, it can cache the returned value and only call it once. If it can see that you never actually use the result of that function, it can choose to not call it at ...


15

The whole program is going to end up contained in the IO monad, basically. That's the bit where I think you're not seeing it from the Haskellers' perspective. So we have a program like this: module Main main :: IO () main = do xmlData <- readFile "input.xml" let jsonData = convert xmlData writeFile "output.json" jsonData convert :: String -> ...


14

Simplest possible example: printing "Hello, world!" changes the state of the system, because the console now displays "Hello, world!", and earlier it didn't. Not only have you changed the state, it's actually impossible to change it back, since you can't un-get characters from a terminal! That's about the most serious side effect possible.


13

According to Greg Young, this idea originated from Bertrand Meyer: Command-Query separation. It states that every method should either be a command that performs an action, or a query that returns data to the caller, but not both. In other words, Asking a question should not change the answer.1 More formally, methods should return a value only if ...


12

(I don't know Erlang, and I can't write Haskell, but I think I can answer nevertheless) Well, in that interview the example of a random number generation library is given. Here is a possible stateful interface: # create a new RNG var rng = RNG(seed) # every time we call the next(ceil) method, we get a new random number print rng.next(10) print rng.next(10)...


12

Obviously, you can find examples of incredibly difficult to read pure functions that perform the same calculations as functions with side effects that are much easier to read. Especially when you use a mechanical transformation like a Y-combinator to arrive at a solution. That's not what is meant by "easier to reason about." The reason it's easier to ...


11

I think you've reinvented monads! Let's look at what we have here, we can "dirty" a pure computation implicitly and use it in an impure one, and we can call impure function from another impure one. That sounds a lot like monads, we can dirty a pure value with return, to call another function from an impure function, we can just use >>= apply :: (a -&...


11

I primarily work in functional code now, and from that perspective it seems blindingly obvious. Side effects create a huge mental burden on programmers trying to read and understand code. You don't notice that burden until you are free from it for a while, then suddenly have to read code with side effects again. Consider this simple example: val foo = 42 ...


11

Looping in functional programming isn't done with control statements like for and while, it's done with explicit calls to functions like map, fold, or recursion - all of which involve placing the inner loop call inside another function. If the loop code mutates variables outside the loop, this inner loop function would be manipulating variables outside its ...


11

An interesting property of languages without side-effects is that introducing parallelism, concurrency, or asynchrony cannot change the meaning of the program. It can make it faster. Or it can make it slower. But it can't make it wrong. This makes it trivial to automatically parallelize programs. So trivial, in fact, that you usually end up with too much ...


11

Some thoughts: Now, as far as I know, it's bad practice to have effectful computations inside a constructor That depends on what you mean by "effectful." The purpose of a constructor is to "construct" an object. To do that, you may need to do many things. One of the things you may need to do is set up some state inside the new object. ...


10

In computer science, a function or expression is said to have a side effect if, in addition to returning a value, it also modifies some state or has an observable interaction with calling functions or the outside world. Reading from a file is an observable interaction with the outside world. It meets the definition of side effect. Reading the 42nd element ...


10

If you don't care about the side effect, then it's referentially transparent. Of course it's possible that you don't care but someone else does, so the applicability of the term is context-dependent. I don't know of a general term for precisely the properties you describe, but an important subset are those that are idempotent. In computer science, slightly ...


9

There is no universal definition of OOP. It is therefore difficult to make a statement like “OOP is stateful”. There are both examples where OOP involves state and examples where OOP is used without any state. OOP tends to be paired with imperative programming, which certainly allows side effects and mutable state. There is one line of thought that OOP is ...


9

I am not sure if there is legitimate use-cases for such code patterns. Yes there are, and such stuff is even used in the c++ standard library. Prominent examples are the std::lock_guard and any kind of Smart Pointers. The principle always follows this pattern: Create a scope Setup some resource (e.g. a mutex lock) within a constructor function Do something ...


8

In my world, a read from memory may be considered a side effect (e.g. memory mapped IO). Now, consider the following: while( ( *memory_mapped_device_status_register & READY_FLAG) == 0) { // Wait } And compare to: status = *memory_mapped_device_status_register; while( ( status & READY_FLAG) == 0) { // Wait ...


7

What I would do in this case would be to introduce my own RobotControl interface with methods corresponding to the ones in the real lib. After having done this, I would make a RobotControlImpl class which implements this interface against the real robot lib. The commands that I consequently would write would not extend the base class, but instead ...


7

Heating the processor and losing time by useless computations is a side effect which is generally ignored, so could be considered as not very concrete. It is not concrete according to the quoted definition of Meyer. This is why compilers are permitted to optimize useless code like /// spend some time busy waiting in a useless computation for (int i=1; i&...


Only top voted, non community-wiki answers of a minimum length are eligible