Death to tuples!

Bengt Richter bokr at oz.net
Fri Dec 2 14:32:58 EST 2005


On 2 Dec 2005 13:05:43 GMT, Antoon Pardon <apardon at forel.vub.ac.be> wrote:

>On 2005-12-02, Bengt Richter <bokr at oz.net> wrote:
>> On 1 Dec 2005 09:24:30 GMT, Antoon Pardon <apardon at forel.vub.ac.be> wrote:
>>
>>>On 2005-11-30, Duncan Booth <duncan.booth at invalid.invalid> wrote:
>>>> Antoon Pardon wrote:
>>>>
>
>Personnaly I expect the following pieces of code
>
>  a = <const expression>
>  b = <same expression>
>
>to be equivallent with
>
>  a = <const expression>
>  b = a
>
>But that isn't the case when the const expression is a list.
>
ISTM the line above is a symptom of a bug in your mental Python source interpreter.
It's a contradiction. A list can't be a "const expression".
We probably can't make real progress until that is debugged ;-)
Note: assert "const expression is a list" should raise a mental exception ;-)

>A person looking at:
>
>  a = [1 , 2]
English: let a refer to a mutable container object initialized to contain
an ordered sequence of specified elements 1 and 2.
>
>sees something resembling
>
>  a = (1 , 2)
English: let a refer to an immutable container object initialized to contain
an ordered sequence of specified elements 1 and 2.
>
>Yet the two are treated very differently. As far as I understand the
>first is translated into somekind of list((1,2)) statement while
They are of course different in that two different kinds of objects
(mutable vs immutable containers) are generated. This can allow an optimization
in the one case, but not generally in the other.

>the second is build at compile time and just bound.
a = (1, 2) is built at compile time, but a = (x, y) would not be, since x and y
can't generally be known a compile time. This is a matter of optimization, not
semantics. a = (1, 2) _could_ be built with the same code as a = (x, y) picking up
1 and 2 constants as arguments to a dynamic construction of the tuple, done in the
identical way as the construction would be done with x and y. But that is a red herring
in this discussion, if we are talking about the language rather than the implementation.

>
>This seems to go against the pythonic spirit of explicit is
>better than implicit.
Unless you accept that '[' is explicitly different from '(' ;-)

>
>It also seems to go against the way default arguments are treated.
I suspect another bug ;-)

>

>> but that's independent of scope. An expression in general may depend on
>> names that have to be looked up, which requires not only a place to look
>> for them, but also persistence of the name bindings. so def foo(arg=PI*func(x)): ...
>> means that at call-time you would have to find 'PI', 'func', and 'x' somewhere.
>> Where & how?
>> 1) If they should be re-evaluated in the enclosing scope, as default arg expressions
>> are now, you can just write foo(PI*func(x)) as your call.
>
>I may be a bit pedantic. (Read that as I probably am)
>
>But you can't necesarry write foo(PI*func(x)) as your call, because PI
>and func maybe not within scope where the call is made.
Yes, I was trying to make you notice this ;-)

>
>> So you would be asking
>> for foo() to be an abbreviation of that. Which would give you a fresh list if
>> foo was defined def foo(arg=[]): ...
>
>This was my first thought.
>
[...]
>>>>> Why on earth should it be the same list, when a function is called
>>>>> and is provided with a list as a default argument?
>> It's not "provided with a list" -- it's provided with a _reference_ to a list.
>> You know this by now, I think. Do you want clone-object-on-new-reference semantics?
>> A sort of indirect value semantics? If you do, and you think that ought to be
>> default semantics, you don't want Python. OTOH, if you want a specific effect,
>> why not look for a way to do it either within python, or as a graceful syntactic
>> enhancement to python? E.g., def foo(arg{expr}):... could mean evaluate arg as you would like.
>> Now the ball is in your court to define "as you would like" (exactly and precisely ;-)
>
>I didn't start my question because I wanted something to change in
>python. It was just something I wondered about. Now I wouldn't
I wonder if this "something" will still exist once you get
assert "const expression is a list" to raise a mental exception ;-)

>mind python to be enhanced at this point, so should the python
>people decide to work on this, I'll give you my proposal. Using your
>syntax.
>
>  def foo(arg{expr}):
>     ...
>
>should be translated something like:
>
>  class _def: pass
>
>  def foo(arg = _def):
>    if arg is _def:
>      arg = expr
>    ...
>
>I think this is equivallent with your first proposal and probably
>not worth the trouble, since it is not that difficult to get
>the behaviour one wants.
Again, I'm not "proposing" anything except to help lay out evidence.
The above is just a spelling of typical idiom for mutable default
value initialization.

>
>I think such a proposal would be most advantaged for the newbees
>because the two possibilities for default values would make them
>think about what the differences are between the two, so they
>are less likely to be confused about the def f(l=[]) case.
>
So are you saying it's not worth the trouble or that it would be
worth the trouble to help newbies?
[...]
>>>Again you are just stating the specific choice python has made.
>>>Not why they made this choice.
>> Why are you interested in the answer to this question? ;-)
>
>Because my impression is that a number of decisions were made
>that are inconsistent with each other. I'm just trying to
>understand how that came about.
An inconsistency in our impression of the world
is not an inconsistency in the world ;-)

>> Do you want
>> to write an accurate historical account, or are you expressing discomfort
>> from having had to revise your mental model of other programming languages
>> to fit Python? Or do you want to try to enhance Python in some way?
>
>If there is discomfort, then that has more to do with having revised
>my mental model to python in one aspect doesn't translate to
>understanding other aspects of python enough.
>
An example?
>>>I know what happens, I would like to know, why they made this choice.

>>>One could argue that the expression for the default argument belongs
>>>to the code for the function and thus should be executed at call time.
>>>Not at definion time. Just as other expressions in the function are
>>>not evaluated at definition time.
>> Maybe it was just easier, and worked very well, and no one showed a need
>> for doing it differently that couldn't easily be handled. If you want
>> an expression evaluated at call time, why don't you write it at the top
>> of the function body instead of lobbying for a change to the default arg
>> semantics?
>
>I'm not lobbying for a change. You are probably right that this is again
>the "Practical beats purity" rule working again. But IMO the python
I didn't say this was a case of "Practical beats purity" -- I said "maybe
it was just easier" -- which doesn't necessarily mean impure to me, nor
that the more difficult choice would have been better ;-)
In fact I think the way default args work now works fine.
If I were to make a list of things to change, that would not be at the top.

>people are making use of that rule too much, making the total language
>less pratical as a whole.
IMO this is hand waving unless you can point to specifics, and a kind of
unseemly propaganda/innuendo if you can't.

>
>Purity is often practical, because it makes it easier to infer knowlegde
>from things you already know. If you break the purity for the practical
>you may make one specific aspect easier to understand, but make it
>less practical to understand the language as a whole.
That is a good point, but to have the real moral standing to talk about purity
one has to be able to demonstrate it, which is really hard.

>
>Personnally I'm someone for whom purity is practical in most cases.
>If a language is pure/consistent it makes the langauge easier to
>learn and understand, because your knowledge of one part of the
>language will carry over to other parts.
I agree, so long as the "knowledge of one part" is not a misconception.

>
>Isn't is practical that strings tuples and list all treat '[]'
>similarly for accessing an individual in the sequence. That means
>I just have to learn what v[x] means for tuples and I know what
>it means for lists, strings and a lot of other things.
But not all, since your example v[x] requires that v not be a dict.

>
>Having a count method for lists but not for tuples breaks that
>consistency and makes that I have to look it up for each sequence
>whether or not it has that method. Not that practical IMO.
But I think you are having the wrong expectation of v[x] syntax.
It will generate code that looks for __getitem__ and having __getitem__
means that iteration syntax may access it if __iter__ does not preempt,
but if you expect this to guarantee the presence of other methods
such as count, then you are misreading v[x].

OTOH, you can have some expectations of list(v), which if it succeeds
will give you the list methods. As mentioned in another post, I think
if iter were a type, iter(v) could return an iterator object that could
have all the methods one might think appropriate for all sequences, and
could thus be a way of unifying sequence usage. iter could also allow
some handy methods that return further specialized iterators (a la itertools)
rather than consuming itself to return a specific result like a count.

>
>> [ ... ]
>>
>> or what are we pursuing?
>
>What I'm pursuing I think is that people would think about what
>impractical effects can arise when you drop purity for practicallity.
I think this is nicely said and important. I wish it were possible
to arrive at a statement like this without wading though massive irrelevancies ;-)

>
>My impression is that when purity is balanced against practicallity
>this balancing is only done on a local scale without considering
>what practicallity is lost over the whole language by persuing
>praticallity on a local aspect.
It is hard to demonstrate personal impressions to others, since
we are not Vulcans capable of mind-melds, so good concrete examples
are critical, along with prose that focuses attention on the aspects
to be demonstrated. Good luck, considering that what may seem
like a valid impression to you may seem like a mis-reading to others ;-)

BTW, I am participating in this thread more out of interest in
the difficulties of human communication that in the topic per se,
so I am probably OT ;-)

Regards,
Bengt Richter



More information about the Python-list mailing list