On 2/28/18 11:00 PM, ROGER GRAYDON CHRISTMAN wrote:
On Wed, Feb 28, 2018, Rick Johnson wrote: >
On Wednesday, February 28, 2018 at 5:02:17 PM UTC-6, Chris Angelico wrote:
Here's one example: reference cycles. When do they get detected?
Taking a really simple situation:

class Foo:
     def __init__(self):
         self.self = self
*shudders*

Can you provide a real world example in which you need an
object which circularly references_itself_? This looks like
a highly contrived example used to (1) merely win the
argument, and (2) Bump fib() up one position from it's
current position as "the worst introductory example of how
to write a function in the history of programming tutorials"
If you want something that looks like a real world example,
consider the very common doubly-linked list:
     [ 1 ] <---> [ 2 ] <---> [ 3 ] <--.....--> [ N ]

This is chock-full of reference cycles, everywhere you see a <-->

Then you have a wrapper List object that has a head referencing
the 1 node and a tail referencing the N node.

And you decide you don't need that List any more.

You could:
1) Take the time the code to carefully delete every single node
in this linked list, taking the time to set all of the internal references to
None, or
2) Just discard your List object, and let the GC take care of the rest.

Note that removing the list alone does not clear any of the
reference counts in the picture above, because those internal
<--> references are all still there.  You either have to manually
remove all the references, or rely on the garbage collector.

Oh, and for those who claim that reference counting is 'efficient',
do bear in mind that every single assignment statement increases
the reference count of one value and possibly reduces the reference
count of another.  So down in the machine or byte-code world,
every assignment operation is really two arithmetic computations
and three assignments, which takes 5 times as many operations
as not doing any reference counting at all.

So if you have a program that can get by leaving unused memory
allocated, and can still terminate the program before all the memory
is claimed, your reference count system is far less efficient than
relying on a garbage collector that happens to not get activated
before your program ends.

Roger Christman
Pennsylvania State University

Now, of course in a language that WANT'S to make reference counting work, and allow for deterministic destruction of object happen, all you need to do isĀ  make one direction of the pointer into a 'weak reference', and the list control object have a strong pointer to the end that starts the strong chain and a weak reference to the other, and when the list control object goes away, so does all the list elements.

Yes, there is a slight speed cost in keeping the reference counts, but there is also a significant cost to the processing that is needed to run the garbage collection. And that doesn't include the cost of having to explicitly manage all resources that aren't memory as you have broken the RAII concept.

I will agree that many programs many programs don't need precise destruction for most of their objects, but many can be helped by it for at least a specific set of them.

I am not sure how hard it would be to implement a really useful reference counting system in Python, as first you would need a concept of a weak pointer to deal with cases like your list above (which I don't think Python has anything like that concept). You would also need to keep the current garbage collection, to handle the existing cases of circular references (I disagree with the original complaint that these are always 'errors', if you know you have garbage collection, the allowance of cycles knowing they will still get cleaned up is a useful simplification if you don't need the immediate clean up).

--
Richard Damon

--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to