Re: PEP 309 (Partial Function Application) Idea

2006-01-16 Thread Ronald Mai
for a new function, named parameter might be a better choise, but for
existing function, placeholder would be better, since you don't need to
modify the exiting code.

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


Re: PEP 309 (Partial Function Application) Idea

2006-01-16 Thread Ronald Mai
sorry, should be existing

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


Re: PEP 309 (Partial Function Application) Idea

2006-01-16 Thread Ronald Mai
for a new function, named parameter might be a better choise, but for
existing function, placeholder would be better, since you don't need to
modify the existing code.

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


Re: PEP 309 (Partial Function Application) Idea

2006-01-15 Thread Giovanni Bajo
Ronald Mai wrote:

 Here is a reference implementation:

 _ = lambda x: x.pop(0)

 def partial(func, *args, **keywords):
 def newfunc(*fargs, **fkeywords):
 newkeywords = keywords.copy()
 newkeywords.update(fkeywords)
 newargs = (lambda seq: tuple([(a == _ and a(seq)) or a for
 a in args] + seq))(list(fargs))
 return func(*newargs, **newkeywords)
 newfunc.func = func
 newfunc.args = args
 newfunc.keywords = keywords
 return newfunc

 Here is example of use:

 def capture(*args):
 return args

 partial(capture)()
 ()
 partial(capture, _)(1)
 (1,)
 partial(capture, _, 2)(1)
 (1, 2)
 partial(capture, 1)(2)
 (1, 2)
 partial(capture, 1, _)(2)
 (1, 2)
 partial(capture, 1, _)()
 IndexError: pop from empty list
 partial(capture, 1, _, _)(2, 3)
 (1, 2, 3)

Other implementations I have seen (boost::bind comes to mind) use ordered
placeholders such as _1, _2, _3, etc to provide more flexibility in adaptation:

 partial(capture, a, _1, _2)(b, c)
(a, b, c)
 partial(capture, a, _2, _1)(b, c)
(a, c, b)

I don't see mention of this in the PEP, but it's a nice feature to have IMO.
-- 
Giovanni Bajo


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


Re: PEP 309 (Partial Function Application) Idea

2006-01-15 Thread bonono

Giovanni Bajo wrote:
 Ronald Mai wrote:

  Here is a reference implementation:
 
  _ = lambda x: x.pop(0)
 
  def partial(func, *args, **keywords):
  def newfunc(*fargs, **fkeywords):
  newkeywords = keywords.copy()
  newkeywords.update(fkeywords)
  newargs = (lambda seq: tuple([(a == _ and a(seq)) or a for
  a in args] + seq))(list(fargs))
  return func(*newargs, **newkeywords)
  newfunc.func = func
  newfunc.args = args
  newfunc.keywords = keywords
  return newfunc
 
  Here is example of use:
 
  def capture(*args):
  return args
 
  partial(capture)()
  ()
  partial(capture, _)(1)
  (1,)
  partial(capture, _, 2)(1)
  (1, 2)
  partial(capture, 1)(2)
  (1, 2)
  partial(capture, 1, _)(2)
  (1, 2)
  partial(capture, 1, _)()
  IndexError: pop from empty list
  partial(capture, 1, _, _)(2, 3)
  (1, 2, 3)

 Other implementations I have seen (boost::bind comes to mind) use ordered
 placeholders such as _1, _2, _3, etc to provide more flexibility in 
 adaptation:

  partial(capture, a, _1, _2)(b, c)
 (a, b, c)
  partial(capture, a, _2, _1)(b, c)
 (a, c, b)

 I don't see mention of this in the PEP, but it's a nice feature to have IMO.
 --
 Giovanni Bajo
Since python has named parameter(and I assume this PEP would support it
as well), is it really that useful to have these place holder things  ?
As when the parameter list gets long, named param should be easier to
read.

The only case I find it useful is for binary ops where I would like to
either bind the left hand side or the right hand side but that can be
handled easily with a flip function as in haskell.

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


Re: PEP 309 (Partial Function Application) Idea

2006-01-15 Thread Giovanni Bajo
[EMAIL PROTECTED] wrote:

 Since python has named parameter(and I assume this PEP would support
 it as well), is it really that useful to have these place holder things
 ?

Probably not so much, you're right.

 As when the parameter list gets long, named param should be easier to
 read.

 The only case I find it useful is for binary ops where I would like to
 either bind the left hand side or the right hand side but that can be
 handled easily with a flip function as in haskell.

I'm not sure I'd like a specialized flip function, compared to the numbered
placeholders solution.
-- 
Giovanni Bajo


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


PEP 309 (Partial Function Application) Idea

2006-01-14 Thread Ronald Mai
In my opinion, Ellipsis might be in the middle, not only in leftmost or
rightmost, so a placeholder approach can be much more flexible and
convenient.

Here is a reference implementation:

_ = lambda x: x.pop(0)

def partial(func, *args, **keywords):
def newfunc(*fargs, **fkeywords):
newkeywords = keywords.copy()
newkeywords.update(fkeywords)
newargs = (lambda seq: tuple([(a == _ and a(seq)) or a for
a in args] + seq))(list(fargs))
return func(*newargs, **newkeywords)
newfunc.func = func
newfunc.args = args
newfunc.keywords = keywords
return newfunc

Here is example of use:

 def capture(*args):
return args

 partial(capture)()
()
 partial(capture, _)(1)
(1,)
 partial(capture, _, 2)(1)
(1, 2)
 partial(capture, 1)(2)
(1, 2)
 partial(capture, 1, _)(2)
(1, 2)
 partial(capture, 1, _)()
IndexError: pop from empty list
 partial(capture, 1, _, _)(2, 3)
(1, 2, 3)

Chris Perkins :

 Random idea of the day: How about having syntax support for
 currying/partial function application, like this:

 func(..., a, b)
 func(a, ..., b)
 func(a, b, ...)

 That is:
 1) Make an Ellipsis literal legal syntax in an argument list.
 2) Have the compiler recognize the Ellipsis literal and transform the
 function call into a curried/parially applied function.

 So the compiler would essentially do something like this:

 func(a, ...) == curry(func, a)
 func(..., a) == rightcurry(func, a)
 func(a, ..., b) == rightcurry(curry(func,a), b)

 I haven't though this through much, and I'm sure there are issues, but
 I do like the way it looks.  The ... really stands out as saying
 something is omitted here.
 
 
 Chris Perkins

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


Re: PEP 309 (Partial Function Application) Idea

2005-03-14 Thread Chris Perkins
Steven Bethard [EMAIL PROTECTED] wrote:
 
 getting attributes with defaults[1]:
  objs.sort(key=lambda a: getattr(a, 'lineno', 0))
  objs.sort(key=getattr(__, 'lineno', 0)
 

Yes, this exact example is one of the (very) few that I found in the
standard library where the syntax actually helps.

 Places where you might be able to use it (with some changes):
 
 using bound methods[1][2]:
  map(lambda x: x.strip(), lst)
  map(str.strip(), lst) #!! doesn't work for unicode
  map(methodcaller('strip'), lst) # proposed by Alex Martelli
  __.strip() # note that calling strip on __ would have to
 # return a curryable looking for one arg...
 

Yes, the bound method problem is what convinced me to give up on this.
One can hardly write strip() (yes, that's four dots).
But note that there is a library out there that does precisely this
(and much more, if I remember) - I believe it's in David Mertz's
Xoltar toolkit. It does allow you to write _.strip() and get a
curried callable (He uses _, a single underscore, as the magic
thingy, which is odd considering its established meaning in
interactive mode).

If we could add an object to the builtins (or elsewhere) called __
that works as I proposed for ..., and also behaves like the things
in David Mertz's library (sorry, don't remember exactly where to find
it, or what it's called, and don't have time to look it up right now),
then this might really get interesting. Then we could do any of:
getattr(__, 'lineno', 0)
__.strip()
__.foo().bar(__)

 adding method to an instance[1]:
  self.plural = lambda n: int(n != 1)

and _maybe_ even:
self.plural = int(__ != 1)


But wait - on second thought, __ is a legal identifier now, unlike
..., so we can't have the compiler messing around with expressions
like foo(x, __), can we.  OK, now I really give up on the whole idea!


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


Re: PEP 309 (Partial Function Application) Idea

2005-03-12 Thread Scott David Daniels
Reinhold Birkenfeld wrote:
Steven Bethard wrote:
Chris Perkins wrote:
Random idea of the day: How about having syntax support for
currying/partial function application, like this:
func(..., a, b)
func(a, ..., b)
func(a, b, ...)
That is:
1) Make an Ellipsis literal legal syntax in an argument list.
2) Have the compiler recognize the Ellipsis literal and transform
  the function call into a curried/parially applied function.
So the compiler would essentially do something like this:
func(a, ...) == curry(func, a)
func(..., a) == rightcurry(func, a)
func(a, ..., b) == rightcurry(curry(func,a), b)
I haven't though this through much, and I'm sure there are issues, but
I do like the way it looks.  The ... really stands out as saying
something is omitted here.
The interaction of this with keyword args and omitted args is
problematic (as is the case for rightcurry, in fact).  I can't
think of a good way to explain what _should_ happen for a
function defined as def function(*args, **kwargs): ... when you:
def fun(bug, frog, verb): ...
f1 = function(1, ..., frog=3)
f2 = f1(..., 4)
f2()
Keywords were why I did no rightcurry definition in the first place;
I couldn't convince myself there was a good, obvious, resolution.
--Scott David Daniels
[EMAIL PROTECTED]
--
http://mail.python.org/mailman/listinfo/python-list


Re: PEP 309 (Partial Function Application) Idea

2005-03-12 Thread Chris Perkins
Scott David Daniels wrote:
Chris Perkins wrote:
Random idea of the day: How about having syntax support for
currying/partial function application, like this:
func(..., a, b)
func(a, ..., b)
func(a, b, ...)

That is:
1) Make an Ellipsis literal legal syntax in an argument list.
2) Have the compiler recognize the Ellipsis literal and transform
   the function call into a curried/parially applied function.
So the compiler would essentially do something like this:

func(a, ...) == curry(func, a)
func(..., a) == rightcurry(func, a)
func(a, ..., b) == rightcurry(curry(func,a), b)

The interaction of this with keyword args and omitted args is
problematic (as is the case for rightcurry, in fact).  I can't
think of a good way to explain what _should_ happen for a
function defined as def function(*args, **kwargs): ... when you:

 def fun(bug, frog, verb): ...
 f1 = function(1, ..., frog=3)
 f2 = f1(..., 4)
 f2()

Keywords were why I did no rightcurry definition in the first place;
I couldn't convince myself there was a good, obvious, resolution.


I agree that it's not obvious what _should_ happen in complex cases.

I wrote up a psuedo-implementation to play with, just to get a feel
for it.  It works only on @curryable functions, and I use __ in place
of  I think that's about as close as I can get in pure Python.

def curryable(func):
This hurts my brain a little bit, but I _think_ it works.
def proxyfunc(*args, **kwds):
if list(args).count(Ellipsis)  1:
raise TypeError('Your mother was a hampster...')
if Ellipsis in args:
@curryable
def curried(*a, **k): 
kwdict = kwds.copy()
kwdict.update(k)
epos = list(args).index(Ellipsis)
return func(*(args[:epos] + a + args[epos+1:]), **kwdict)
return curried
return func(*args, **kwds)
return proxyfunc

def test():
__ = Ellipsis
@curryable
def fun(bug, frog, verb):
print bug, frog, verb

f1 = fun(1, __, frog=3)
f2 = f1(__, 4)
try:
f2()
except TypeError, e:
print e # multiple values for keyword 'frog'

f1 = fun(1, __, verb=3) 
f2 = f1(__, 4) 
f2()
f2(verb=99)

try:
f1(__, 2, __)
except TypeError, e:
print e

if __name__ == '__main__':
test()


After playing with this a bit, I found the semantics to be reasonably 
obvious once I got used to it; at least in the cases I tried.  I'd be
quite happy to have anything fishy throw an exception.  Cases where 
I would actually use this would be quite simple, I think.

On the other hand, I'm not convinced that this construct would be
especially useful.  I spent some time looking at uses of lambda in the
standard library, hoping to find lots of examples where a (...)
function would be more readable, but I eventually gave up. (Found
dozens of cases where a list-comp or genexp would be better, though).

While I think that func(x, ...) is more readable than partial(func, x),
I'm not sure that I would use either of them often enough to warrant
special syntax. If anyone disagrees, feel free to petition python-dev;
I don't expect to pursue this any further.

Thanks to all for your comments.


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


Re: PEP 309 (Partial Function Application) Idea

2005-03-12 Thread Steven Bethard
Chris Perkins wrote:
[snip implementation]
While I think that func(x, ...) is more readable than partial(func, x),
I'm not sure that I would use either of them often enough to warrant
special syntax.
Interesting.  Thought it might be worth listing a few of the current 
places people use lambdas (and lambda replacements like 
operator.attrgetter/itemgetter) that this might be useful, and a few of 
the places where it probably wouldn't be.

Places where it might be useful:
getting attributes:
lambda obj: obj.attr
attrgetter('attr')
getattr(__, attr)
getting attributes with defaults[1]:
objs.sort(key=lambda a: getattr(a, 'lineno', 0))
objs.sort(key=getattr(__, 'lineno', 0)
Places where you might be able to use it (with some changes):
using bound methods[1][2]:
map(lambda x: x.strip(), lst)
map(str.strip(), lst) #!! doesn't work for unicode
map(methodcaller('strip'), lst) # proposed by Alex Martelli
__.strip() # note that calling strip on __ would have to
   # return a curryable looking for one arg...
Places where I can't see how to use it:
creating a function out of nothing[2]:
button.setlabel(lambda: 'Click Me!')
button.setlabel('Click Me!'.__str__) # works 'cause str returns self
adding arguments[1]:
lambda x: 
adding method to an instance[1]:
self.plural = lambda n: int(n != 1)
So I guess it's a cool idea, but I don't know if it's really going to 
pacify anyone who is upset about losing lambda...  (Not that I'm 
suggesting that was your intention -- but it's something that's been 
recently on my mind.)

Steve
[1]http://mail.python.org/pipermail/python-list/2004-December/257990.html
[2]http://www.artima.com/forums/flat.jsp?forum=106thread=98196
--
http://mail.python.org/mailman/listinfo/python-list


PEP 309 (Partial Function Application) Idea

2005-03-11 Thread Chris Perkins
Random idea of the day: How about having syntax support for
currying/partial function application, like this:

func(..., a, b)
func(a, ..., b)
func(a, b, ...)

That is:
1) Make an Ellipsis literal legal syntax in an argument list.
2) Have the compiler recognize the Ellipsis literal and transform the
function call into a curried/parially applied function.

So the compiler would essentially do something like this:

func(a, ...) == curry(func, a)
func(..., a) == rightcurry(func, a)
func(a, ..., b) == rightcurry(curry(func,a), b)

I haven't though this through much, and I'm sure there are issues, but
I do like the way it looks.  The ... really stands out as saying
something is omitted here.


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


Re: PEP 309 (Partial Function Application) Idea

2005-03-11 Thread Steven Bethard
Chris Perkins wrote:
Random idea of the day: How about having syntax support for
currying/partial function application, like this:
func(..., a, b)
func(a, ..., b)
func(a, b, ...)
That is:
1) Make an Ellipsis literal legal syntax in an argument list.
2) Have the compiler recognize the Ellipsis literal and transform the
function call into a curried/parially applied function.
So the compiler would essentially do something like this:
func(a, ...) == curry(func, a)
func(..., a) == rightcurry(func, a)
func(a, ..., b) == rightcurry(curry(func,a), b)
I haven't though this through much, and I'm sure there are issues, but
I do like the way it looks.  The ... really stands out as saying
something is omitted here.
Interesting idea, but I have a feeling that it probably won't fly for a 
couple of reasons:

(1) The existing use of Ellipsis doesn't have anything to do with your 
suggested use.  I think people are generally opposed to giving 
keywords/symbols in Python two very different meanings.  This is one of 
the reasons Guido never liked the a, b, *c = iterable syntax.

(2) Emphasis recently on python-dev has been away from syntax changes 
and towards expansion of the standard library.  You would have to make a 
_very_ good case that the new syntax is merited.

Generally I do like the idea -- I think a lot of the cases that people 
have made for keeping lambda could be discarded with something like 
this...  But it'd need an extremely well thought out PEP (and an 
implementation of course) and even then, I wouldn't get my hopes up.

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