Re: [Python-Dev] concerns regarding callable() method

2007-04-08 Thread Andrew Koenig
 I have seen in PEP 3100 that callable() function is planned to be
 removed in Python 3000 with this replacement: just call the object
 and catch the exception???.  For one, the object (if it is
 callable) can raise exception itself, so you need to somehow to
 differentiate between exception raised inside its __call__ and
 exception raised if object is not callable to begin with.

I seem to recall bringing up the same issue a while ago; at the time, the
answer was that if you need it, you can write your own:

def callable(x):
return hasattr(x, '__call__')

My own preference would be for such queries to be defined abstractly as a
built-in part of the language, but apparently my preference is out of sync
with the community in this particular respect.



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] dict(keys, values)

2007-02-01 Thread Andrew Koenig
 Unfortunately
 
dict(keys=keys, values=values) == {keys: values}

Ummm, no:

dict(keys=keys, values=values) == {'keys': keys, 'values': values}



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] compex numbers (was Floor Division)

2007-01-23 Thread Andrew Koenig
 If real and imag are themselves complex numbers, then normalizing
 the result will move the imaginary portion of the real vector into
 the imaginary part and vice versa.

Not quite.

 complex(1,1j)
0j
 complex(0,1j)
(-1+0j)

So it moves the imaginary portion of the imag argument into the real part
of the result with change of sign, on the basis that 1j*1j == -1.



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 351 - do while

2006-10-01 Thread Andrew Koenig
 (I don't think this has been suggested yet.)
 
  while enter_condition, exit_condition:
 body

This usage makes me uneasy, not the least because I don't understand why the
comma isn't creating a tuple.  That is, why whould

while x, y:
body

be any different from

while (x,  y):
body

?

My other concern is that exit_condition is evaluated out of sequence.



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 351 - do while

2006-10-01 Thread Andrew Koenig
 This pattern:
 
   while entry_cond:
  ...
   and while not exit_cond:
  ...
 
 has been suggested before, and I believe that at least one of the times it
 was suggested, it had some support from Guido.  Essentially, the and
 while not exit is equivalent to an if exit: break that's more visible
 due to not being indented.

I like this suggestion.  In fact it is possible that at one time I suggested
something similar.

It reminds me of something that Dijkstra suggested in his 1971 book A
Discipline of Programming.  His ides looked somewhat like this:

do condition 1 - action 1

...

[] condition n - action n
od

Here, the [] should be thought of as a delimiter; it was typeset as a tall
narrow rectangle.

The semantics are as follows:

If all of the conditions are false, the statement does nothing.

Otherwise, the implementation picks one of the true conditions,
executes the corresponding action, and does it all again.

There is no guarantee about which action is executed if more than one of the
conditions is true.

The general idea, then, is that each action should falsify its corresponding
condition while bring the loop closer to termination; when all of the
conditions are false, the loop is done.

For example, he might write Euclid's algorithm this way:

do x  y - y := y mod x
[] y  x - x := x mod y
od

If we were to adopt while ... and while in Python, then Dijkstra's
construct could be rendered this way:

while x  y:
y %= x
or while y  x:
x %= y

I'm not suggesting this seriously as I don't have enough realistic use
cases.  Still, it's interesting to see that someone else has grappled with a
similar problem.



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Explicit Lexical Scoping (pre-PEP?)

2006-07-06 Thread Andrew Koenig
 However I still don't believe global has the stretchiness in its
 meaning that you claim it has. Have you ever heard a Python programmer
 talking about closures use the word global variable?

I guess the term I've heard most often is free variable, but I wouldn't be
surprised if I saw the term global used to describe a free variable.

However, I should point out that Dijkstra used global in a similar way in
his 1971 book A Discipline of Programming.  The program examples in that
book are in a language he devised for the purpose; one of the language's
features is that every variable used in every block must be explicitly
declared, even if it is taken from a surrounding block.  If I remember
correctly, the terms he used for variables taken from a surrounding block
and variables defined and used in the same block were global and
private, respectively.



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Explicit Lexical Scoping (pre-PEP?)

2006-07-04 Thread Andrew Koenig
 Borrowing from Perl, the keyword 'my' is used to declare an explicitly
 scoped variable:
 
 def f1():
my x = 1
def f2():
   x = 2   # Does not create a new x
 
 In the above example, the statement 'my x = 1' declares that the scope
 of the variable 'x' is the outer function f1. Any assignment to x will
 modify the existing x, rather than creating a new definition.

-1, for this reason:

def f()
x = 2   # Does this create a local variable?

Today, the answer is yes.  Under this proposal, you can't answer the
question without inspecting the entire context in which f is defined.

For that reason, I would much rather have the first assignment in a block
say explicitly whether it is intended to create a local variable:

def f1():
   x = 1
   def f2():
  global x
  x = 2# Does not create a new x

This might even be abbreviated:

def f1():
   x = 1
   def f2():
  global x = 2   # Equivalent to the last example above



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Lexical scoping in Python 3k

2006-07-03 Thread Andrew Koenig
 I don't think trivial is the right word to use here,
 since it implies something that's of so little importance
 that it can be ignored. But the simple cases are precisely
 the ones where this wart hurts the most, so we can't
 ignore them.

I'd like to inject an example that might help make this discussion more
concrete.

Consider the following function:

def for_each(seq, f):
for i in seq:
f(i)

I'm sure I've seen more than one instance of someone on comp.lang.python
trying to do the equivalent of using a function such as this one to compute
the sum of the elements of a sequence as follows:

def sum(seq):
result = 0
def accum(i):
result += i
for_each(seq, accum)
return result

and wonder why it doesn't work.  Still odder, why it doesn't work and the
following does:

def sum(seq):
result = [0]
def accum(i):
result[0] += i
for_each(seq, accum)
return result[0]

Transforming the first definition of sum above into the second may be
trivial, but only if you've encountered the technique before.  Moreover, the
first version of sum uses a technique that is more than 45 years old (!), as
it was available to Algol 60 programmers.


___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] 2.5 and beyond

2006-07-01 Thread Andrew Koenig

 a = []
 for i in range(10):
 a.append(lambda: i)
 print [x() for x in a]

 [9, 9, 9, 9, 9, 9, 9, 9, 9, 9]

Aha! -- Thank you for jogging my memory.

You seem to be right -- the problem is not that Python is lexically scoped,
but that when you define a variable with =, it leaks out into the
surrounding function scope.

Here's an example:

If True:
y = 123
print y

It may be obvious that this should print 123, but that's only because =
combines properties of assignment and definition.  In particular, if we were
to write

y = 42
if True:
y = 123
print y

it would be very surprising if this example were to print anything but 123.

Here is a corresponding fragment in C++:

int y = 42;
if (true) {
y = 123;
}
std::cout  y  \n;

The int in the first line means that the variable y is being defined.  Its
lack in the third line means that y refers to a variable defined in an outer
scope.  So both instances of y here refer to the same variable, as they do
in Python.

But because definition and assignment are separated in C++, we can also
write

int y = 42;
if (true) {
int y = 123;
}
std::cout  y  \n;

and the fragment will print 42.  In this example, there are two distinct
variables, both named y.

So the problem, as I see it, is indeed that in Python there are suites that
look to me as if they should define scopes, but don't.  Indeed, if I write

if (foo):
y = 123

I can't even determine by inspecting the program whether y is defined at
all.  I might argue that y is always defined, by virtue of appearing before
= somewhere in this scope, but the compiler tells me name 'y' is not
defined if I try it, so I guess that's the right way to treat it.

So here's how I understand what Greg was saying.

Suppose I write

x = []
for i in range(10):
x.append(lambda:i)
print [f() for f in x]

This example will print [9, 9, 9, 9, 9, 9, 9, 9, 9, 9], which I think is
wildly unintuitive.

My intuition in this matter is partly formed by C++, but it is also formed
by other languages going as far back as Algol 68.  That intuition says that
because the suite controlled by a for statement is executed any number of
times, potentially including zero, it should be considered as its own scope,
and any variables defined in that scope should stay there.

In particular, the variable i should be defined in the scope of the for,
which implies that each time through the loop, the name i should be
(re)bound to a different object.

What surprises me even more is that if I try to define such a variable
explicitly, it still doesn't work:

x = []
for i in range(10):
j = i
x.append(lambda:j)
print [f() for f in x]

This example still prints [9, 9, 9, 9, 9, 9, 9, 9, 9, 9].  If I understand
the reason correctly, it is because even though j is defined only in the
body of the loop, loop bodies are not scopes, so the variable's definition
is hoisted out into the surrounding function scope.

To convince myself of this behavior, I defined an extra function scope, the
purpose of which is to localize j:

x = []
for i in range(10):
def foo():
j = i
return lambda:j
x.append(foo())
print [f() for f in x]

Indeed, this example prints [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].  The example
also points up the fact that

x.append(lambda:i)

and

def foo():
j = i
return lambda:j
x.append(foo())

behave differently, where my intuition (and, I suspect, many other people's
as well) would be that they would be equivalent.

Finally, I observe that this second example above is also equivalent to

x.append(lambda i=i: i)

which is what explains the fairly common idiom

x = []
for i in range(10):
x.append(lambda i=i:i)
print [f() for f in x]

So maybe what I meant when I asked for lexical scopes was two things:

1) Every indentation level should be a scope;
2) In general, variable definitions should not leak into
   surrounding scopes.

I realize that (2) is too simplistic.  Someone who writes

if x  0:
y = -x
else:
y = x

will expect y to be defined in the scope surrounding the if even if it was
not already defined there.  On the other hand, I think that the subtle
pitfalls that come from allowing for variables to leak into the
surrounding scopes are much harder to deal with and understand than would be
the consequences of restricting their scopes as outlined above.



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 

Re: [Python-Dev] Lexical scoping in Python 3k

2006-07-01 Thread Andrew Koenig
 What about doing something similar to how import was changed?
 
 .a = 5 # this scope (self might be too magical
 ..a = 3 # up one scope
 ...a # up three
 
 Of course, this looks ... perhaps a bit strange. Also, counting is a
 bother.

I'd rather see a simpler rule: = never defines a variable in a surrounding
scope.  If you want to affect the binding of such a variable, you have to
define it explicitly in the scope in which you want it.

Example:

x = 42
def f():
x = 123 # rebinds x as defined above
y = 123 # defines local variable
f()
print x # prints 123
print y # error -- y not defined

Yes, I know that rule is too simplistic.  But I think I'd still prefer it to
the way things are now.



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Lexical scoping in Python 3k

2006-07-01 Thread Andrew Koenig
 Fully functional lexical scopes, then? 

Fine-grained scopes?



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] 2.5 and beyond

2006-07-01 Thread Andrew Koenig
 Don't recall what that was, but creating a new scope on each iteration
 sounds hard to explain in Python.

I don't think it's particularly hard to explain.  For example, one way to
explain it is to say that

for i in stuff:
body

is equivalent to

for hiddenvar in stuff:
local i = hiddenvar
body

This explanation doesn't need to rest on recursion.



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] 2.5 and beyond

2006-06-30 Thread Andrew Koenig
 I think it should increment (i.e. rebind) g, for the same reason that
 
   g = [1]
   def f():
   g[0] += 1
   f()
 
 rebinds g[0].

I saw messages out of sequence and did not realize that this would be a
change in behavior from 2.4.  Sigh.

I hope Py3000 has lexical scoping a la Scheme...



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] 2.5 and beyond

2006-06-30 Thread Andrew Koenig
 That's not a very constructive proposal (especially since I don't know
 Scheme). Perhaps you could elaborate on what needs to change?

The fundamental principle is that the binding of every name is determined
during compilation, not during execution.  This property does not quite
apply to Python at present.  For example:

x = 42
def f():
y = x
x = 123
return y
f()

This example fails with local variable 'x' referenced before assignment
because the compiler sees that f contains an assignment to x, so it makes x
a local variable, and then when you try to assign x to y during execution,
it fails.  This behavior is consistent with the notion of lexical scoping.

However, if I write

def g():
return x
x = 42
g()

the result is 42.  With lexical scoping, I believe it should be undefined.

The reason is that when the compiler encounters the definition of g,
variable x is not yet bound, and there is nothing in the body of g that
would bind it.  Therefore, g requires a binding to exist at the time it is
compiled; because no such binding exists, this example would be an error (at
compile time) under lexical scoping.






___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] 2.5 and beyond

2006-06-30 Thread Andrew Koenig
 I read a la Scheme here as actually nothing like Scheme, except I
 want a non-tricky way to rebind a name from an enclosing scope within
 an enclosed scope.

Almost.  What I really want is for it to be possible to determine the
binding of every name by inspecting the source text of the program.  Right
now, it is often possible to do so, but sometimes it isn't.



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Any reason that any()/all() do not take a predicateargument?

2006-04-13 Thread Andrew Koenig
 sorry if this came up before, but I tried searching the archives and
 found nothing.  It would be really nice if new builtin truth functions
 in 2.5 took a predicate argument(defaults to bool), so one could
 write, for example:
 
 seq = [1,2,3,4,5]
 if any(seq, lambda x: x==5):
 ...
 
 which is clearly more readable than
 
 reduce(seq, lambda x,y: x or y==5, False)

How about this?

if any(x==5 for x in seq):




___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] as mania

2006-03-07 Thread Andrew Koenig
 Thinking over it, this is too much a difference between the with-as and
 my as, so I'm abandoning this idea. My as would just have been a
 shortcut to avoid writing longish expressions that have to be checked for
 true-ness and then tinkered with.

ML has a similar feature, which you may consider as an argument either for
or against it depending on your taste.  The point is that ML lets you write
patterns that decompose data structures, and the as usage lets you talk
about the whole data structure and the decomposed one at the same time.

For example, in ML, :: works like cons in Lisp, so that x::y is a list
with a first element of x and a tail of y, which must be a list.  In other
words, [3, 4, 5] is equivalent to (3::4::5::nil) in ML.

Now consider the following:

fun merge(nil, y) = y
  | merge(x, nil) = x
  | merge (x as xh::ht, y as yh::yt) =
if xh  yh
then xh::merge(xt, y)
else xt::merge(x, yt)

Without the as clause, we would have had to write

fun merge(nil, y) = y
  | merge(x, nil) = x
  | merge(x, y) =
let val xh::xt = x
val yh::yt = y
 in if xh  yh
then xh::merge(xt, y)
else xt::merge(x, yt)
end

which is somewhat longer and harder to follow.

As it turns out, Python has similar ways of decomposing data structures:

(x, y) = foo

or

def bar((x, y)):
# etc.

and I have sometimes wished I could write

z as (x, y) = foo

or

def bar(z as (x, y)):
# etc.

However, it's not real high on my list of priorities, and I suspect that
many Pythonists consider these usages to be a frill anyway.



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] as mania

2006-03-07 Thread Andrew Koenig

 Function arguments are not covered by this trick, but
 
 def bar(z):
 (x,y) = z
 
 probably isn't too much overhead...

It's not the machine overhead, it's the intellectual overhead.  I know there
are some who will disagree with me, but I would find it easier to read

def foo(origin as (x1, y1), corner as (x2, y2)):

than to read

def foo(origin, corner):
(x1, y1) = origin
(x2, y2) = corner

It's not a big deal, but it is not completely negligible either.



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] _length_cue()

2006-02-08 Thread Andrew Koenig
 I'm worried about the name.  There are now exactly two names that behave
 like a special method without having the double-underscores around it.
 The first name is 'next', which is kind of fine because it's for
 iterator classes only and it's documented.  But now, consider: the
 CPython implementation can unexpectedly invoke a method on a
 user-defined iterator class, even though this method's name is not
 '__*__' and not documented as special!  That's new and that's bad.

Might I suggest that at least you consider using hint instead of cue?
I'm pretty sure that hint has been in use for some time, and always to
mean a value that can't be assumed to be correct but that improves
performance if it is.

For example, algorithms that insert values in balanced trees sometimes take
hint arguments that suggest where the algorithm should start searching for
the insertion point.



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Octal literals

2006-02-02 Thread Andrew Koenig
 I definately agree with the 0c664 octal literal. Seems rather more
 intuitive.

I still prefer 8r664.



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Octal literals

2006-01-31 Thread Andrew Koenig
 Possibly os.chmod and os.umask could be extended to take a string
 argument so we could write chmod(path, 0640).

-1.

Would you really want chmod(path, 0640) and chmod(path, 0640) to have
different meanings?
 


___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Octal literals

2006-01-31 Thread Andrew Koenig
 Apart from making 0640 a syntax error (which I think is wrong too),
 could this be solved by *requiring* the argument to be a string? (Or
 some other data type, but that's probably overkill.)

That solves the problem only in that particular context.

I would think that if it is deemed undesirable for a leading 0 to imply
octal, then it would be best to decide on a different syntax for octal
literals and use that syntax consistently everywhere.

I am personally partial to allowing an optional radix (in decimal) followed
by the letter r at the beginning of a literal, so 19, 8r23, and 16r13 would
all represent the same value.



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] yield back-and-forth?

2006-01-20 Thread Andrew Koenig
 The discussion about PEP 343 reminds me of the following. Bram Cohen
 pointed out in private email that, before PEP 342, there wasn't a big
 need for a shortcut to pass control to a sub-generator because the
 following for-loop works well enough:

  def main_generator():
   ...
   for value in sub_generator():
   yield value

 but now that yield can return a value, that value might have to be
 passed into sub_generator(), not to mention of exceptions. I'm sure
 there's a way to write that (although I haven't found the time to
 figure it out) but I expect it to be cumbersome and subtle.

It looks to me like continuations are starting to rear their heads...




___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Small any/all enhancement

2005-12-27 Thread Andrew Koenig
 Of course I already knew all the alternatives using map and the generator
 expression, but I felt like mine was clearer for a reader, this is
 probably true but not enough to justify the change.

If there is to be any enhancement, I think I would prefer it to be an
enhancement to map, so that map's second and subsequent arguments can be
sequences or iterables, and its result is an iterable if any of its
arguments is an iterable.

Unfortunately, that would be an incompatible change :-(



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Coroutines, generators, function calling

2005-10-20 Thread Andrew Koenig
 so the new syntax would
 not be useful, unless it was something that provided access to the index
 item as a variable, like:
 
 yield foo(i) for i in x
 
 which barely saves you anything (a colon, a newline, and an indent).

Not even that, because you can omit the newline and indent:

for i in x: yield foo(i)

There's a bigger difference between

for i in x: yield i

and

yield from x

Moreover, I can imagine optimization opportunities for yield from that
would not make sense in the context of comprehensions.



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Coroutines, generators, function calling

2005-10-18 Thread Andrew Koenig
   Sure, that would work.  Or even this, if the scheduler would
 automatically recognize generator objects being yielded and so would run
 the the nested coroutine until finish:

This idea has been discussed before.  I think the problem with recognizing
generators as the subject of yield statements is that then you can't yield
a generator even if you want to.

The best syntax I can think of without adding a new keyword looks like this:

yield from x

which would be equivalent to

for i in x:
yield i

Note that this equivalence would imply that x can be any iterable, not just
a generator.  For example:

yield from ['Hello', 'world']

would be equivalent to

yield 'Hello'
yield 'world'



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 343 updated

2005-10-16 Thread Andrew Koenig
 PEP 343 has been updated on python.org.

 Highlights of the changes:

- changed the name of the PEP to be simply The 'with' Statement

Do you mean PEP 346, perchance?  PEP 343 is something else entirely.



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] C.E.R. Thoughts

2005-10-10 Thread Andrew Koenig
 Congragulations heartily given. I missed the ternary op in c... Way to
 go! clean and easy and now i can do:

 if ((sys.argv[1] =='debug') if len(sys.argv)  1 else False):
   pass

 and check variables IF AND ONLY if they exist, in a single line!

Umm... Is this a joke?



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] and and or operators in Py3.0

2005-09-22 Thread Andrew Koenig
 In C, C++, C#, Java, and JavaScript, what do you get when you print the
 result of 3 || 10?

In C and C++, you get 1.  (in c++ the result is actually true, not 1, but
true prints as 1 by default for backward compatibility)



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] removing nested tuple function parameters

2005-09-19 Thread Andrew Koenig
 I agree that we shouldn't mess with them in 2.x. Yet I think they are
 a candidate for being dropped from Py3K. While every feature is used
 by *someone* (as the feedback to Brett's query clearly shows) this one
 has several things against it. For every user who is fond of them
 there are probably ten who have never even heard of it. It's purely
 syntactic sugar (the only place where it's not trivial to replace is
 in a lambda). I've encountered quite a few people who had a hard time
 reading code that uses it. I personally prefer reading code that
 doesn't use this feature; for one thing, when this is used, you can't
 refer to a parameter by name.

I don't know whether this qualifies as an argument for or against the
feature, but ML has a nice way of referring to such a parameter by name:

fun f(x as (y, z)) = (* ... *)

This defines f as a function with an argument that is a 2-element tuple.
The name x is bound to the argument, and the names y and z are bound to the
two components of the argument.

This example is syntactic sugar for

fun f x = let val (y, z) = x in (* ... *) end

but it I find the sugared version easier and more natural to write and
understand.  If you don't know ML, the unsugared version might be easier to
follow if I indent it Pythonically:

fun f x =
let
val (y, z) = x
in
(* ... *)
end

The idea is that the stuff between in and end is executed in the scope
of the bindings between let and in, after which those bindings are
discarded.



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] removing nested tuple function parameters

2005-09-19 Thread Andrew Koenig
 The only practical reason to like this feature is sparing the need of
 finding an otherwise useless name for the formal argument.  Another
 reason, but not practical at all, is that the concept conveys some
 elegance and originality (each programming language should ideally have
 a few of these) and is enforced in other places in Python, like in the
 `for' statement -- where I find implied unpacking very, very useful.

One other reason: It is possible to imagine using the feature to catch some
type errors at the point of call, rather than having to get into the
function itself before detecting them.



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Wishlist: dowhile

2005-06-15 Thread Andrew Koenig
  I believe that Algol 68 loops looked like the following (in somewhat
  more Python-like terms):
 
  [for identifier [from suite] [step suite] to suite]
  [while suite]
  do suite od


 As far as I remember, it was:

 do
   suite
 while suite; ending with a boolean value
   suite
 od

 It might be that this could be preceded by a 'for' clause, but memory
 fails me there.

To be completely sure, I dug out my copy of the Informal Introduction to
Algol 68 by Lindsey and van der Meulen.  This book is the official Algol 68
tutorial book.  It describes the loop clause as follows:

for
some int identifier, which is hereby declared
from
some meek int unit
by
some other meek int unit
to
a third meek int unit
while
a meek bool enquiry-clause
do
a void serial-clause
od

where any of these keywords and its sequel can be omitted, except for do
or od.

Here, the term meek refers to how aggressively the compiler should try to
convert the result to int; it specifies, for example, that if after from
you write the name of a procedure without arguments, that procedure will be
called instead of using the procedure itself as a starting point (which
would be nonsensical).



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 343 - next steps

2005-06-13 Thread Andrew Koenig

  But I cannot do this:
 
  def f(x as (a, b)):
  # ...

  which is what I was suggesting.

 Yeah, I knew that. How important is that to you?

I would really have liked it for a program I was working on at one time that
had lots of small methods that passed around values of forms such as
(a,(b,c)).  Each method would pick one or more of the components out of its
compound value and then would sometimes pass the entire value down to the
next level.

Of course I could do it this way:

def f(x):
(a,(b,c)) = x
# ...

but in this particular application, as would have offered significant
extra convenience.

I understand that this is not a real big deal, which is why I haven't
written up a PEP :-)


___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] PEP 343 - next steps

2005-06-11 Thread Andrew Koenig
 The issue is: if we allow VAR to be a
 comma-separated list of variables now, that cuts off the extension to
 (a) in the future; so the PEP would have to be amended to state that
 VAR must be a single variable or a list of variables IN PARENTHESES.
 Thoughts?

I am not sure how relevant this is, but the syntax x as (a, b) sure looks
to me like (a, b) is a tuple.

Of course, I'm biased by ML, which has a feature that I wish Python had:

fun f(x as (a, b)) = ...

This says that f's argument must be a 2-element tuple.  It binds x to the
argument and also binds a and b to the argument's components.

Of course the program could be written this way:

fun f(x) = let val (a, b) = x in ... end

but the as syntax is more succinct, direct, and convenient.

If such a feature were implemented in Python, I would imagine it to allow
usages such as

x as (a, b) = (3, 4)

which would be equivalent to

x = (a, b) = (3, 4)

Of course, this usage shows that the syntax is unnecessary in this context,
but what I care about is

def f(x as (a, b)):
# ...

which has the advantage over the alternative

def f(x):
(a, b) = x
# ...

that if you call f with the wrong arguments, you get a clearer diagnostic
message.

It's kind of an edge case, and I am not seriously pushing for its adoption,
but I do think it worth pointing out that when I see x as (a, b), that's
what it immediately brings to mind.


___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


RE: [Python-Dev] Re: anonymous blocks

2005-04-27 Thread Andrew Koenig

 that we are having this discussion at all seems a signal that the
 semantics are likely too subtle.

I feel like we're quietly, delicately tiptoeing toward continuations...


___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


RE: [Python-Dev] defmacro

2005-04-26 Thread Andrew Koenig
 This doesn't feel right to me.  By that argument, people would want
 to improve
 
   (mapcar (lambda (x) (car x)) list-of-lists)
 
 to
 
   (mapcar list-of-lists (x) (car x))
 
 Have you ever heard someone complain about that lambda, though?

Wel  Shouldn't you have written

(mapcar car list-of-lists)

or am I missing something painfully obvious?

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


RE: [Python-Dev] Lambda deferred evaluation (was: Adding any() andall())

2005-03-16 Thread Andrew Koenig

 Lambda will be more difficult.  Eric Raymond adapted an anti-gun control
 slogan and said you can pry lambda out of my cold dead hands.  A bunch
 of folks will sorely miss the ability to create anonymous functions on
 the fly.  When lambda is used for deferred argument evaluation (a la PEP
 312), the def syntax is a crummy substitute.

  Yeah, I'm with you here.  As warty as lambda is, it just is so damn
  convenient some times.  I've recently been using it as a companion to
  property(), providing concise definitions of read-only attributes.

I'm with you on lambda:  I've found a few places where losing it would be a
major inconvenience.

One example is in a library I wrote to implement the Snobol4 algorithm for
recursive-descent pattern matching.  Using that algorithm relies heavily on
the ability to specify subexpressions for deferred evaluation -- their
values must not be computed until they are actually needed.  For example,
here is a mini-specification for arithmetic expressions in Snobol4:

id = any(letters) span(letters digits)
primary = id | '(' *expr ')'
factor = primary arbno(any(*/) primary)
expr = factor arbno(any(+-) factor)

This should be fairly straightforward once you realize that arbno is like
a regular-expression *, blank is used for concatenation, and | (meaning
or) binds less tightly than blank.

The whole definition depends on *expr, which is a request for deferred
evaluation of expr.  In other words, it refers to the value of expr when
encountered during matching, rather than the (null) value it has when the
assignment to primary is evaluated.

Through appropriate use of overloading, I have been able to translate this
code into the following Python:

id = any(letters) + span(letters + digits)
primary = id | '(' + defer(lambda: expr) + ')'
factor = primary + arbno(any(*/) + primary)
expr = factor + arbno(any(+-) + factor)

I do not want to have to rewrite this code as:

def defer_expr:
return expr
id = any(letters) + span(letters + digits)
primary = id | '(' + defer(defer_expr) + ')'
factor = primary + arbno(any(*/) + primary)
expr = factor + arbno(any(+-) + factor)

because I do not want to have to make up a new name, and because in
practice, I've seen patterns in which there are many deferred evaluations,
not just one as in this example.  In other words, I want deferred evaluation
to remain a conceptually inexpensive operation, and lambda is the only way
of doing this.



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com