Re: Some syntactic sugar proposals

2010-12-02 Thread Tim Chase

On 12/02/2010 10:39 AM, Mark Dickinson wrote:

On Nov 15, 12:46 pm, Tim Chase  wrote:

On 11/15/2010 12:39 AM, Dmitry Groshev wrote:


x in range optimisation


I've often thought this would make a nice O(1)-test lookup on an
xrange() generator.


An O(1) test for 'x in' is implemented in Python 3.2,
at least provided that x has type 'int', 'long' or 'bool'.  (If x is
an instance of a subclass of int or long, then there's a risk that the
semantics of the membership test have been changed by an explicitly
overridden __eq__, so Python wimps out and falls back to the O(n)
algorithm in that case.)


Drat, bested again by the python time-machine.  Thanks for 
bringing that to my attention.


-tkc



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


Re: Some syntactic sugar proposals

2010-12-02 Thread Mark Dickinson
On Nov 15, 12:46 pm, Tim Chase  wrote:
> On 11/15/2010 12:39 AM, Dmitry Groshev wrote:
>
> > x in range optimisation
>
> I've often thought this would make a nice O(1)-test lookup on an
> xrange() generator.

An O(1) test for 'x in ' is implemented in Python 3.2,
at least provided that x has type 'int', 'long' or 'bool'.  (If x is
an instance of a subclass of int or long, then there's a risk that the
semantics of the membership test have been changed by an explicitly
overridden __eq__, so Python wimps out and falls back to the O(n)
algorithm in that case.)

Python 3.2a4+ (py3k:86635:86636M, Nov 21 2010, 19:22:18)
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> -1 in range(10**9)
False
>>> 5 in range(0, 10**100, 2)
False
>>> 10**99 in range(0, 10**100, 2)
True

IIRC, there wasn't sufficient interest to get it backported to Python
2.7 in time for its release.  Though as a pure optimization, one could
argue that it would still be possible to get this into Python 2.7.2.

Mark
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-12-01 Thread Steven D'Aprano
On Wed, 01 Dec 2010 15:18:32 -0800, Dmitry Groshev wrote:

> Here is a fresh example of what I meant by my first proposal. You need
> to build a matrix like this:
> 2 1 0 ...
> 1 2 1 ...
> 0 1 2 ...
> ...
> ... 1 2 1
> ... 0 1 2
> You could do this by one-liner:
> [[(2 - abs(x - y)) if it > 0 else 0 for x in xrange(8)] for y in
> xrange(8)]
> ...but in reality you should write something like this: [[(lambda t: t
> if t > 0 else 0)(2 - abs(x - y)) for x in xrange(8)] for y in xrange(8)]
> or this
> [[(2 - abs(x - y)) if (2 - abs(x - y)) > 0 else 0 for x in xrange(8)]
> for y in xrange(8)]
> or even this
> def foo(x, y):
> if abs(x - y) == 0:
> return 2
> elif abs(x - y) == 1:
> return 1
> else:
> return 0
> [[foo(x, y) for x in xrange(8)] for y in xrange(8)]


All those one-liners give me a headache. At least your "foo" solution is 
understandable.

But I'd do it like this:

>>> array = [[0]*8 for _ in range(8)]
>>> for i in range(8):
... array[i][i] = 2
... if i > 0: array[i][i-1] = 1
... if i < 7: array[i][i+1] = 1
...
>>> pprint.pprint(array)
[[2, 1, 0, 0, 0, 0, 0, 0],
 [1, 2, 1, 0, 0, 0, 0, 0],
 [0, 1, 2, 1, 0, 0, 0, 0],
 [0, 0, 1, 2, 1, 0, 0, 0],
 [0, 0, 0, 1, 2, 1, 0, 0],
 [0, 0, 0, 0, 1, 2, 1, 0],
 [0, 0, 0, 0, 0, 1, 2, 1],
 [0, 0, 0, 0, 0, 0, 1, 2]]



When you stop trying to make everything a one-liner, it's amazing how 
readable you can make code :)



-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-12-01 Thread Dmitry Groshev
On Nov 22, 2:21 pm, Andreas Löscher  wrote:
> >     if x in range(a, b): #wrong!
> > it feels so natural to check it that way, but we have to write
> >     if a <= x <= b
> > I understand that it's not a big deal, but it would be awesome to have
> > some optimisations - it's clearly possible to detect things like that
> > "wrong" one and fix it in a bytecode.
>
> You can implement it yourself:
>
> class between(object):
>         def __init__(self, a,b):
>                 super(crang, self).__init__()
>                 self.a=a
>                 self.b=b
>         def __contains__(self, value):
>                 return self.a <= value <= self.b
>
> >>> 12.45 in between(-100,100)
>
> true
>
> But do you need
>
> a <  x <  b
> a <= x <  b
> a <= x <= b or
> a <  x <= b ?
>
> Sure, you could set a new parameter for this, but the normal way is not
> broken at all.
>
> Best

Of course there are better ways to do this. Your "between", standart
comparisons and so, but expressing this as "i in range(a, b)" is just
intuitive and declarative.
Here is a fresh example of what I meant by my first proposal. You need
to build a matrix like this:
2 1 0 ...
1 2 1 ...
0 1 2 ...
...
... 1 2 1
... 0 1 2
You could do this by one-liner:
[[(2 - abs(x - y)) if it > 0 else 0 for x in xrange(8)] for y in
xrange(8)]
...but in reality you should write something like this:
[[(lambda t: t if t > 0 else 0)(2 - abs(x - y)) for x in xrange(8)]
for y in xrange(8)]
or this
[[(2 - abs(x - y)) if (2 - abs(x - y)) > 0 else 0 for x in xrange(8)]
for y in xrange(8)]
or even this
def foo(x, y):
if abs(x - y) == 0:
return 2
elif abs(x - y) == 1:
return 1
else:
return 0
[[foo(x, y) for x in xrange(8)] for y in xrange(8)]
It's not THAT matter, but it's just about readability and shortness in
some cases.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-22 Thread Andreas Löscher
> if x in range(a, b): #wrong!
> it feels so natural to check it that way, but we have to write
> if a <= x <= b
> I understand that it's not a big deal, but it would be awesome to have
> some optimisations - it's clearly possible to detect things like that
> "wrong" one and fix it in a bytecode.


You can implement it yourself:

class between(object):
def __init__(self, a,b):
super(crang, self).__init__()
self.a=a
self.b=b
def __contains__(self, value):
return self.a <= value <= self.b

>>> 12.45 in between(-100,100)
true


But do you need

a <  x <  b
a <= x <  b
a <= x <= b or
a <  x <= b ?

Sure, you could set a new parameter for this, but the normal way is not
broken at all.

Best


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


Re: Some syntactic sugar proposals

2010-11-18 Thread Mark Wooding
Steven D'Aprano  writes:

> >> Not everything needs to be a one liner. If you need this, do it the
> >> old- fashioned way:
> >>
> >> t = foo()
> >> if not pred(t): t = default_value
> > 
> > I already explained how to write it as a one-liner:
> > 
> > t = (lambda y: y if pred(y) else default_value)(foo())
>
> I didn't say it couldn't be written as a one-liner. I suggested that it 
> was better not to.

Ahh.  I misunderstood the first sentence above as dismissing the
possibility.  Sorry.  I agree that it's not a /nice/ one-liner. ;-)

> The costs of the one-liner are:
>
> * reduced readability;
> * requires an increased level of knowledge of the reader ("what's lambda 
> do?");
> * runtime inefficiency (you create a function object, only to use it once 
> then throw it away).

This last can be obviated by a clever compiler (which, in our case, we
have not got).  The second could be considered an advantage: it's
educational!

> The advantages?
>
> * one fewer line of code.
>
> In my experience, the obsessiveness in which some people look for one-
> liners is far from helpful, and goes against the spirit of Python. This 
> isn't Perl :)

Oh, I agree completely.  On the other hand, it's just /fun/.  Python is
a fun language and using its features in playfully unusual ways is
enjoyable; like a good pun in a natural language.  Just as puns aren't
always appropriate in written language, playful code isn't always
appropriate either; but that doesn't mean it's never appropriate.

(Java has no sense of humour.  C++ does have, but it's a bit weird.)

-- [mdw]
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-18 Thread Steven D'Aprano
On Thu, 18 Nov 2010 09:32:23 +, Mark Wooding wrote:

[...]
> You're wrong.  Python evaluates these left-to-right, as I said.
> Parentheses override operator associativity; they don't affect
> evaluation order at all.

Fair enough. I concede your point.


[...]
>> Not everything needs to be a one liner. If you need this, do it the
>> old- fashioned way:
>>
>> t = foo()
>> if not pred(t): t = default_value
> 
> I already explained how to write it as a one-liner:
> 
> t = (lambda y: y if pred(y) else default_value)(foo())


I didn't say it couldn't be written as a one-liner. I suggested that it 
was better not to.

The costs of the one-liner are:

* reduced readability;
* requires an increased level of knowledge of the reader ("what's lambda 
do?");
* runtime inefficiency (you create a function object, only to use it once 
then throw it away).

The advantages?

* one fewer line of code.

In my experience, the obsessiveness in which some people look for one-
liners is far from helpful, and goes against the spirit of Python. This 
isn't Perl :)


-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-18 Thread Mark Wooding
Steven D'Aprano  writes:

> On Wed, 17 Nov 2010 16:31:40 +, Mark Wooding wrote:
>
> > But I don't think that's the big problem with this proposal.  The real
> > problem is that it completely changes the evaluation rule for the
> > conditional expression.  (The evaluation rule is already pretty screwy:
> > Python is consistently left-to-right -- except here.)
>
> Not quite...
>
> >>> 1+2*3
> 7
> >>> (1+2)*3
> 9

You're wrong.  Python evaluates these left-to-right, as I said.
Parentheses override operator associativity; they don't affect
evaluation order at all.

Consider:

def say(x):
  print 'seen %s' % x
  return x

print say(1) + say(2) * say(3)
print (say(1) + say(2)) * say(3)

Run this program and you get

seen 1
seen 2
seen 3
7
seen 1
seen 2
seen 3
9

So definitely left-to-right.  Translating into reverse-Polish, say with
Dijkstra's shunting-yard algorithm, is enlightening: you get

1 2 3 * +

for the first and

1 2 + 3 *

for the second.  This preserves evaluation order; indeed, this is a
general property of the shunting-yard algorithm.

Finally, I quote from the language reference (5.13 of the 2.5 version),
just to show that (this time, at least) I'm not trying to impose
unfamiliar terminology, and that Python is defined to behave like this
and I'm not relying on implementation-specific details.  Alas, it also
highlights a genuine inconsistency, but one which might be considered
tolerable.

: 5.13 Evaluation order
: =
: 
: Python evaluates expressions from left to right. Notice that while
: evaluating an assignment, the right-hand side is evaluated before the
: left-hand side.
: 
: In the following lines, expressions will be evaluated in the
: arithmetic order of their suffixes:
: 
:  expr1, expr2, expr3, expr4
:  (expr1, expr2, expr3, expr4)
:  {expr1: expr2, expr3: expr4}
:  expr1 + expr2 * (expr3 - expr4)
:  func(expr1, expr2, *expr3, **expr4)
:  expr3, expr4 = expr1, expr2

So the above example is /explicitly/ dealt with in the language
reference, if only you'd cared to look.

> Not everything needs to be a one liner. If you need this, do it the old-
> fashioned way:
>
> t = foo()
> if not pred(t): t = default_value

I already explained how to write it as a one-liner:

t = (lambda y: y if pred(y) else default_value)(foo())

-- [mdw]
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-17 Thread Steven D'Aprano
On Wed, 17 Nov 2010 16:31:40 +, Mark Wooding wrote:

> But I don't think that's the big problem with this proposal.  The real
> problem is that it completely changes the evaluation rule for the
> conditional expression.  (The evaluation rule is already pretty screwy:
> Python is consistently left-to-right -- except here.)

Not quite...

>>> 1+2*3
7
>>> (1+2)*3
9

But other than that, I agree with your analysis for why Python should not 
be changed to allow:

t = foo() as v if pred(v) else default_value


Not everything needs to be a one liner. If you need this, do it the old-
fashioned way:

t = foo()
if not pred(t): t = default_value


-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-17 Thread Mark Wooding
Christopher  writes:

> i don't like magic names. what about:
>
> t = foo() as v if pred(v) else default_value

This is an improvement on `it'; anaphorics are useful in their place,
but they don't seem to fit well with Python.

But I don't think that's the big problem with this proposal.  The real
problem is that it completely changes the evaluation rule for the
conditional expression.  (The evaluation rule is already pretty screwy:
Python is consistently left-to-right -- except here.)

Evaluating a conditional expression starts in the middle, by evaluating
the condition.  If the condition is true, then it evaluates the
consequent (to the left); otherwise it evaluates the alternative (to the
right).  Screwy, but tolerable.

The proposal is to evaluate the /consequent/, stash it somewhere,
evaluate the condition, and then either output the consequent which we
evaluated earlier or the alternative which we must evaluate now.

Of course, the implementation must be able to tell which of these
evaluation rules to apply.  The marker to look for is either `it'
(original anaphoric proposal -- this is the real reason why `it' should
be a reserved word: its presence radically alters the evaluation rule,
so it ought to be a clear syntactic marker) or `as' (as suggested
above).

Elsewhere in the language, `as' is pretty consistent in what it does:
it provides a name for a thing described elsewhere (a `with' context
object, or an imported thing) -- but nothing else.  It certainly doesn't
suggest a change in the way anything else is evaluated.

1/x if x != 0 else None

works for any numeric x; it'd be really surprising to me if

1/x as hunoz if x != 0 else None

didn't.

-1 on this one.

-- [mdw]
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-17 Thread Andreas Waldenburger
On Wed, 17 Nov 2010 10:18:51 -0500 Mel  wrote:

> Christopher wrote:
> 
> >> ? Of course we can write it as
> >> t = foo() if pred(foo()) else default_value
> >> but here we have 2 foo() calls instead of one. Why can't we write
> >> just something like this:
> >> t = foo() if pred(it) else default_value
> >> where "it" means "foo() value"?
> > 
> > i don't like magic names. what about:
> > 
> > t = foo() as v if pred(v) else default_value
> 
> !!  so: assignment inside an expression.
> 
I like the idea of having an "as ... if" construct, though. :)

/W

-- 
To reach me via email, replace INVALID with the country code of my home 
country.  But if you spam me, I'll be one sour Kraut.

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


Re: Some syntactic sugar proposals

2010-11-17 Thread Mel
Christopher wrote:

>> ? Of course we can write it as
>> t = foo() if pred(foo()) else default_value
>> but here we have 2 foo() calls instead of one. Why can't we write just
>> something like this:
>> t = foo() if pred(it) else default_value
>> where "it" means "foo() value"?
> 
> i don't like magic names. what about:
> 
> t = foo() as v if pred(v) else default_value

!!  so: assignment inside an expression.

Mel.

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


Re: Some syntactic sugar proposals

2010-11-17 Thread Christopher
> ? Of course we can write it as
>     t = foo() if pred(foo()) else default_value
> but here we have 2 foo() calls instead of one. Why can't we write just
> something like this:
>     t = foo() if pred(it) else default_value
> where "it" means "foo() value"?

i don't like magic names. what about:

t = foo() as v if pred(v) else default_value


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


Re: Some syntactic sugar proposals

2010-11-16 Thread John Ladasky
On Nov 14, 11:30 pm, alex23  wrote:
> On Nov 15, 4:39 pm, Dmitry Groshev  wrote:
>
> >     if x in range(a, b): #wrong!
>
> Only in Python 3.x, it's perfectly valid in Python 2.x. To achieve the
> same in Python 3.x, try:
>
>     if x in list(range(a, b,)): # BUT SEE MY COMMENT BELOW
>
> > it feels so natural to check it that way, but we have to write
> >     if a <= x <= b
> > I understand that it's not a big deal, but it would be awesome to have
> > some optimisations - it's clearly possible to detect things like that
> > "wrong" one and fix it in a bytecode.
>
> This seems more like a pessimisation to me: your range version
> constructs a list just to do a single container check. That's a _lot_
> more cumbersome than two simple comparisons chained together.

Also: testing for the membership of x in a set is NOT the same thing
as testing using inequality operators.  The inequality operators will
return True for any FLOATING-POINT value within the range (a...b), but
the set test will only return True for set members.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-16 Thread André
On Nov 15, 2:39 am, Dmitry Groshev  wrote:
> Here are some proposals. They are quite useful at my opinion and I'm
> interested for suggestions. It's all about some common patterns.
> First of all: how many times do you write something like
>     t = foo()
>     t = t if pred(t) else default_value

Never!

[snip]

> And the third. The more I use python the more I see how "natural" it
> can be. By "natural" I mean the statements like this:
>     [x.strip() for x in reversed(foo)]
> which looks almost like a natural language. But there is some
> pitfalls:
>     if x in range(a, b): #wrong!

This is true only if x is an integer such that  a <= x < b

> it feels so natural to check it that way, but we have to write
>     if a <= x <= b

This is true if x is an integer OR a float.   Two very different
cases, deserving of different notation.

André


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


Re: Some syntactic sugar proposals

2010-11-16 Thread Ian Kelly

On 11/16/2010 3:42 AM, Steven D'Aprano wrote:

On Mon, 15 Nov 2010 22:40:00 -0700, Ian Kelly wrote:


On 11/15/2010 10:26 PM, Steven D'Aprano wrote:

t = foo()+bar()+baz() if pred(it) else baz()-foo()-bar()

What does "it" mean here?


"it" would mean the result of the expression foo()+bar()+baz().  What
else could it mean?


It could mean the last expression, baz(). Or the entire compound
expression, foo()+bar()+baz().


Unless the precedence rules were to change, the three expressions in the 
example that are operated on by the ternary are these:


1. foo()+bar()+baz()
2. pred(it)
3. baz()-foo()-bar()

So the antecedent would have to be one of those in order to make any 
sense at all, and obviously the only choice of those that would be 
useful is the first one.



There are valid objections to the proposal, but the
intended semantics seem perfectly clear.


Fair point, my example was terrible and didn't show the point that was
clear in my head. Mea culpa. How about this instead?

t = foo()+it if pred(it) else bar()

Should that be a SyntaxError, or is `it` a variable that holds its value
from statement to statement?


SyntaxError.  Implementing this without making 'it' a keyword would be 
very sloppy, IMO.


Another option would be to use a special variable named '__', similar to 
the variable '_' that the REPL uses to store the result of the last 
command.  This might break some existing code, but probably not very 
much.  Mostly it would just be confusing.



t = (foo() if pred(it) else bar()) if cond(it) else baz()


More problematic:

t = foo() if pred(bar() if pred2(it) else str(it)) else bar()

Does the first 'it' belong to the inner or outer ternary?  Probably the 
inner one.  What about the second 'it'?



BTW, I frequently use "it" for iterators, and making "it" a reserved word
would break a lot of my code. This would make me quite peeved.


I do the same, and yes, it would make upgrading a real pain.

Cheers,
Ian

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


Re: Some syntactic sugar proposals

2010-11-16 Thread Steven D'Aprano
On Mon, 15 Nov 2010 22:40:00 -0700, Ian Kelly wrote:

> On 11/15/2010 10:26 PM, Steven D'Aprano wrote:
>> t = foo()+bar()+baz() if pred(it) else baz()-foo()-bar()
>>
>> What does "it" mean here?
> 
> "it" would mean the result of the expression foo()+bar()+baz().  What
> else could it mean?

It could mean the last expression, baz(). Or the entire compound 
expression, foo()+bar()+baz().


> There are valid objections to the proposal, but the
> intended semantics seem perfectly clear.

Fair point, my example was terrible and didn't show the point that was 
clear in my head. Mea culpa. How about this instead?

t = foo()+it if pred(it) else bar()

Should that be a SyntaxError, or is `it` a variable that holds its value 
from statement to statement?

t = it

t = (foo() if pred(it) else bar()) if cond(it) else baz()


For what it's worth, Apple's defunct Hypertalk language had a couple of 
syntax elements very much like that. Hypertalk had a special variable, 
"it", which you used like this:

get the number of cards
put it into field "Card number"

I trust I don't have to explain this? :)

Hypertalk also had a special function, "the result", which worked 
something like this:

ask "This is a dialog box. Please type your answer here:"
put the result into field "Your answer"

(or you could use "result()" instead). Both of these worked quite well 
with Hypertalk, particularly with it's focus on non-programmers, but they 
were designed into the language from the beginning. In Python they would 
be the proverbial round peg in a square hole.

BTW, I frequently use "it" for iterators, and making "it" a reserved word 
would break a lot of my code. This would make me quite peeved.



-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-15 Thread Ian Kelly

On 11/15/2010 10:26 PM, Steven D'Aprano wrote:

t = foo()+bar()+baz() if pred(it) else baz()-foo()-bar()

What does "it" mean here?


"it" would mean the result of the expression foo()+bar()+baz().  What 
else could it mean?  There are valid objections to the proposal, but the 
intended semantics seem perfectly clear.


Cheers,
Ian

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


Re: Some syntactic sugar proposals

2010-11-15 Thread Steven D'Aprano
On Sun, 14 Nov 2010 22:39:05 -0800, Dmitry Groshev wrote:

> Here are some proposals. They are quite useful at my opinion and I'm
> interested for suggestions. It's all about some common patterns. First
> of all: how many times do you write something like
> t = foo()
> t = t if pred(t) else default_value
> ? 

Hardly ever. Not often enough to need special syntax for it.


Of course we can write it as
> t = foo() if pred(foo()) else default_value
> but here we have 2 foo() calls instead of one. Why can't we write just
> something like this:
> t = foo() if pred(it) else default_value
> where "it" means "foo() value"?


t = foo()+bar()+baz() if pred(it) else baz()-foo()-bar()

What does "it" mean here?



> Second, I saw a lot of questions about using dot notation for a
> "object-like" dictionaries and a lot of solutions like this:
> class dotdict(dict):
> def __getattr__(self, attr):
> return self.get(attr, None)
> __setattr__= dict.__setitem__
> __delattr__= dict.__delitem__
> why there isn't something like this in a standart library?


Because dot notation for dictionaries is not something we should 
encourage.



> And the
> third. The more I use python the more I see how "natural" it can be. By
> "natural" I mean the statements like this:
> [x.strip() for x in reversed(foo)]
> which looks almost like a natural language. But there is some pitfalls:
> if x in range(a, b): #wrong!

Why do you say it's wrong? It's perfectly correct:

1 in range(1, 10)
=> returns True

1.5 in range(1, 10)
=> returns False

5 in range(1, 10)
=> returns True

10 in range(1, 10)
=> returns False

exactly as I expect for element testing in a half-open interval. So 
where's the problem? If you want interval testing, you need to perform an 
interval test, not an element test.


> it feels so natural to check it that way, but we have to write
> if a <= x <= b
> I understand that it's not a big deal, but it would be awesome to have
> some optimisations - it's clearly possible to detect things like that
> "wrong" one and fix it in a bytecode.


If I write:

x in range(1, 10)

how do you expect the compiler to read my mind and know if I want the 
half-open interval or the closed interval?



-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-15 Thread John Nagle

On 11/14/2010 11:30 PM, alex23 wrote:

On Nov 15, 4:39 pm, Dmitry Groshev  wrote:

First of all: how many times do you write something like





Second, I saw a lot of questions about using dot notation for a
"object-like" dictionaries and a lot of solutions like this:
 class dotdict(dict):
 def __getattr__(self, attr):
 return self.get(attr, None)
 __setattr__= dict.__setitem__
 __delattr__= dict.__delitem__
why there isn't something like this in a standart library?


Personally, I like keeping object attribute references separate from
dictionary item references.


Right.  This isn't JavaScript.  If you need a "dict", use a
"dict".  Don't use attributes as named storage. It leads to
problems.  Functions and various built-in objects are in the
attribute namespace, and this can lead to name clashes.
Maybe security holes, if the attribute keys come from
external input.  There are also some restrictions on
the syntax of attribute names, restrictions "dict"
does not have.

Remember, you can inherit from "dict", which
allows you to write

obj['abc']

which is almost as short as

obj.abc

but safer.

John Nagle
--
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-15 Thread Brian Blais
On Nov 15, 2010, at 1:39 AM, Dmitry Groshev wrote:

>if x in range(a, b): #wrong!
> it feels so natural to check it that way, but we have to write
>if a <= x <= b
> I understand that it's not a big deal, but it would be awesome to have
> some optimisations - it's clearly possible to detect things like that
> "wrong" one and fix it in a bytecode.

I don't think anyone has pointed this out, but these are *not* the same thing.  
observe:


x=3
if x in range(1,10):
print "yay!"

if 1<=x<10:
print "yay too!"

x=3.2
if x in range(1,10):
print "yay!"

if 1<=x<10:
print "yay too!"

output:

yay!
yay too!
yay too!


bb
-- 
Brian Blais
bbl...@bryant.edu
http://web.bryant.edu/~bblais
http://bblais.blogspot.com/



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


Re: Some syntactic sugar proposals

2010-11-15 Thread Terry Reedy

On 11/15/2010 1:39 AM, Dmitry Groshev wrote:

Here are some proposals. They are quite useful at my opinion and I'm
interested for suggestions. It's all about some common patterns.
First of all: how many times do you write something like
 t = foo()
 t = t if pred(t) else default_value


Never. t=t unbinds and rebinds 't' to the same object. A waste.
Only rebind if needed.
if not pred(t): t = default_value


? Of course we can write it as
 t = foo() if pred(foo()) else default_value
but here we have 2 foo() calls instead of one. Why can't we write just
something like this:
 t = foo() if pred(it) else default_value
where "it" means "foo() value"?


Too magical.

I agree with most other comments.

--
Terry Jan Reedy

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


Re: Some syntactic sugar proposals

2010-11-15 Thread Tim Chase

On 11/15/2010 12:39 AM, Dmitry Groshev wrote:

x in range optimisation


I've often thought this would make a nice O(1)-test lookup on an 
xrange() generator.  I don't have strong use-cases for it, but a 
bit of well-tested code in the standard library would save me 
from doing the math (along with its potential fenceposting and 
sign errors) the couple times I've reached for it.  Using the


  x in list(xrange(...)) # or "range()" depending your version

ends up with an O(n) lookup, though I suppose one could create a 
set() for O(1) lookups, but that still requires O(N) storage 
(where a mathematical lookup would involve O(1) storage *and* time)



foo() if foo() else bar()


This is usually indicative that you need to cache the 
object...something like


  etcc = expensive_to_calculate_constructor()
  result = foo(etcc) if test(etcc) else bar()

That way, you cache the potentially-expensive calculation, 
indicate to other readers-of-your-code that it's 
potentially-expensive, and enforce the use of that cache to 
ensure that you don't duplicate the expensive op.


-tkc






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


Re: Some syntactic sugar proposals

2010-11-15 Thread Mark Wooding
Dmitry Groshev  writes:

> First of all: how many times do you write something like
> t = foo()
> t = t if pred(t) else default_value
> ? Of course we can write it as
> t = foo() if pred(foo()) else default_value
> but here we have 2 foo() calls instead of one. Why can't we write just
> something like this:
> t = foo() if pred(it) else default_value
> where "it" means "foo() value"?

How about

t = (lambda y: y if pred(y) else default_value)(foo(x))

You could even package the lambda into a named function if you get bored
of typing or your aesthetic senses are offended.

> And the third. The more I use python the more I see how "natural" it
> can be. By "natural" I mean the statements like this:
> [x.strip() for x in reversed(foo)]
> which looks almost like a natural language. But there is some
> pitfalls:
> if x in range(a, b): #wrong!
> it feels so natural to check it that way, but we have to write
> if a <= x <= b

This, I think, is your error.  The test `x in range(a, b)' means the
same as `a <= x < b' (only in Python 2 it builds a list and then throws
it away again).  Such half-open intervals turn out to be what you want
most of the time, and I think you'll avoid many bugs if you embrace them
rather than trying to cling to the fully-closed intervals above.

Python very definitely made the right decision to use half-open
intervals pervasively, e.g., for `rangeand 'in sequence slicing.  It's a
bad idea to fight against it.

Advantages of half-open intervals [a, b):

  * The number of elements is exactly b - a; closed intervals contain an
extra element which is often forgotten.

  * They compose and split nicely: if a <= c <= b then [a, b) is exactly
the disjoint union of [a, c) and [c, b).

  * Sums over these intervals are often better behaved; indeed, there's
a rather pretty analogy between sums on half-open intervals and
definite integrals which is lost if you use closed intervals.  (The
above two observations are special cases of this one.)  See Concrete
Mathematics (Graham, Knuth, Patashnik) for more on this.

  * It's easy to express an empty interval.  You can't do that if you
work entirely with closed intervals, but empty sets are an important
boundary case and it's annoying to have to handle them separately.

-- [mdw]
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-15 Thread Hrvoje Niksic
Dmitry Groshev  writes:

> which looks almost like a natural language. But there is some
> pitfalls:
> if x in range(a, b): #wrong!
> it feels so natural to check it that way, but we have to write
> if a <= x <= b

For the record, you have to write:

if a <= x < b:

Ranges are open on the ending side.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-15 Thread Dmitry Groshev
On Nov 15, 12:03 pm, alex23  wrote:
> On Nov 15, 5:50 pm, Dmitry Groshev  wrote:
>
> > On Nov 15, 10:30 am, alex23  wrote:
> > > Personally, I like keeping object attribute references separate from
> > > dictionary item references.
>
> > Your Python doesn't - dot notation is just a sugar for __dict__ lookup
> > with default metaclass.
>
> That's a gross oversimplification that tends towards wrong:
>
> >>> class C(object):
>
> ...   def __init__(self):
> ...     self._x = None
> ...   @property
> ...   def x(self): return self._x
> ...   @x.setter
> ...   def x(self, val): self._x = val
> ...>>> c = C()
> >>> c.x = 1
> >>> c.x
> 1
> >>> c.__dict__['x']
>
> Traceback (most recent call last):
>   File "", line 1, in 
> KeyError: 'x'
>
> But my concern has _nothing_ to do with the implementation detail of
> how objects hold attributes, it's solely over the clarity that comes
> from being able to visually tell that something is an object vs a
> dictionary.

Oh, now I understand you. But this "dotdict" (or "bunch") things don't
break anything. You still need to use it explicitly and it is very
useful if you need to serialize some JSON data about some entities.
s = """[{"name": "Jhon Doe", "age": "12"}, {"name": "Alice",
"age": "23"}]"""
t = map(dotdict, json.loads(s))
t[0] #{'age': '12', 'name': 'Jhon Doe'}
t[0].age #'12'
Of course you can do this with namedtuple, but in fact this isn't a
tuple at all. It's a list of entities.

> > > This seems more like a pessimisation to me: your range version
> > > constructs a list just to do a single container check. That's a _lot_
> > > more cumbersome than two simple comparisons chained together.
>
> > By "wrong" I meant exactly this. I told about "compiler" optimisation
> > of statements like this so it would not construct a list.
>
> So you want this:
>
>   if x in range(1,10):
>
> ...to effectively emit the same bytecode as a chained comparison while
> this:
>
>   for x in range(1,10):
>
> ...produces a list/generator?
>
> Never going to happen. "Special cases aren't special enough to break
> the rules." The standard form for chained comparisons can handle far
> more complex expressions which your 'in' version could not: 0 <= min
> <= max <= 100

I know about chained comparisons, thanks. It's not about them. It's
about bytecode optimisation. But maybe you are right about "Special
cases aren't special enough to break the rules". I kinda forgot that :)
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-15 Thread alex23
On Nov 15, 5:50 pm, Dmitry Groshev  wrote:
> On Nov 15, 10:30 am, alex23  wrote:
> > Personally, I like keeping object attribute references separate from
> > dictionary item references.
>
> Your Python doesn't - dot notation is just a sugar for __dict__ lookup
> with default metaclass.

That's a gross oversimplification that tends towards wrong:

>>> class C(object):
...   def __init__(self):
... self._x = None
...   @property
...   def x(self): return self._x
...   @x.setter
...   def x(self, val): self._x = val
...
>>> c = C()
>>> c.x = 1
>>> c.x
1
>>> c.__dict__['x']
Traceback (most recent call last):
  File "", line 1, in 
KeyError: 'x'

But my concern has _nothing_ to do with the implementation detail of
how objects hold attributes, it's solely over the clarity that comes
from being able to visually tell that something is an object vs a
dictionary.

> > This seems more like a pessimisation to me: your range version
> > constructs a list just to do a single container check. That's a _lot_
> > more cumbersome than two simple comparisons chained together.
>
> By "wrong" I meant exactly this. I told about "compiler" optimisation
> of statements like this so it would not construct a list.

So you want this:

  if x in range(1,10):

...to effectively emit the same bytecode as a chained comparison while
this:

  for x in range(1,10):

...produces a list/generator?

Never going to happen. "Special cases aren't special enough to break
the rules." The standard form for chained comparisons can handle far
more complex expressions which your 'in' version could not: 0 <= min
<= max <= 100
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-14 Thread Dmitry Groshev
On Nov 15, 10:30 am, alex23  wrote:
> On Nov 15, 4:39 pm, Dmitry Groshev  wrote:
>
> > First of all: how many times do you write something like
> >     t = foo()
> >     t = t if pred(t) else default_value
> > ? Of course we can write it as
> >     t = foo() if pred(foo()) else default_value
> > but here we have 2 foo() calls instead of one. Why can't we write just
> > something like this:
> >     t = foo() if pred(it) else default_value
> > where "it" means "foo() value"?
>
> Could you provide an actual use case for this. This seems weird to me:
> you're creating an object, testing the object, then possibly throwing
> it away and using a default instead. Are you sure you can't
> restructure your code as such:
>
>    t = foo(x) if  else default

Sure. Let's pretend you have some string foo and compiled regular
expression bar.
Naive code:
t = bar.findall(foo)
if len(t) < 3:
t = []
Code with proposed syntactic sugar:
t = bar.findall(foo) if len(it) > 2 else []

> > Second, I saw a lot of questions about using dot notation for a
> > "object-like" dictionaries and a lot of solutions like this:
> >     class dotdict(dict):
> >         def __getattr__(self, attr):
> >             return self.get(attr, None)
> >         __setattr__= dict.__setitem__
> >         __delattr__= dict.__delitem__
> > why there isn't something like this in a standart library?
>
> Personally, I like keeping object attribute references separate from
> dictionary item references.
Your Python doesn't - dot notation is just a sugar for __dict__ lookup
with default metaclass.

> This seems more like a pessimisation to me: your range version
> constructs a list just to do a single container check. That's a _lot_
> more cumbersome than two simple comparisons chained together.
By "wrong" I meant exactly this. I told about "compiler" optimisation
of statements like this so it would not construct a list.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-14 Thread alex23
On Nov 15, 5:30 pm, alex23  wrote:
>    t = foo(x) if  else default

This should read 'test' instead of 'text', sorry.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-14 Thread alex23
On Nov 15, 4:39 pm, Dmitry Groshev  wrote:
> First of all: how many times do you write something like
>     t = foo()
>     t = t if pred(t) else default_value
> ? Of course we can write it as
>     t = foo() if pred(foo()) else default_value
> but here we have 2 foo() calls instead of one. Why can't we write just
> something like this:
>     t = foo() if pred(it) else default_value
> where "it" means "foo() value"?

Could you provide an actual use case for this. This seems weird to me:
you're creating an object, testing the object, then possibly throwing
it away and using a default instead. Are you sure you can't
restructure your code as such:

   t = foo(x) if  else default

> Second, I saw a lot of questions about using dot notation for a
> "object-like" dictionaries and a lot of solutions like this:
>     class dotdict(dict):
>         def __getattr__(self, attr):
>             return self.get(attr, None)
>         __setattr__= dict.__setitem__
>         __delattr__= dict.__delitem__
> why there isn't something like this in a standart library?

Personally, I like keeping object attribute references separate from
dictionary item references. If you're someone who doesn't mind
muddying that distinction, then - as you've discovered - it's a simple
addition to your own code.

>     if x in range(a, b): #wrong!

Only in Python 3.x, it's perfectly valid in Python 2.x. To achieve the
same in Python 3.x, try:

if x in list(range(a, b,)): # BUT SEE MY COMMENT BELOW
> it feels so natural to check it that way, but we have to write
>     if a <= x <= b
> I understand that it's not a big deal, but it would be awesome to have
> some optimisations - it's clearly possible to detect things like that
> "wrong" one and fix it in a bytecode.

This seems more like a pessimisation to me: your range version
constructs a list just to do a single container check. That's a _lot_
more cumbersome than two simple comparisons chained together.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-14 Thread Dmitry Groshev
On Nov 15, 9:48 am, Chris Rebert  wrote:
> On Sun, Nov 14, 2010 at 10:39 PM, Dmitry Groshev  
> wrote:
> > Here are some proposals. They are quite useful at my opinion and I'm
> > interested for suggestions. It's all about some common patterns.
> 
> > Second, I saw a lot of questions about using dot notation for a
> > "object-like" dictionaries and a lot of solutions like this:
> >    class dotdict(dict):
> >        def __getattr__(self, attr):
> >            return self.get(attr, None)
> >        __setattr__= dict.__setitem__
> >        __delattr__= dict.__delitem__
> > why there isn't something like this in a standart library?
>
> There 
> is:http://docs.python.org/library/collections.html#collections.namedtuple
>
> The "bunch" recipe is also fairly well-known; I suppose one could
> argue whether it's 
> std-lib-worthy:http://code.activestate.com/recipes/52308-the-simple-but-handy-collec...
>
> Cheers,
> Chris

namedtuple is not a "drop-in" replacement like this "dotdict" thing -
you first need to create a new namedtuple instance. As for me it's a
bit too complicated.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-14 Thread Chris Rebert
On Sun, Nov 14, 2010 at 10:39 PM, Dmitry Groshev  wrote:
> Here are some proposals. They are quite useful at my opinion and I'm
> interested for suggestions. It's all about some common patterns.

> Second, I saw a lot of questions about using dot notation for a
> "object-like" dictionaries and a lot of solutions like this:
>    class dotdict(dict):
>        def __getattr__(self, attr):
>            return self.get(attr, None)
>        __setattr__= dict.__setitem__
>        __delattr__= dict.__delitem__
> why there isn't something like this in a standart library?

There is:
http://docs.python.org/library/collections.html#collections.namedtuple

The "bunch" recipe is also fairly well-known; I suppose one could
argue whether it's std-lib-worthy:
http://code.activestate.com/recipes/52308-the-simple-but-handy-collector-of-a-bunch-of-named/

Cheers,
Chris
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Some syntactic sugar proposals

2010-11-14 Thread Dmitry Groshev
On Nov 15, 9:39 am, Dmitry Groshev  wrote:
> Here are some proposals. They are quite useful at my opinion and I'm
> interested for suggestions. It's all about some common patterns.
> First of all: how many times do you write something like
>     t = foo()
>     t = t if pred(t) else default_value
> ? Of course we can write it as
>     t = foo() if pred(foo()) else default_value
> but here we have 2 foo() calls instead of one. Why can't we write just
> something like this:
>     t = foo() if pred(it) else default_value
> where "it" means "foo() value"?
> Second, I saw a lot of questions about using dot notation for a
> "object-like" dictionaries and a lot of solutions like this:
>     class dotdict(dict):
>         def __getattr__(self, attr):
>             return self.get(attr, None)
>         __setattr__= dict.__setitem__
>         __delattr__= dict.__delitem__
> why there isn't something like this in a standart library?
> And the third. The more I use python the more I see how "natural" it
> can be. By "natural" I mean the statements like this:
>     [x.strip() for x in reversed(foo)]
> which looks almost like a natural language. But there is some
> pitfalls:
>     if x in range(a, b): #wrong!
> it feels so natural to check it that way, but we have to write
>     if a <= x <= b
> I understand that it's not a big deal, but it would be awesome to have
> some optimisations - it's clearly possible to detect things like that
> "wrong" one and fix it in a bytecode.
>
> x in range optimisation
> dot dict access
> foo() if foo() else bar()

Oh, I'm sorry. I forgot to delete my little notes at the bottom of
message.
-- 
http://mail.python.org/mailman/listinfo/python-list


Some syntactic sugar proposals

2010-11-14 Thread Dmitry Groshev
Here are some proposals. They are quite useful at my opinion and I'm
interested for suggestions. It's all about some common patterns.
First of all: how many times do you write something like
t = foo()
t = t if pred(t) else default_value
? Of course we can write it as
t = foo() if pred(foo()) else default_value
but here we have 2 foo() calls instead of one. Why can't we write just
something like this:
t = foo() if pred(it) else default_value
where "it" means "foo() value"?
Second, I saw a lot of questions about using dot notation for a
"object-like" dictionaries and a lot of solutions like this:
class dotdict(dict):
def __getattr__(self, attr):
return self.get(attr, None)
__setattr__= dict.__setitem__
__delattr__= dict.__delitem__
why there isn't something like this in a standart library?
And the third. The more I use python the more I see how "natural" it
can be. By "natural" I mean the statements like this:
[x.strip() for x in reversed(foo)]
which looks almost like a natural language. But there is some
pitfalls:
if x in range(a, b): #wrong!
it feels so natural to check it that way, but we have to write
if a <= x <= b
I understand that it's not a big deal, but it would be awesome to have
some optimisations - it's clearly possible to detect things like that
"wrong" one and fix it in a bytecode.

x in range optimisation
dot dict access
foo() if foo() else bar()
-- 
http://mail.python.org/mailman/listinfo/python-list