On Tue, Mar 31, 2020 at 12:39:56AM -0700, Christopher Barker wrote:

> But while the OP specifically suggested adding += to stringIO, you might
> note that he did not suggest it as an extension to the file protocol, which
> StringIO mimics. Rather, he suggested that there should be something that
> can be used as an efficient buffer to build up strings, that had the same
> API as str does. He figures that it would be pretty easy to get that by
> adding += to StringIO.
> 
> But wouldn’t a mutable string type satisfy that as well?

Indeed it would, and if I ask for a nutcracker to crack open peanuts a 
nuclear powered 200 tonne bulldozer would satisfy the requirements too.

What Paul asked for:

https://media.qcsupply.com/media/catalog/product/cache/122b61bfb663175d7f1bbb5dbb7f535b/3/5/350679-3_2.jpg

What we're talking about instead:

http://media.firebox.com/pic/p1861_column_grid_12.jpg

If you want a mutable string type, you have to support a rather 
extensive string API that includes at least ten operators:

    + * % == != in < <= >= >

plus slicing and about 45 methods. (There may be some things I have 
missed.) Paul asked for *one* operator, `+=`.


> And why WOULD folks that want a buffer to build strings in use string
> concatenation? Maybe because in the end they want a string? But even if
> StringIO grew +=, then they get a StringIO object at the end, and would
> need to call .getvalue() to get a str.

Yes, rather like the way you have to call `''.join(buf)` if you use a 
list.

If your point is a criticism of the StringIO proposal, it is equally a 
criticism of the recommended list+join idiom, but we still tell people 
to use list+join, so it can't be a very important issue.

And if it's not a valid criticism of the list+join idiom, or at least a 
very minor, unimportant one, then precisely the same applies to 
StringIO.


> So how exactly does this meet the use case of being able to drop it into
> code that’s written to use strings?

This has been covered at least twice, once by Paul and once by me. When 
you are refactoring the "string concatenation" idiom to list append, 
you have to change three things:

1. the buffer initialisation: `buf = ''` --> `buf = []`;
2. add a conversion to the end: `result = ''.join(buf)`;
3. and potentially dozens of instances of `buf += s` to `buf.append(s)`.

The third may be scattered around multiple functions. It is not always 
an easy refactoring. We should not assume that every append to the 
buffer will be in a single place or even a single function.

Under Paul's suggestion, you change the buffer initialisation, add the 
conversion, and nothing else needs to be touched.

You also get a performance boost (by my testing, using StringIO is about 
halfway in speed between string concat and list+join), and potentially a 
memory saving relative to the list version.

(Although Paul's calculations on that have been disputed, and I don't 
think we have a definite answer on that one just yet.)


> BTW, what about folks that concatenaste strings with plain + ? You couldn’t
> drop StringIO in there reasonably either.

Do you mean people who write `buf = buf + substring`?

Maybe that's an argument to support `+` as well. Perhaps it would be 
weird and surprising to support augmented assignment for an operator 
without supporting the operator? But I don't have a strong feeling 
either way.

Or maybe that's just an argument that no solution is going to solve 
*every* problem. What do we do about people who write this:

    buf = f'{buf}{substring}'

inside a loop? We can't fix everyone's code with one change.


> If we want to provide a way for folks to not do naive string concatenation—
> adding += to StringIO is not any better than telling them to use a list and
> .join() — it’s still a whole other way of doing it.

It's not really. The point is to minimise how many things need to 
change. Instead of changing every `buf += s` into `buf.append(s)`, you 
just leave them alone.

In that regard, it's *the same way* of doing it, the only difference is 
that the buffer changes from an immutable string to a builder.

We should be careful to avoid exaggerating tiny differences, especially 
when that involves a double-standard.

Is it a problem for the recommended list+join idiom that it is "a whole 
other way of doing it"? If no, then its not a problem for StringIO 
either. If the answer is yes, then StringIO is no worse than what people 
are already told to do, so it's not really much of a problem.


> And the list and join() method uses two of the most common builtins— there
> is a real advantage to that.

Again, we must beware of double-standards. This list often says:

"Not everything needs to be a builtin, just put it in a module."

Also this list:

"Being a builtin is a real advantage, we can't use StringIO because it 
comes from a module that needs importing."

We can't have it both ways.

In this case, using StringIO does involve one extra import. Okay, that's 
fine, the standard library is full of things that require one extra 
import but nevertheless are a common, or even sometimes recommended, way 
to do it. itertools comes to mind especially, using iterators in Python 
is ubiquitous and yet we still require people to import a module to do 
something as fundamental as slice an iterator.

But maybe we can consider an alternative that doesn't require that 
import.

> Anyway, I’m not proposing a mutable string type. It was really just an
> example of: if this was really needed, it would have been done.

Ah, so by that argument, *every* new proposal can be immediately 
rejected. If this were really needed, it would have already been done. 
Python 3.8 is the optimal language with literally every single desirable 
feature, nothing to be added, and no unneeded cruft to be removed.

I trust that's not what you intended to say :-)


-- 
Steven
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/OHZ4LBSO6WPJFGQB77TZXX3ERTYH6Y6P/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to