[Tutor] Side effect and return value
avi.e.gross at gmail.com
avi.e.gross at gmail.com
Fri Sep 20 21:26:52 EDT 2024
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 <tutor-bounces+avi.e.gross=gmail.com at python.org> On Behalf Of
Albert-Jan Roskam
Sent: Friday, September 20, 2024 11:03 AM
To: dn <PythonList at DancesWithMice.info>
Cc: tutor at python.org
Subject: Re: [Tutor] Side effect and return value
On Sep 20, 2024 02:06, dn via Tutor <tutor at python.org> 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 - Tutor at python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
More information about the Tutor
mailing list