Why tuple with one item is no tuple

B

Bill Mill

Hi,
<type 'str'>

I wonder why ('1') is no tuple????

because, syntactically, those parens are for grouping, and do not
unambiguously define a tuple. It's a python gotcha. To define a
one-tuple, put a comma after the '1':
Because I have to treat this "special" case differently in my code.

you shouldn't have to; post your code if you still think you do.

Peace
Bill Mill
bill.mill at gmail.com
 
R

Roy Smith

Gregor Horvath said:
Hi,
<type 'str'>

I wonder why ('1') is no tuple????

You need to say ('1',). In just plain ('1'), the parens are
interpreted as grouping, not as tuple creation. Depending on your
point of view, this is either a "special case", or an "ugly wart" in
the syntax.

a = () # tuple of zero elements
a = (1,) # tuple of one element
a = 1, # tuple of one element
a = (1) # scalar
a = (1, 2) # tuple of two elements
a = 1, 2 # tuple of two elements
a = , # syntax error

The big question is, is it the parens that make it a tuple, or is it
the comma? If you go along with the parens school of thought, then
(1,) is the special case. If you believe in commas, then the () is
the special case. In either case, it's a bit ugly, but we learn to
overlook the occasional cosmetic blemishes of those we love :)
 
P

Paddy

Hmm,
going 'the other way', you are allowed an extra , but you can't have
(,) as the empty tuple.:
....
Traceback ( File "<interactive input>", line 1
(,)
^
SyntaxError: invalid syntax


-- Pad.
 
J

James Stroud

a = ()       # tuple of zero elements
a = (1,)     # tuple of one element
a = 1,       # tuple of one element
a = (1)      # scalar
a = (1, 2)   # tuple of two elements
a = 1, 2     # tuple of two elements
a = ,        # syntax error

The big question is, is it the parens that make it a tuple, or is it
the comma?  If you go along with the parens school of thought, then
(1,) is the special case.  If you believe in commas, then the () is
the special case.  In either case, it's a bit ugly, but we learn to
overlook the occasional cosmetic blemishes of those we love :)

The answer is obvious, the naked comma should be an empty tuple.
 
B

Bill Mill

The answer is obvious, the naked comma should be an empty tuple.

The other answer, that parens should be required to surround all
tuples, is obvious too.

Neither is particularly appealing; a lone comma creating a data
structure seems counter-intuitive, but it's nice to do a, b = b, a
instead of (a, b) = (b, a) . In this case, since the need to create
empty tuples is vanishingly rare, I'm okay with a little
inconsistency.

Peace
Bill Mill
bill.mill at gmail.com
 
R

Reinhold Birkenfeld

Bill said:
The other answer, that parens should be required to surround all
tuples, is obvious too.

Neither is particularly appealing; a lone comma creating a data
structure seems counter-intuitive, but it's nice to do a, b = b, a
instead of (a, b) = (b, a) . In this case, since the need to create
empty tuples is vanishingly rare, I'm okay with a little
inconsistency.

And if you don't like it at all, you can still use tuple() to "create"
an empty tuple.

Reinhold
 
A

Antoon Pardon

Op 2005-03-16 said:
Gregor Horvath said:
type(['1'])
type(('1'))
<type 'str'>

I wonder why ('1') is no tuple????

There were lots of answers, but I'm not sure I saw the "why" addressed.

Consider this:

a = (3 + 5) * 5

You really, really want (3 + 5) to be an integer, not a one-item tuple.

I sometimes do wonder if some impliciteness wouldn't be better here,
so that any item could be treated as if it was a one-item tuple.

A bit like every char being a string.
 
D

Diez B. Roggisch

Consider this:
I sometimes do wonder if some impliciteness wouldn't be better here,
so that any item could be treated as if it was a one-item tuple.

A bit like every char being a string.

There is no char. There are strings of lenght 1. And the above example makes
it clear that there would be an ambiguity that could _maybe_ be solved in a
static typed language (the application of the (3+5) as left side to the
operator <*> if <*> only is defined as [num, num] -> num), but clearly not
in a dynamic typed one as python.

And if the static typed language allows operator overloading, it could very
well be that someone creates a overloading for

<*> : [tuple[num], tuple[num]] -> <whatever>

which would reintroduce the ambiguity.

Soooooo, in the end it boils down to some explicitness - where IMHO an
additional comma is pretty much no problem at all. Another option would of
course be the introduction of different parentheses for tuples - but I
can't find some on my keyboard.
 
A

Antoon Pardon

Op 2005-03-16 said:
There is no char. There are strings of lenght 1.

That is a matter of view. But to illustrate what I mean,
the following is an infinite loop in python

s = 'hi'
while true:
s = s[0]
And the above example makes
it clear that there would be an ambiguity that could _maybe_ be solved in a
static typed language (the application of the (3+5) as left side to the
operator <*> if <*> only is defined as [num, num] -> num), but clearly not
in a dynamic typed one as python.

That ambiguity is only caused because python uses the same characters
for very different operations and to be honest I don't like that.

for instance I have written once somekind of vector class where
it was natural for these vectors to be added as well as te be
concatenated. Unfortunately python uses "+" for both so I had
no way to have both operators in a natural way in python.

So that a <*> would create an ambiguity if items would be silently
transformed in a one-item tuple when appropiate is IMO more caused
And if the static typed language allows operator overloading, it could very
well be that someone creates a overloading for

<*> : [tuple[num], tuple[num]] -> <whatever>

which would reintroduce the ambiguity.

Soooooo, in the end it boils down to some explicitness - where IMHO an
additional comma is pretty much no problem at all. Another option would of
course be the introduction of different parentheses for tuples - but I
can't find some on my keyboard.

Well I can't find braille on my keyboard, but if I wanted to, it
wouldn't be difficult to get it on my screen. So is it with
different parentheses. That python can't use these parentheses
is again a design decision.
 
D

Diez B. Roggisch

That ambiguity is only caused because python uses the same characters
for very different operations and to be honest I don't like that.

As I said: show me which parentheses to use - and keep in mind that:

- < and > are for comparisions and the same ambiguity troubles arise
- unicode surely features some usable characters (e.g. the quotation markes
that look like <<, but are one char). But for one that complains that
typing and additional comma is too much already, I doubt that having to
press some weird multi key stroke is a viable option. To me neither, as I
prefer my parentheses to be accessed easily, even on a vi running in a
console from a tn3270 terminal

for instance I have written once somekind of vector class where
it was natural for these vectors to be added as well as te be
concatenated. Unfortunately python uses "+" for both so I had
no way to have both operators in a natural way in python.

And no way in mathematics or any other language either - if you want the
same function symbol on the same operators to have _different_ semantics,
you're getting pretty non-deterministic.

So that a <*> would create an ambiguity if items would be silently
transformed in a one-item tuple when appropiate is IMO more caused
by the design decision to use <*> for two totally diffent operations
then because of the dynamic nature of python.

Your opinion is wrong. It's because you seem to not have understood the
example: The expression (5 + 4) could be understood as 9 or as (9,). In
python (and each and every other dynamically typed language) you can't
decide which version to take. So you have to decide on _one_, and as every
kid in school learns that (5+4) * 5 is 45, it was a reasonable decision to
use the semantics we have today.

In a statically typed language, (5+4) _could_ be the tuple if the expression
is used in a typing context that makes that determinable. An example would
be

list((5+4))

as the list constructor needs a iterable to work, so it would be declared
like this:

list _ : [ iterable[alpha] ] -> list[alpha]

But then you'd have to forbid overloading of operators, or someone could
declare a list like this:

list _ : [ num ] -> list[int]

to create lists of zeros of type int. Which would reintroduce the ambiguity
again.

And if the static typed language allows operator overloading, it could
very well be that someone creates a overloading for

<*> : [tuple[num], tuple[num]] -> <whatever>

which would reintroduce the ambiguity.

Soooooo, in the end it boils down to some explicitness - where IMHO an
additional comma is pretty much no problem at all. Another option would
of course be the introduction of different parentheses for tuples - but I
can't find some on my keyboard.

Well I can't find braille on my keyboard, but if I wanted to, it
wouldn't be difficult to get it on my screen. So is it with
different parentheses. That python can't use these parentheses
is again a design decision.

For someone who expresses his disliking to type _one_ comma in the few cases
of single element tuples in thousands of lines of code, it strikes me odd
that you'd go an are willing to add extra trouble entering _each_ and
_every_ tuple in your code by using some hitherto unknown character that
won't be enterable easily....

But you showed that strange sense of reasoning before - I remember you
wanting to shave off microseconds by optimising constant expressions like
5*4 whilst at the same time arguing in another thread that you'd like to
have mutable keys for dicts that needed copying the very same keys - at
much greater costs, per case and even more so in general as using dicts is
common where pure constant arithmetic expressions aren't.
 
D

Daniel Dittmar

Diez said:
And no way in mathematics or any other language either - if you want the
same function symbol on the same operators to have _different_ semantics,
you're getting pretty non-deterministic.
I think he meant that Python should have introduced different operators
for addition and sequence concatenation.
Your opinion is wrong. It's because you seem to not have understood the
example: The expression (5 + 4) could be understood as 9 or as (9,). In

It should be understood as 9, but if integers etc implement the sequence
protocol, 9 can be used just like a tuple
(http://www.livejournal.com/users/glyf/29038.html).

There have been other proposals where you could write 'for i in 5' etc.

I find this 'creative use of overloading' rather awful. But what the
heck, I find list comprehension rather awful.

Daniel
 
D

Diez B. Roggisch

I think he meant that Python should have introduced different operators
for addition and sequence concatenation.

I reread his example and have to admit I'm confused: He complains about
having written his _own_ vector class - and concatenation and addition had
to use both + ?

He could have used | for concatenation instead. Apart from the concatenation
IMHO not being a mathematical founded operation on vectors.

I maybe was confused of him using + as bad example and then extending that
to *. But even more so my point is valid: If you forbid the overloading of
operators, you have to come up with even _more_ operator names, like ocaml
has *. and * for multiplication of floats and ints. So you end up with way
more clutter in the source, certainly more than the occasional extra comma.
It should be understood as 9, but if integers etc implement the sequence
protocol, 9 can be used just like a tuple
(http://www.livejournal.com/users/glyf/29038.html).

The examples focus too much on numbers - if we use instead

("foo")

we would get a iterable yielding ["foo",] or - as string already supports
iteration - ['f', 'o', 'o']. Which one to chose?
There have been other proposals where you could write 'for i in 5' etc.

I find this 'creative use of overloading' rather awful. But what the
heck, I find list comprehension rather awful.

Well, the number of operators built into the language is limited - and I
actually prefer to have the possibility to overload these if I want to.
Nobody forces me - I could use

v1.concat(v2)

for two vectors v1, v2 if I wanted to.
 
J

Jeremy Bowers

OK, OK, I'll give up on the commas. Maybe we should just use dollar signs :?

No, using symbols like that is bad. Clearly we need a new parser constant,
THE_ZERO_LENGTH_EMPTY_TUPLE.

We will, of course, have to forbid assigning any other name to that
constant (more language changes) so that people don't start creating their
own inconsistent name... *especially* shorter ones.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,754
Messages
2,569,525
Members
44,997
Latest member
mileyka

Latest Threads

Top