Re: A friendlier, sugarier lambda -- a proposal for Ruby-like blocks in python

2006-10-17 Thread Theerasak Photha
On 14 Oct 2006 09:25:00 -0700, Paul Boddie [EMAIL PROTECTED] wrote:

 Unlike Java, Python's first class functions and
 methods are already highly useful for callback-based systems

Curious: how well does the use of returning inner functions work as a
strategy for providing effectively 'anonymous' callbacks? e.g.

def outer(x):
  def inner(y):
...
  return inner

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


Re: A friendlier, sugarier lambda -- a proposal for Ruby-like blocks in python

2006-10-17 Thread Paul Boddie
Theerasak Photha skrev:
 On 14 Oct 2006 09:25:00 -0700, Paul Boddie [EMAIL PROTECTED] wrote:

  Unlike Java, Python's first class functions and
  methods are already highly useful for callback-based systems

 Curious: how well does the use of returning inner functions work as a
 strategy for providing effectively 'anonymous' callbacks? e.g.

 def outer(x):
   def inner(y):
 ...
   return inner

Well enough, I'd imagine. There may be people who resent having to use
a statement to create a block of code, especially one which defines a
local name (the horror!), but as the lambda replacement discussions
showed, a sub-statement code block doesn't necessarily have an
acceptable formulation in non-Lisp-like languages. Or, at least, people
struggled to find such a formulation in Python which didn't severely
affect readability, and there are people who regard even
uncontroversial but related things as list comprehensions as being much
less readable than most other constructs in the language.

Paul

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


Re: A friendlier, sugarier lambda -- a proposal for Ruby-like blocks in python

2006-10-16 Thread Bruno Desthuilliers
Paul Boddie wrote:
 Kay Schluehr wrote:
 Spreading tiny function definitions all over the code
 may be finally not such a good idea compared with a few generic methods
 that get just called? OO might run out of fashion these days but Python
 is not Java and Pythons OO is pretty lightweight.
 
 I think you've successfully identified a recent trend in Python
 development: the abandonment of fairly transparent object-oriented
 techniques in favour of more opaque but supposedly more convenient
 hybrid techniques. 

Just for the record : Ruby's code-blocks (closures, really) come from
Smalltalk, which is still the OneTrueObjectLanguage(tm).


-- 
bruno desthuilliers
python -c print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in '[EMAIL PROTECTED]'.split('@')])
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: A friendlier, sugarier lambda -- a proposal for Ruby-like blocks in python

2006-10-16 Thread Kay Schluehr
Bruno Desthuilliers wrote:

 Just for the record : Ruby's code-blocks (closures, really) come from
 Smalltalk, which is still the OneTrueObjectLanguage(tm).

IsTheOneTrueObjectLanguage(tm)ReallyCamelCased?

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


Re: A friendlier, sugarier lambda -- a proposal for Ruby-like blocks in python

2006-10-16 Thread Bruno Desthuilliers
Kay Schluehr wrote:
 Bruno Desthuilliers wrote:
 
 Just for the record : Ruby's code-blocks (closures, really) come from
 Smalltalk, which is still the OneTrueObjectLanguage(tm).
 
 IsTheOneTrueObjectLanguage(tm)ReallyCamelCased?
 
ThatsAGoodQuestion.

DoYouMeanIsTheIdentifierTheOneTrueObjectLanguage(tm)CamelCasedOrIsTheObjectObjectBoundToIdentifierTheOneTrueObjectLanguage(tm)CamelCasedOrYetSomethingElse?

-- 
bruno desthuilliers
python -c print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in '[EMAIL PROTECTED]'.split('@')])
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: A friendlier, sugarier lambda -- a proposal for Ruby-like blocks in python

2006-10-16 Thread jmdeschamps

Bruno Desthuilliers wrote:
 Kay Schluehr wrote:
  Bruno Desthuilliers wrote:
 
  Just for the record : Ruby's code-blocks (closures, really) come from
  Smalltalk, which is still the OneTrueObjectLanguage(tm).
 
  IsTheOneTrueObjectLanguage(tm)ReallyCamelCased?
 
 ThatsAGoodQuestion.

 DoYouMeanIsTheIdentifierTheOneTrueObjectLanguage(tm)CamelCasedOrIsTheObjectObjectBoundToIdentifierTheOneTrueObjectLanguage(tm)CamelCasedOrYetSomethingElse?

 --
 bruno desthuilliers
 python -c print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
 p in '[EMAIL PROTECTED]'.split('@')])
youGuysAreAllCrazyOrSomethingNicer(CrazyBeingANiceAttributeHere)(ButIDon'tKnowAboutSyncategoremasLikeParenthesisOrApostrophe)InCamelBackNotationWhichAsNothingToDoWithPolishReverseNotation)ThankYou

Jean-Marc

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


Re: A friendlier, sugarier lambda -- a proposal for Ruby-like blocks in python

2006-10-15 Thread Kay Schluehr
Paul Boddie wrote:
 Kay Schluehr wrote:
 
  Spreading tiny function definitions all over the code
  may be finally not such a good idea compared with a few generic methods
  that get just called? OO might run out of fashion these days but Python
  is not Java and Pythons OO is pretty lightweight.

 I think you've successfully identified a recent trend in Python
 development: the abandonment of fairly transparent object-oriented
 techniques in favour of more opaque but supposedly more convenient
 hybrid techniques. Unlike Java, Python's first class functions and
 methods are already highly useful for callback-based systems - such
 systems in Java suffer from interface proliferation and needless
 one-off class definitions - but it seems to me that the subsequent
 language evolution in favour of anonymous blocks brings fewer benefits
 and can, as you say, diminish readability.

I was actually more concerned about extensibility than readability.
Talking about classes being lightweight I mentioned classes to be
first-class objects and intended constructions like this:

class fetchPage_event(fetchPage('http://python.org')):
def _showResponse(self, response)
print fancy formatting: %s % response.text

where all the registration and framework magics happens when the
fetchPage_event class is created. Adding callbacks just happen when
you add a method to the class. Here you have your block with no
additional syntax. You can pass the fetchPage_event class around and
add and overwrite methods in subclasses in the same fashion. A subclass
can be created within any statement on the fly etc. Here you have an OO
solution that is both short and has a clean design.

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


Re: A friendlier, sugarier lambda -- a proposal for Ruby-like blocks in python

2006-10-15 Thread Kay Schluehr
[EMAIL PROTECTED] wrote:
 Kay Schluehr wrote:
  The with statement is already implemented in Python 2.5.
 
  http://docs.python.org/whatsnew/pep-343.html
 
  The main difference between the with statement and Ruby blocks is that
  the with-statement does not support loops. Yielding a value of a
  function decorated with a contextmanager and passing it to the BLOCK of
  the with statement is essentially a one-shot. Therefore you can't use
  the with statement to define iterators. It is not a lightweight visitor
  pattern replacement as it is in Ruby. Hence the with- and the
  for-statement are orthogonal to each other in Python.

 Thanks or the What's-New link, it clarified things for me.  So there
 are several ways to do things with code blocks now in python..
  * for/while define loops around their blocks
  * if defines contional control into its block
  * with defines startup/cleanup context surrounding its block

 Twisted addCallback() is a different pattern than either of these.  The
 code is deferred to execute at some later time.  If there are many more
 patterns of things you could want to do with a block, it might be nice
 to have a blocks-are-closures mechanism.

That's true. As I mentioned in my response to Paul Boddie I do think it
is a poor solution even in Ruby(!) but I agree that given the situation
we just have with poorly designed application frameworks ( no illusion:
they won't ever go away and I do not pretend to be smarter and doing it
better in any case ) blocks are a quite nice feature for providing ad
hoc solutions. I consider them as somewhat aligned with a
worse-is-better philosophy.



I recently created an extended lambda as an example for my EasyExtend
language extension framework for Python. These kind of showcases are,
at least for me, important for getting programming practice within the
system and explore and extend the framework. The two things I cared
about when altering the semantics of lambda were:
1) Enabling multiple expressions separated by ';'
2) Enabling so called simple statements

Python does not only distinguish between expressions and statements but
also between simple and compound statements within its grammar
description. A compound statement is typically multiline and contains a
block. A simple statement is something like print, exec, raise or
assert containing no block. So I actually extended lambda to the limit
of an anonymous closure containing no block.

One might take this into consideration and alter the premises. But this
would be up to you, breno. At the moment I do not recommend using EE
because it is under heavy reconstruction but for the not so distant
future ( end of november is my personal deadline for the next release )
I recommend taking a look on it by anyone who aims to walk the RoR path
of a customized domain specific language for Python. For those who are
dilligent there are will be quite a lot of examples. For some it might
be even fun.

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


Re: A friendlier, sugarier lambda -- a proposal for Ruby-like blocks in python

2006-10-15 Thread [EMAIL PROTECTED]
Alexey Borzenkov wrote:
 [EMAIL PROTECTED] wrote:
  but maybe it reduces code readabilty a bit for people
  that have just started to program:
 
  mul2 = def(a, b):
  return a * b
 
  Instead of:
 
  def mul2(a, b):
  return a * b

 For such simple cases, yes. What about:

   button.click += def(obj):
 # do stuff

 You obviously can't:

   def button.click(obj):
 # do stuff

 :-) And if you make intermediate function and then assign it somewhere,
 it pollutes namespace: it's still left there, unneeded.

If you're really uptight about it you can
def temp_function(...):
  
button.click = temp_function
del(temp_function)

But for something like the example I'd probably just use a local name
wherever the definition is needed; there's no namespace pollution in
any meaningful sense then.

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


Re: A friendlier, sugarier lambda -- a proposal for Ruby-like blocks in python

2006-10-15 Thread Steven D'Aprano
On Sat, 14 Oct 2006 09:00:53 +, James Stroud wrote:

  Compared to the Python I know and love, Ruby isn't quite the same.
  However, it has at least one terrific feature: blocks.

[snip 220-odd quoted lines]

 http://mail.python.org/pipermail/python-list/2004-April/215805.html


Hi James,

You seem to have mislaid your snipper. It is very useful for when you're
replying to a very large post, and all you want to do is add a single line
at the end. It reduces frustration in readers who find themselves
scrolling, and scrolling, and scrolling, and scrolling through quoted text
they've already read, wondering why you've quoted all this stuff if you
aren't actually commenting on it, and prevents readers from unfairly
dismissing you as just another metoobie.



-- 
Steven.

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


Re: A friendlier, sugarier lambda -- a proposal for Ruby-like blocks in python

2006-10-14 Thread Kay Schluehr
[EMAIL PROTECTED] wrote:

 But [embedding a definition, ks] is awkward since the lambda is constrained 
 to be one
 line; you
 can't come back later and add much to the callback's code.
 Furthermore, this example isn't even legal, because 'print' isn't a
 function, but a statement -- lambda is further constrained to only
 contain an expression.

 Many have complained about this crippled-ness of lambda, but it
 actually makes some sense.  Since Python uses colons and indentation to
 define blocks of code, it would be awkward to close a multiline lambda.
  The best I could think of would look like

 deferred.addCallback(lambda r:
 print(fancy formatting %s % r.text)
 )

 ^
 |

 That trailing paranthesis is WAY un-Pythonic.

Maybe it is not common place because some users are underinformed and
hypnotized by whitespace semantics but you can add a trailing backslash
to achieve line coninuation within a single expression:

 deferred.addCallback(lambda r:  puts(fancy formatting %s \
... ))

This works syntactically.

[...]

 There might be some sort of overlap with PEP 343 and the 'with'
 statement, but I'm not sure exactly.  Sorry I'm late to the game and
 commenting on last year's PEP's, but I've only started reading them.
 Note that PEP's 343 and 340 are very focused on resource management --
 but I think that letting one define code blocks as closures could make
 resource handling routines be easily written in Python.

The with statement is already implemented in Python 2.5.

http://docs.python.org/whatsnew/pep-343.html

The main difference between the with statement and Ruby blocks is that
the with-statement does not support loops. Yielding a value of a
function decorated with a contextmanager and passing it to the BLOCK of
the with statement is essentially a one-shot. Therefore you can't use
the with statement to define iterators. It is not a lightweight visitor
pattern replacement as it is in Ruby. Hence the with- and the
for-statement are orthogonal to each other in Python.

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


Re: A friendlier, sugarier lambda -- a proposal for Ruby-like blocks in python

2006-10-14 Thread Paul Rubin
[EMAIL PROTECTED] writes:
 deferred = fetchPage('http://python.org')
 def _showResponse(response)
 print fancy formatting: %s % response.text
 deferred.addCallback(_showResponse)
 
 Lots of Twisted code has to be written backwards like this.

But that's just ugly.  The fetchPage function should take the callback
as an argument.  In an asynchronous system it would even be buggy.
What happens if the page fetch completes before you add the callback?
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: A friendlier, sugarier lambda -- a proposal for Ruby-like blocks in python

2006-10-14 Thread Kay Schluehr
Paul Rubin wrote:
 [EMAIL PROTECTED] writes:
  deferred = fetchPage('http://python.org')
  def _showResponse(response)
  print fancy formatting: %s % response.text
  deferred.addCallback(_showResponse)
 
  Lots of Twisted code has to be written backwards like this.

 But that's just ugly.  The fetchPage function should take the callback
 as an argument.  In an asynchronous system it would even be buggy.
 What happens if the page fetch completes before you add the callback?

As long as the fetchPage object does not start fetching right after
being constructed but only after applying an additional activate()
method the code is not buggy. I'm not sure about this design either. Is
_showResponse really that characteristic for fetchPage that it can't be
an object method? Spreading tiny function definitions all over the code
may be finally not such a good idea compared with a few generic methods
that get just called? OO might run out of fashion these days but Python
is not Java and Pythons OO is pretty lightweight.

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


Re: A friendlier, sugarier lambda -- a proposal for Ruby-like blocks in python

2006-10-14 Thread Marc 'BlackJack' Rintsch
In [EMAIL PROTECTED], Kay Schluehr
wrote:

 [EMAIL PROTECTED] wrote:
 
 Many have complained about this crippled-ness of lambda, but it
 actually makes some sense.  Since Python uses colons and indentation to
 define blocks of code, it would be awkward to close a multiline lambda.
  The best I could think of would look like

 deferred.addCallback(lambda r:
 print(fancy formatting %s % r.text)
 )

 ^
 |

 That trailing paranthesis is WAY un-Pythonic.
 
 Maybe it is not common place because some users are underinformed and
 hypnotized by whitespace semantics but you can add a trailing backslash
 to achieve line coninuation within a single expression:
 
 deferred.addCallback(lambda r:  puts(fancy formatting %s \
 ...   ))
 
 This works syntactically.

It works just fine without the trailing backslash.  A logical line does
not end until all opened parenthesis and brackets are matched by their
closing counterpart.

Ciao,
Marc 'BlackJack' Rintsch
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: A friendlier, sugarier lambda -- a proposal for Ruby-like blocks in python

2006-10-14 Thread Duncan Booth
Paul Rubin http://[EMAIL PROTECTED] wrote:

 [EMAIL PROTECTED] writes:
 deferred = fetchPage('http://python.org')
 def _showResponse(response)
 print fancy formatting: %s % response.text
 deferred.addCallback(_showResponse)
 
 Lots of Twisted code has to be written backwards like this.
 
 But that's just ugly.  The fetchPage function should take the callback
 as an argument.  In an asynchronous system it would even be buggy.
 What happens if the page fetch completes before you add the callback?

Or it should be trivial to give deferred a decorator method and write:

@deferred.callback
def _showResponse(response):
...

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


Re: A friendlier, sugarier lambda -- a proposal for Ruby-like blocks in python

2006-10-14 Thread James Stroud
[EMAIL PROTECTED] wrote:
 Hi all --
 
 Compared to the Python I know and love, Ruby isn't quite the same.
 However, it has at least one terrific feature: blocks.  Whereas in
 Python a
 block is just several lines of locally-scoped-together code, in Ruby
 a
 block defines a closure (anonymous function).  To avoid confusion
 let's call
 them Ruby block-closures.  I see them as just a syntax for defining
 closures
 and passing them into method calls.  I think something analogous could
 be added
 to Python in a very simple manner that would make closures much more
 readable
 and usable, and nail some use cases nicely.
 
 To define a new closure and pass it into a function call, there are two
 current
 methods: inline 'def' and 'lambda'.  Consider the following Twisted-ish
 code:
 
 deferred = fetchPage('http://python.org')
 def _showResponse(response)
 print fancy formatting: %s % response.text
 deferred.addCallback(_showResponse)
 
 Lots of Twisted code has to be written backwards like this.
 Theoretically, it
 might be nice to use lambda right in the addCallback() call, like:
 
 deferred.addCallback(lambda r:  print(fancy formatting %s
 %r.text) )
 
 But this is awkward since the lambda is constrained to be one line; you
 can't
 come back later and add much to the callback's code.  Furthermore, this
 example
 isn't even legal, because 'print' isn't a function, but a statement --
 lambda
 is further constrained to only contain an expression.
 
 Many have complained about this crippled-ness of lambda, but it
 actually makes
 some sense.  Since Python uses colons and indentation to define blocks
 of code,
 it would be awkward to close a multiline lambda.  The best I could
 think of
 would look like
 
 deferred.addCallback(lambda r:
 print(fancy formatting %s % r.text)
 )
 
 ^
 |
 
 That trailing paranthesis is WAY un-Pythonic.  We don't close code
 blocks like
 that!  And in general, declaring big multiline anonymous functions in
 the
 middle of a list of normal variable arguments is weird -- it just
 doesn't fit.
 It's perfectly legal to pass in 4 closures, interspersed with number
 and string
 arguments.  Imagine defining all of those inline with 'lambda'
 expressions!
 And what about nesting?  And then there's the term lambda, while a
 great
 homage to Lisp and computation theory, just isn't the friendliest
 programming
 vocab term.
 
 (from my limited understanding,) Ruby block-closures assume a specific
 use
 case: You want to pass exactly one multiline, defined-right-there
 closure to a
 method when calling it.  Therefore, you should get to define the
 closure
 *immediately following* the method call.  I suggest a Python version
 with a
 keyword 'using' (or 'with'?) that takes the block of code as a closure,
 and
 passes it to the method call as the *last argument*.  The above example
 becomes:
 
 deferred.addCallback() using response:
 print fancy formatting %s % response.text
 
 and in general, the following two code snippets are equivalent:
 
 
 def _f(x,y):
 [do stuff with x and y]
 function_with_callback(a,b,c, _f)
 
 function_with_callback(a,b,c) using x,y:
 [do stuff with x and y]
 next_statement()
 
 ... where function_with_callback wants a 2-arg function as its last
 argument.
 It gets to call _f, or equivalently the defined-right-there
 closure/ruby-block,
 however it wants to -- wait for an I/O operation to finish, whatever.
 I'm not
 so hot about the fact that it looks like addCallback() should be
 completed
 before the 'using' keyword kicks in, but this is the simplest I could
 think of.
 
 This syntax does not let you define a new function and store it as a
 local
 variable.  Python already has inline 'def' for that (that is, you can
 do a
 'def' in any block of code you want, and it stays local to that scope.)
  It
 does not, strictly speaking, let you do anything new -- as Guido has
 stated,
 you could ditch lambda and achieve the equivalent by declaring the
 little
 callback function as an inline 'def', like in the first deferred
 example here.
 
 This only optimizes for the case of defining a closure only for the
 purpose of
 passing it in as an argument to a method.  However, this must be the
 only use
 for anonymous functions in Python, since we already have inline 'def'.
 I've
 always felt that passing in a lambda in lisp and python, or the
 equivalent
 anonymous function(x,y) {} in javascript, or anonymous classes in java,
 was
 always awkward.  You have to think about defining a new anonymous
 function
 *within* your method call and such, and then you have to close
 parantheses
 after it -- it's just weird, I dunno.
 
 This proposal could also handle some of the use cases mentioned in PEP
 310 and
 340.  If you design your callback-taking functions to have only one
 callback
 and have it as the last argument, you can trivially write lock
 acquition (omit
 'using' for a no-arg block-closure):

Twisted Deferreds (was: Re: A friendlier, sugarier lambda -- a proposal for Ruby-like blocks in python)

2006-10-14 Thread Bjoern Schliessmann
Paul Rubin wrote:

 But that's just ugly.  The fetchPage function should take the
 callback as an argument.  In an asynchronous system it would even
 be buggy. 

It won't, in my understanding/experience, since the local context
must first terminate before the reactor takes control again and
handles other events. Twisted isn't concurrent like using threads
here, and adding callbacks immediately after getting a Deferred
instance returned is common practice.

 What happens if the page fetch completes before you add the 
 callback?

If the Deferred is fired, all already added {call,err}backs will be
executed. If you add new ones at this point, they'll be executed
immediately. IIRC.

http://twistedmatrix.com/projects/core/documentation/howto/async.html
http://twistedmatrix.com/projects/core/documentation/howto/defer.html

Regards,


Björn

-- 
BOFH excuse #12:

dry joints on cable plug

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


Re: A friendlier, sugarier lambda -- a proposal for Ruby-like blocks in python

2006-10-14 Thread Paul Boddie
Kay Schluehr wrote:

 Spreading tiny function definitions all over the code
 may be finally not such a good idea compared with a few generic methods
 that get just called? OO might run out of fashion these days but Python
 is not Java and Pythons OO is pretty lightweight.

I think you've successfully identified a recent trend in Python
development: the abandonment of fairly transparent object-oriented
techniques in favour of more opaque but supposedly more convenient
hybrid techniques. Unlike Java, Python's first class functions and
methods are already highly useful for callback-based systems - such
systems in Java suffer from interface proliferation and needless
one-off class definitions - but it seems to me that the subsequent
language evolution in favour of anonymous blocks brings fewer benefits
and can, as you say, diminish readability.

Of course, there are other similar areas in recent Python development.
Nested functions appear to eliminate the need for one-off classes:

def f(x):# class f:
  def g(y):  #   def __init__(self, x):
return op(x, y)  # self.x = x
  return g   #   def __call__(self, y):
g = f(a) # return op(self.x, y)
 # g = f(a)

Generators could be replaced by classes whose objects would act as
state machines. Here, the readability permitted by the enhancement is
significantly greater than that permitted by the language prior to the
introduction of the enhancement, although there may be cases where
state machines are more instructive representations in understanding a
system.

Generally, though, such enthusiasm for reducing the number of
keypresses involved in implementing something often seems to deny how
concise Python code already is in many situations.

Paul

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


Re: A friendlier, sugarier lambda -- a proposal for Ruby-like blocks in python

2006-10-14 Thread brenocon
Kay Schluehr wrote:
 The with statement is already implemented in Python 2.5.

 http://docs.python.org/whatsnew/pep-343.html

 The main difference between the with statement and Ruby blocks is that
 the with-statement does not support loops. Yielding a value of a
 function decorated with a contextmanager and passing it to the BLOCK of
 the with statement is essentially a one-shot. Therefore you can't use
 the with statement to define iterators. It is not a lightweight visitor
 pattern replacement as it is in Ruby. Hence the with- and the
 for-statement are orthogonal to each other in Python.

Thanks or the What's-New link, it clarified things for me.  So there
are several ways to do things with code blocks now in python..
 * for/while define loops around their blocks
 * if defines contional control into its block
 * with defines startup/cleanup context surrounding its block

Twisted addCallback() is a different pattern than either of these.  The
code is deferred to execute at some later time.  If there are many more
patterns of things you could want to do with a block, it might be nice
to have a blocks-are-closures mechanism.

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


Re: A friendlier, sugarier lambda -- a proposal for Ruby-like blocks in python

2006-10-14 Thread Alexey Borzenkov
[EMAIL PROTECTED] wrote:
 Compared to the Python I know and love, Ruby isn't quite the same.
 However, it has at least one terrific feature: blocks.

Well, I particularly like how Boo (http://boo.codehaus.org) has done
it:

  func(a, b, c) def(p1, p2, p3):
stmts

I was so attached to these nameless def-forms that I was even shocked
when I found that this doesn't work in python:

  f = def(a, b):
return a*b

Another good feature of Boo, btw.

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


Re: A friendlier, sugarier lambda -- a proposal for Ruby-like blocks in python

2006-10-14 Thread bearophileHUGS
Alexey Borzenkov:
 I was so attached to these nameless def-forms that I was even shocked
 when I found that this doesn't work in python:
   f = def(a, b):
 return a*b
 Another good feature of Boo, btw.

I think Boo has some good things worth consideration (and maybe worth
to copy) and some bad things that I like less than Python ones.
Turning def and class into functions reduces the need of lambdas
(compared to a lambda the required return is the only thing in the way)
and I like it, but maybe it reduces code readabilty a bit for people
that have just started to program:

mul2 = def(a, b):
return a * b

Instead of:

def mul2(a, b):
return a * b

The lightweight Io language uses an even simpler approach, some
examples:
http://www.iolanguage.com/about/samplecode/
An example:

factorial := method(n, if(n == 1, 1, n * factorial(n - 1)))

The method function is used to define functions...

Bye,
bearophile

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


Re: A friendlier, sugarier lambda -- a proposal for Ruby-like blocks in python

2006-10-14 Thread Alexey Borzenkov
[EMAIL PROTECTED] wrote:
 but maybe it reduces code readabilty a bit for people
 that have just started to program:

 mul2 = def(a, b):
 return a * b

 Instead of:

 def mul2(a, b):
 return a * b

For such simple cases, yes. What about:

  button.click += def(obj):
# do stuff

You obviously can't:

  def button.click(obj):
# do stuff

:-) And if you make intermediate function and then assign it somewhere,
it pollutes namespace: it's still left there, unneeded.

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


A friendlier, sugarier lambda -- a proposal for Ruby-like blocks in python

2006-10-13 Thread brenocon
Hi all --

Compared to the Python I know and love, Ruby isn't quite the same.
However, it has at least one terrific feature: blocks.  Whereas in
Python a
block is just several lines of locally-scoped-together code, in Ruby
a
block defines a closure (anonymous function).  To avoid confusion
let's call
them Ruby block-closures.  I see them as just a syntax for defining
closures
and passing them into method calls.  I think something analogous could
be added
to Python in a very simple manner that would make closures much more
readable
and usable, and nail some use cases nicely.

To define a new closure and pass it into a function call, there are two
current
methods: inline 'def' and 'lambda'.  Consider the following Twisted-ish
code:

deferred = fetchPage('http://python.org')
def _showResponse(response)
print fancy formatting: %s % response.text
deferred.addCallback(_showResponse)

Lots of Twisted code has to be written backwards like this.
Theoretically, it
might be nice to use lambda right in the addCallback() call, like:

deferred.addCallback(lambda r:  print(fancy formatting %s
%r.text) )

But this is awkward since the lambda is constrained to be one line; you
can't
come back later and add much to the callback's code.  Furthermore, this
example
isn't even legal, because 'print' isn't a function, but a statement --
lambda
is further constrained to only contain an expression.

Many have complained about this crippled-ness of lambda, but it
actually makes
some sense.  Since Python uses colons and indentation to define blocks
of code,
it would be awkward to close a multiline lambda.  The best I could
think of
would look like

deferred.addCallback(lambda r:
print(fancy formatting %s % r.text)
)

^
|

That trailing paranthesis is WAY un-Pythonic.  We don't close code
blocks like
that!  And in general, declaring big multiline anonymous functions in
the
middle of a list of normal variable arguments is weird -- it just
doesn't fit.
It's perfectly legal to pass in 4 closures, interspersed with number
and string
arguments.  Imagine defining all of those inline with 'lambda'
expressions!
And what about nesting?  And then there's the term lambda, while a
great
homage to Lisp and computation theory, just isn't the friendliest
programming
vocab term.

(from my limited understanding,) Ruby block-closures assume a specific
use
case: You want to pass exactly one multiline, defined-right-there
closure to a
method when calling it.  Therefore, you should get to define the
closure
*immediately following* the method call.  I suggest a Python version
with a
keyword 'using' (or 'with'?) that takes the block of code as a closure,
and
passes it to the method call as the *last argument*.  The above example
becomes:

deferred.addCallback() using response:
print fancy formatting %s % response.text

and in general, the following two code snippets are equivalent:


def _f(x,y):
[do stuff with x and y]
function_with_callback(a,b,c, _f)

function_with_callback(a,b,c) using x,y:
[do stuff with x and y]
next_statement()

... where function_with_callback wants a 2-arg function as its last
argument.
It gets to call _f, or equivalently the defined-right-there
closure/ruby-block,
however it wants to -- wait for an I/O operation to finish, whatever.
I'm not
so hot about the fact that it looks like addCallback() should be
completed
before the 'using' keyword kicks in, but this is the simplest I could
think of.

This syntax does not let you define a new function and store it as a
local
variable.  Python already has inline 'def' for that (that is, you can
do a
'def' in any block of code you want, and it stays local to that scope.)
 It
does not, strictly speaking, let you do anything new -- as Guido has
stated,
you could ditch lambda and achieve the equivalent by declaring the
little
callback function as an inline 'def', like in the first deferred
example here.

This only optimizes for the case of defining a closure only for the
purpose of
passing it in as an argument to a method.  However, this must be the
only use
for anonymous functions in Python, since we already have inline 'def'.
I've
always felt that passing in a lambda in lisp and python, or the
equivalent
anonymous function(x,y) {} in javascript, or anonymous classes in java,
was
always awkward.  You have to think about defining a new anonymous
function
*within* your method call and such, and then you have to close
parantheses
after it -- it's just weird, I dunno.

This proposal could also handle some of the use cases mentioned in PEP
310 and
340.  If you design your callback-taking functions to have only one
callback
and have it as the last argument, you can trivially write lock
acquition (omit
'using' for a no-arg block-closure):

def protect(lock, f):
lock.acquire()
f()
lock.release()

protect(myLock):
[do stuff that needs myLock to be acquired]

Of course, 

Re: A friendlier, sugarier lambda -- a proposal for Ruby-like blocks in python

2006-10-13 Thread brenocon
[repost -- fixed formatting]
Hi all --

Compared to the Python I know and love, Ruby isn't quite the same.
However, it has at least one terrific feature: blocks.  Whereas in
Python a block is just several lines of locally-scoped-together code,
in Ruby a block defines a closure (anonymous function).  To avoid
confusion let's call them Ruby block-closures.  I see them as just a
syntax for defining closures and passing them into method calls.  I
think something analogous could be added to Python in a very simple
manner that would make closures much more readable and usable, and nail
some use cases nicely.

To define a new closure and pass it into a function call, there are two
current methods: inline 'def' and 'lambda'.  Consider the following
Twisted-ish code:

deferred = fetchPage('http://python.org')
def _showResponse(response)
print fancy formatting: %s % response.text
deferred.addCallback(_showResponse)

Lots of Twisted code has to be written backwards like this.
Theoretically, it might be nice to use lambda right in the
addCallback() call, like:

deferred.addCallback(lambda r:  print(fancy formatting %s
%r.text) )

But this is awkward since the lambda is constrained to be one line; you
can't come back later and add much to the callback's code.
Furthermore, this example isn't even legal, because 'print' isn't a
function, but a statement -- lambda is further constrained to only
contain an expression.

Many have complained about this crippled-ness of lambda, but it
actually makes some sense.  Since Python uses colons and indentation to
define blocks of code, it would be awkward to close a multiline lambda.
 The best I could think of would look like

deferred.addCallback(lambda r:
print(fancy formatting %s % r.text)
)

^
|

That trailing paranthesis is WAY un-Pythonic.  We don't close code
blocks like that!  And in general, declaring big multiline anonymous
functions in the middle of a list of normal variable arguments is weird
-- it just doesn't fit. It's perfectly legal to pass in 4 closures,
interspersed with number and string arguments.  Imagine defining all of
those inline with 'lambda' expressions!  And what about nesting?  And
then there's the term lambda, while a great homage to Lisp and
computation theory, just isn't the friendliest programming
vocab term.

(from my limited understanding,) Ruby block-closures assume a specific
use case: You want to pass exactly one multiline, defined-right-there
closure to a method when calling it.  Therefore, you should get to
define the closure *immediately following* the method call.  I suggest
a Python version with a keyword 'using' (or 'with'?) that takes the
block of code as a closure, and passes it to the method call as the
*last argument*.  The above example becomes:

deferred.addCallback() using response:
print fancy formatting %s % response.text

and in general, the following two code snippets are equivalent:

def _f(x,y):
[do stuff with x and y]
function_with_callback(a,b,c, _f)

function_with_callback(a,b,c) using x,y:
[do stuff with x and y]
next_statement()

... where function_with_callback wants a 2-arg function as its last
argument.  It gets to call _f, or equivalently the defined-right-there
closure/ruby-block, however it wants to -- wait for an I/O operation to
finish, whatever. I'm not so hot about the fact that it looks like
addCallback() should be completed before the 'using' keyword kicks in,
but this is the simplest I could think of.

This syntax does not let you define a new function and store it as a
local variable.  Python already has inline 'def' for that (that is, you
can do a 'def' in any block of code you want, and it stays local to
that scope.)  It does not, strictly speaking, let you do anything new
-- as Guido has stated, you could ditch lambda and achieve the
equivalent by declaring the
little callback function as an inline 'def', like in the first deferred
example here.

This only optimizes for the case of defining a closure only for the
purpose of passing it in as an argument to a method.  However, this
must be the only use for anonymous functions in Python, since we
already have inline 'def'. I've always felt that passing in a lambda in
lisp and python, or the equivalent anonymous function(x,y) {} in
javascript, or anonymous classes in java, was always awkward.  You have
to think about defining a new anonymous
function *within* your method call and such, and then you have to close
parantheses after it -- it's just weird, I dunno.

This proposal could also handle some of the use cases mentioned in PEP
310 and 340.  If you design your callback-taking functions to have only
one callback and have it as the last argument, you can trivially write
lock acquition (omit 'using' for a no-arg block-closure):

def protect(lock, f):
lock.acquire()
f()
lock.release()

protect(myLock):
[do stuff that needs myLock