Re: Side effect and return value
"avi.e.gross--- via Tutor" <[email protected]> Fri, 20 Sep 2024 21:26:52 -0400
| Newsgroups | gmane.comp.python.tutor |
|---|---|
| Message-ID | <[email protected]> |
The following is OPINION except where it is FACT. And this is long enough that some of you should hit NEXT. The topic is about one form of purity or, frankly, religion, in Computer Science and related fields. There is a school of thought that makes a fairly valid point. If you want a high probability of code that does not cause odd errors, and can mathematically be shown to in some sense be optimal, then you can restrict a language drastically so it does a very few things well and other things with difficulty and others not at all. In the real world people rapidly move on if they can as these are toy languages in many ways. It is true that many things in CS can be written in ways that work decently and mostly for small samples. Consider something as simple as adding things to a list. In some languages, that means you slide forward one link at a time to the last item which points to something like NIL and add an item. By the time you are adding thousands, this slows down. Someone suggest an idea. Build the list backwards as inserting a new front item takes constant time. When done, reverse the list just once! That is an example of twisting the algorithm when you could have had a form of linear list that keeps a pointer both to the head and tail and can be added to trivially. That would make the operation fast but opens possible vulnerabilities. Along come purists and suggest every addition to a new list must be done by asking some central code to make a COPY with the added item. The old version now can be garbage collected as nothing else may be allowed to "point" to it. Therefore, your code typically requires a call to a function to result in receiving the new list and at the same time, the old list is no longer available or in scope. Often you have to stand on your head in these scenarios to get things done before winter. Or take recursion. Some languages want to do almost everything recursively. Nice but it can eat memory having a hundred function calls on the stack when some iterative solution takes up no space at all. But, if you can somehow rewrite the algorithm to use tail recursion, all is fine as each function call replaces the previous one on the stack. Too many other examples like this make you realize that purists are too pure to be allowed to program. So, consider the opposite. A language like Python supports objects and a way to program using object-oriented paradigms. Many, probably most, languages now have such ideas to one degree or another. But objects have all kinds of "state" that is or becomes a part of them. All kinds of operations change them internally. They can become quite large and contain other objects within them or off to the side. Talk about side effects because so much of what you do to them just changes the internals and the results may be seen later or not at all. Imagine an object that holds some statistical analysis and there is a way to specify options later, such as to use a different method of sorting by providing a function to use so that filenames like "S3E22" will sort before "S12E123". This is a real example I recently worked on. When you set this, nothing much happens. But later, when the object has a need to sort the data it has been given, it now does something different than before and sorts the lists ["S", 3, "E", 22] versus ["S", 12, "E", 123] which sorts differently than just alphabetically would have. If objects were immutable, and some are, then I see a need for massive amounts of copying as any change to an object cannot happen unless it is done anew. Older versions may persist. I see a potential mess. You almost want to construct an object all at once. So, just being object oriented may make the concept of a function doing either a side-effect or return something a bit fuzzy. But python has MANY other ideas and constructs that simply do not easily go away and keep changing. One is closures where you can create functions that somehow hold on to variables so that calling them again and again allows them to retrieve and change those variables. They act a tad like objects. Another is generators of several kinds that do not finish but yield something and sleep till called again and yield some more. Some can also receive something. Calling a generator to keep returning the next prime will thus change the generator to hold on to the last rime it calculated so it can next time start from right after that. It sounds like a variant of a closure or it can look like an object that can be called and stores the change each time. I will stop but assure you there are so many more ideas like currying and other functional programming methods that are very useful and yet seem to violate all kinds of idealistic rules. Bring in parallel programming and the mess gets messier. But, that does not mean you should not follow the advice when feasible. If you do not need a mutable list but can use a tuple, then you probably should. Some mistakes would then perhaps be caught. My opinion is that python has been way too lax compared to some other languages and that can be good. The attempts at adding variations on TYPING to the language as options has some merit as it allows programmers to state clearly their intent so that linters can detect many anomalies. This may be a reasonable compromise between purity and practicality, if done well. -----Original Message----- From: Tutor <[email protected]> On Behalf Of Albert-Jan Roskam Sent: Friday, September 20, 2024 11:03 AM To: dn <[email protected]> Cc: [email protected] Subject: Re: [Tutor] Side effect and return value On Sep 20, 2024 02:06, dn via Tutor <[email protected]> wrote: On 20/09/24 08:40, Albert-Jan Roskam wrote: > Hi, > I've just read "Code that fits into your Brain". > The author says a function with a side effect should not have a return > value. But how would one write this function in order to do that? It took me a moment to realise that what I was (trying to) remembering is Mark Seemann's book, "Code that fits in your Head". === That's indeed the book I meant. Loved reading it. He also mentioned that learning/using functional principles had also been very useful for his OOP skills. But I think you're right, one has to be pragmatic sometimes. 1 Pure Functions: A pure function is one where the output is determined solely by its input values, without observable side effects. 2 Avoiding Side Effects: Functional programming aims to minimize side effects, which are changes in state that occur outside a given function's scope. ==== Hmmm, the function in my example was not pure in two ways: the GUIDs in the json make the return value impossible to predict AND it has a side effect (a record is INSERTed in a table). Oh well. :-) @Cameron's post illustrates such very neatly. === Did Cameron also reply to my post? I didn't see anything. Is there also a news group for Python Tutor? The mailing lists have been so quiet lately. Comp.lang.python has more traffic the mirrored mailing list _______________________________________________ Tutor maillist - [email protected] To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor _______________________________________________ Tutor maillist - [email protected] To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor