C#3.0 and lambdas

C

Christophe

Serhiy Storchaka a écrit :
Roel said:
Fredrik Lundh schreef:
meanwhile, over in python-dev land:

"Is anyone truly attached to nested tuple function parameters; 'def
fxn((a,b)): print a,b'? /.../

Would anyone really throw a huge fit if they went away? I am willing
to write a PEP for their removal in 2.6 with a deprecation in 2.5 if
people are up for it."


I for one would not like to see that disappear. I like being able to
write, for example:

def drawline((x1, y1), (x2, y2)):
# draw a line from x1, y1 to x2, y2
foo(x1, y1)
bar(x2, y2)

instead of

def drawline(p1, p2):
x1, y1 = p1
x2, y2 = p2
# draw a line from x1, y1 to x2, y2
foo(x1, y1)
bar(x2, y2)

or

def drawline(p1, p2):
# draw a line from p1[0], p1[1] to p2[0], p2[1]
foo(p1[0], p1[1])
bar(p2[0], p2[1])


def drawline(p1, p2):
# draw a line from p1 to p2
foo(*p1)
bar(*p2)

That one is stupid. I don't see how you can make it work without some
global storing the p1 information in foo which I would consider as very
ugly code.
 
F

Fredrik Lundh

Christophe said:
That one is stupid. I don't see how you can make it work without some
global storing the p1 information in foo which I would consider as very
ugly code.

if you cannot see how that can work, you clearly haven't done much graphics
programming in your days...

</F>
 
S

Steve Holden

Christophe said:
Serhiy Storchaka a écrit :
Roel Schroeven wrote:
[...]
or

def drawline(p1, p2):
# draw a line from p1[0], p1[1] to p2[0], p2[1]
foo(p1[0], p1[1])
bar(p2[0], p2[1])


def drawline(p1, p2):
# draw a line from p1 to p2
foo(*p1)
bar(*p2)


That one is stupid. I don't see how you can make it work without some
global storing the p1 information in foo which I would consider as very
ugly code.

In which case perhaps you should actually try the code. Then once you
realise it works you can start to figure out why :). Hint: f(*p1)
appears as len(p1) separate arguments to the called function.

regards
Steve
 
C

Christophe

Fredrik Lundh a écrit :
Christophe wrote:




if you cannot see how that can work, you clearly haven't done much graphics
programming in your days...

You should probably notice that graphics library have changed a lot in
the last 20 years. Also, that one was an example but it could have been :

def draw_circle(c, p):
"""Draws a circle centered on c and which goes through p"""
pass
 
C

Christophe

Steve Holden a écrit :
Christophe said:
Serhiy Storchaka a écrit :
Roel Schroeven wrote:
[...]
or

def drawline(p1, p2):
# draw a line from p1[0], p1[1] to p2[0], p2[1]
foo(p1[0], p1[1])
bar(p2[0], p2[1])



def drawline(p1, p2):
# draw a line from p1 to p2
foo(*p1)
bar(*p2)


That one is stupid. I don't see how you can make it work without some
global storing the p1 information in foo which I would consider as
very ugly code.


In which case perhaps you should actually try the code. Then once you
realise it works you can start to figure out why :). Hint: f(*p1)
appears as len(p1) separate arguments to the called function.

You should also notice that foo knows the starting point of the line but
not the ending point and so it can't draw the line. On the other hand,
bar knows the end point but not the starting point so it can't do the
job either.

And what about a function which computes the line length ?
 
S

Steve Holden

Christophe said:
Steve Holden a écrit :
Christophe wrote:

Serhiy Storchaka a écrit :


Roel Schroeven wrote:
[...]


or

def drawline(p1, p2):
# draw a line from p1[0], p1[1] to p2[0], p2[1]
foo(p1[0], p1[1])
bar(p2[0], p2[1])



def drawline(p1, p2):
# draw a line from p1 to p2
foo(*p1)
bar(*p2)



That one is stupid. I don't see how you can make it work without some
global storing the p1 information in foo which I would consider as
very ugly code.


In which case perhaps you should actually try the code. Then once you
realise it works you can start to figure out why :). Hint: f(*p1)
appears as len(p1) separate arguments to the called function.


You should also notice that foo knows the starting point of the line but
not the ending point and so it can't draw the line. On the other hand,
bar knows the end point but not the starting point so it can't do the
job either.
This is rubbish.

foo(*p1)

is *exactly* equivalent to

foo(p1[0], p1[1])

and similarly

bar(p2)

is *exactly* equivalent to

bar(p2[0], p2[1])

and consequently the second version of drawline is exactly equivalent to
the first. So, if the second one is useless then so is the first.
And what about a function which computes the line length ?

I'm not sure what point you are trying to make here. Can you explain?

regards
Steve
 
R

Roel Schroeven

Christophe schreef:
Steve Holden a écrit :
Christophe said:
Serhiy Storchaka a écrit :

Roel Schroeven wrote:

[...]

or

def drawline(p1, p2):
# draw a line from p1[0], p1[1] to p2[0], p2[1]
foo(p1[0], p1[1])
bar(p2[0], p2[1])




def drawline(p1, p2):
# draw a line from p1 to p2
foo(*p1)
bar(*p2)



That one is stupid. I don't see how you can make it work without some
global storing the p1 information in foo which I would consider as
very ugly code.



In which case perhaps you should actually try the code. Then once you
realise it works you can start to figure out why :). Hint: f(*p1)
appears as len(p1) separate arguments to the called function.


You should also notice that foo knows the starting point of the line but
not the ending point and so it can't draw the line. On the other hand,
bar knows the end point but not the starting point so it can't do the
job either.

It was just an example of tuples as arguments to a function and doing
something with the values of the tuples in the function itself. Even so,
many graphical environments offer MoveTo(x, y) and LineTo(x, y) or
equivalents. MoveTo moves some internal cursor to the specified position
without drawing a line; LineTo draws a line from the stored cursor
position to the specified position and moves the internal cursor to that
new position.
And what about a function which computes the line length ?

That would have been a better example indeed, since the *p1 trick
doesn't work there.

def euclidian_distance((x1, y1), (x2, y2)):
return math.sqrt((x2 - x1)**2 + (y2 - y1)**2)

That's a lot nicer, I think, than this:

def euclidian_distance(p1, p2):
return math.sqrt((p2[0] - p1[0])**2 + (p2[1] - p1[1])**2)
 
C

Christophe

Steve Holden a écrit :
Christophe said:
Steve Holden a écrit :
Christophe wrote:


Serhiy Storchaka a écrit :


Roel Schroeven wrote:


[...]


or

def drawline(p1, p2):
# draw a line from p1[0], p1[1] to p2[0], p2[1]
foo(p1[0], p1[1])
bar(p2[0], p2[1])




def drawline(p1, p2):
# draw a line from p1 to p2
foo(*p1)
bar(*p2)



That one is stupid. I don't see how you can make it work without
some global storing the p1 information in foo which I would consider
as very ugly code.



In which case perhaps you should actually try the code. Then once you
realise it works you can start to figure out why :). Hint: f(*p1)
appears as len(p1) separate arguments to the called function.



You should also notice that foo knows the starting point of the line
but not the ending point and so it can't draw the line. On the other
hand, bar knows the end point but not the starting point so it can't
do the job either.
This is rubbish.

foo(*p1)

is *exactly* equivalent to

foo(p1[0], p1[1])

and similarly

bar(p2)

is *exactly* equivalent to

bar(p2[0], p2[1])

and consequently the second version of drawline is exactly equivalent to
the first. So, if the second one is useless then so is the first.

Well, sorry about that but you are perfectly right. The point I was
trying to defend though was that such construct is very uncommon. It
isn't always possible to unpack the tuples like that because you usually
need all the info at once.
I'm not sure what point you are trying to make here. Can you explain?

As I said, the point was that in that specific case, you can do it like
that, but most of the time you need the unpack info for all the data in
the same function. For example to compute the line length.

def length((x1,y1),(x2,y2)):
return math.hypot(x1-x2,y1-y2)

No unpack trick ( that I know of ) can be used here. You only have 1 way
to do it without the unpack in function parameters syntax :

def length(p1, p2):
x1, y1 = p1
x2, y2 = p2
return math.hypot(x1-x2,y1-y2)
 
F

Fredrik Lundh

Christophe said:
You should probably notice that graphics library have changed a lot in
the last 20 years.

yeah, nobody uses things like OpenGL and PDF and SVG and similar APIs
these days...

</F>
 
S

Scott David Daniels

Roel said:
...
Christophe schreef:
...
And what about a function which computes the line length ?

That would have been a better example indeed, since the *p1 trick
doesn't work there.

def euclidian_distance((x1, y1), (x2, y2)):
return math.sqrt((x2 - x1)**2 + (y2 - y1)**2)

That's a lot nicer, I think, than this:

def euclidian_distance(p1, p2):
return math.sqrt((p2[0] - p1[0])**2 + (p2[1] - p1[1])**2)

But not massively nicer than:

def euclidian_distance(p1, p2):
(x1, y1), (x2, y2) = p1, p2
return math.sqrt((x2 - x1)**2 + (y2 - y1)**2)

--Scott David Daniels
(e-mail address removed)
 
R

Robert Kern

Christophe said:
Steve Holden a écrit :

Well, sorry about that but you are perfectly right. The point I was
trying to defend though was that such construct is very uncommon. It
isn't always possible to unpack the tuples like that because you usually
need all the info at once.

Many, many drawing APIs use a Postscript-like model such that drawing a
line from p1 to p2 decomposes into something like this:

moveto(p1)
lineto(p2)

Almost always those are methods on some object that maintains the state
(no globals in sight):

gc.moveto(p1)
gc.lineto(p2)

I think it's much more common than you realize. You are right that there
are plenty of functions that you might want to call that would require
something like this:

low_level_drawline(x1, y1, x2, y2)

that isn't amenable to *argument unpacking.

--
Robert Kern
(e-mail address removed)

"In the fields of hell where the grass grows high
Are the graves of dreams allowed to die."
-- Richard Harter
 
D

Dennis Lee Bieber

No unpack trick ( that I know of ) can be used here. You only have 1 way
to do it without the unpack in function parameters syntax :

def length(p1, p2):
x1, y1 = p1
x2, y2 = p2
return math.hypot(x1-x2,y1-y2)
.... return math.hypot(p1[0] - p2[0], p1[1] - p2[1])
....
Still no need for intermediate variables, you can index the tuple at
need.
--
 
C

Christophe

Dennis Lee Bieber a écrit :
No unpack trick ( that I know of ) can be used here. You only have 1 way
to do it without the unpack in function parameters syntax :

def length(p1, p2):
x1, y1 = p1
x2, y2 = p2
return math.hypot(x1-x2,y1-y2)

... return math.hypot(p1[0] - p2[0], p1[1] - p2[1])
...

5.0


Still no need for intermediate variables, you can index the tuple at
need.

Well, I prefer the explicit tuple unpack anyway. It gives better results
than using tuple indexing ( and better performance too most of the time )
 
B

Bill Mill

Roel said:
...
Christophe schreef:
...
And what about a function which computes the line length ?

That would have been a better example indeed, since the *p1 trick
doesn't work there.

def euclidian_distance((x1, y1), (x2, y2)):
return math.sqrt((x2 - x1)**2 + (y2 - y1)**2)

That's a lot nicer, I think, than this:

def euclidian_distance(p1, p2):
return math.sqrt((p2[0] - p1[0])**2 + (p2[1] - p1[1])**2)

But not massively nicer than:

def euclidian_distance(p1, p2):
(x1, y1), (x2, y2) = p1, p2
return math.sqrt((x2 - x1)**2 + (y2 - y1)**2)

But the question is - why go to the effort to remove the (by your
admission) slightly nicer version?

Peace
Bill Mill
bill.mill at gmail.com
 
D

Dieter Maurer

Fredrik Lundh said:
...
meanwhile, over in python-dev land:

"Is anyone truly attached to nested tuple function parameters; 'def
fxn((a,b)): print a,b'? /.../

Yes, I am...
Would anyone really throw a huge fit if they went away? I am willing
to write a PEP for their removal in 2.6 with a deprecation in 2.5 if
people are up for it."

I would think of it as a great stupidity.
 
S

Steven D'Aprano

Well, I prefer the explicit tuple unpack anyway. It gives better results
than using tuple indexing ( and better performance too most of the time )


I would love to see your test code and profiling results that demonstrate
that explicit tuple unpacking in the body of a function is faster than
tuple unpacking (implicit or explicit) in the header of a function.
 
S

Steven Bethard

Steven said:
I would love to see your test code and profiling results that demonstrate
that explicit tuple unpacking in the body of a function is faster than
tuple unpacking (implicit or explicit) in the header of a function.

Should be pretty close. I believe the byte-code is nearly identical:

py> def f1((x, y)):
.... pass
....
py> def f2(x_y):
.... x, y = x_y
....
py> dis.dis(f1)
1 0 LOAD_FAST 0 (.0)
3 UNPACK_SEQUENCE 2
6 STORE_FAST 1 (x)
9 STORE_FAST 2 (y)

2 12 LOAD_CONST 0 (None)
15 RETURN_VALUE
py> dis.dis(f2)
2 0 LOAD_FAST 0 (x_y)
3 UNPACK_SEQUENCE 2
6 STORE_FAST 2 (x)
9 STORE_FAST 1 (y)
12 LOAD_CONST 0 (None)
15 RETURN_VALUE

STeVe
 
C

Christophe

Steven Bethard a écrit :
Should be pretty close. I believe the byte-code is nearly identical:

You forgot the most important function : f3
.... print x,y
........ x,y = x_y
.... print x,y
........ print x_y[0], x_y[1]
.... 1 0 LOAD_FAST 0 (.0)
3 UNPACK_SEQUENCE 2
6 STORE_FAST 1 (x)
9 STORE_FAST 2 (y)

2 12 LOAD_FAST 1 (x)
15 PRINT_ITEM
16 LOAD_FAST 2 (y)
19 PRINT_ITEM
20 PRINT_NEWLINE
21 LOAD_CONST 0 (None)
24 RETURN_VALUE 2 0 LOAD_FAST 0 (x_y)
3 UNPACK_SEQUENCE 2
6 STORE_FAST 2 (x)
9 STORE_FAST 1 (y)

3 12 LOAD_FAST 2 (x)
15 PRINT_ITEM
16 LOAD_FAST 1 (y)
19 PRINT_ITEM
20 PRINT_NEWLINE
21 LOAD_CONST 0 (None)
24 RETURN_VALUE 2 0 LOAD_FAST 0 (x_y)
3 LOAD_CONST 1 (0)
6 BINARY_SUBSCR
7 PRINT_ITEM
8 LOAD_FAST 0 (x_y)
11 LOAD_CONST 2 (1)
14 BINARY_SUBSCR
15 PRINT_ITEM
16 PRINT_NEWLINE
17 LOAD_CONST 0 (None)
20 RETURN_VALUE
 
E

Erik Wilsher

And I think the discussion that followed proved your point perfectly
Fredrik. Big discussion over fairly minor things, but no "big picture".
Where are the initiatives on the "big stuff" (common documentation
format, improved build system, improved web modules, reworking the
standard library to mention a few) Hey, even Ruby is passing us here.
 
R

Reinhold Birkenfeld

Erik said:
And I think the discussion that followed proved your point perfectly
Fredrik. Big discussion over fairly minor things, but no "big picture".
Where are the initiatives on the "big stuff" (common documentation
format, improved build system, improved web modules, reworking the
standard library to mention a few) Hey, even Ruby is passing us here.

This is Open Source. If you want an initiative, start one.

Reinhold
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,071
Latest member
MetabolicSolutionsKeto

Latest Threads

Top