The Artima Developer Community
Sponsored Link

Weblogs Forum
Language Design Is Not Just Solving Puzzles

27 replies on 2 pages. Most recent reply: May 7, 2011 1:04 PM by Richard Silverman

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 27 replies on 2 pages [ « | 1 2 ]
Kay Schluehr

Posts: 302
Nickname: schluehk
Registered: Jan, 2005

Re: Figure out the problem Posted: Feb 12, 2006 10:18 AM
Reply to this message Reply
Advertisement
> Maybe something like this...
>
> l=[1,2,3,4]
>
> def each(l):
> for i in l:
> yield i
>
>
> each(l)->(x):
> print x
>
> def fun(x):
> print x
>
> each(l)->fun

Marcin, if you look for Ruby like block functionality in Python 2.4 you will most likely define a function decorator for such a purpose. The one I describe here does not cover the block semantics of Ruby, of course, but it manages your example quite well.

def accept_block(func):
def wrap_generator(*args,**kwd):
gen = func(*args,**kwd)
def block_call(block=None):
if block:
res = gen.next()
try:
return block(res)
except TypeError:
return block(*res)
else:
return gen.next()
return block_call
return wrap_generator

@accept_block
def each(l):
for i in l:
yield i

# tribute to Ruby :)
import sys
puts = sys.stdout.write

>>> iter = each([1,2,3,4])
>>> iter()
1
>>> iter(lambda x: puts("Here's the next value: %s"x))
Here's the next value: 2

# small variant with block accepting two arguments

@accept_block
def each_and_succ(l):
for i in l:
yield i,i+1

>>> iter = each_and_succ([1,2,3,4])
>>> iter()
1,2
>>> iter(lambda x,y: puts("Next value: %s and its successor %s"%(x,y))
"Next value: 2 and its successor 3"


Kay

Steve Donovan

Posts: 24
Nickname: stevedonov
Registered: May, 2005

Re: Figure out the problem Posted: Feb 13, 2006 7:51 AM
Reply to this message Reply
The Boo approach to multiline lambdas involves a clever syntactical trick. If a function takes a function/closure as a last argument, then that argument can be specified directly as a def block:

sum = 0
newlist = map(range(0,10)) def (x):
sum += x
return sum

(This is in 'ducky' mode so that you don't have to declare x to have some specific type).

Of course, Boo also has inline closures:
squares = map(list,{x | x*x})
but this is not very Pythonic (altho Booish)

steve d.

Kay Schluehr

Posts: 302
Nickname: schluehk
Registered: Jan, 2005

Re: Figure out the problem Posted: Feb 13, 2006 9:50 AM
Reply to this message Reply
> The Boo approach to multiline lambdas involves a clever
> syntactical trick. If a function takes a function/closure
> as a last argument, then that argument can be specified
> directly as a def block:

> sum = 0
> newlist = map(range(0,10)) def (x):
> sum += x
> return sum

It shouldn't be hard in Python to create syntax for infinitely many different statements either.

At comp.lang.python variants where discussed such like this suite:

newlist = map(f, range(10)) with:
def f(x):
global sum
sum+=x
return sum

The main cause for this construction was nice syntax for properties. In Python 2.4 the descriptor functions seem to belong to the class and not to the property. The situation is comparable with decorator assignments before Python 2.4, where they had to be placed after the definition of the decorated function.

Nevertheless there is no way to turn this into expression syntax without trashing the language.

> (This is in 'ducky' mode so that you don't have to declare
> x to have some specific type).
>
> Of course, Boo also has inline closures:
> squares = map(list,{x | x*x})
> but this is not very Pythonic (altho Booish)

It looks nice but it reminds me of set-comprehension syntax.
If we want something that looks really lambda-like I would propose {x}.x*x

Kay

Guido van van Rossum

Posts: 359
Nickname: guido
Registered: Apr, 2003

Re: Figure out the problem Posted: Feb 13, 2006 12:27 PM
Reply to this message Reply
> sum = 0
> newlist = map(range(0,10)) def (x):
> sum += x
> return sum


How's that so much better than the existing solution, putting the def before the call? That way it isn't limited to the last argument either.

Steve Donovan

Posts: 24
Nickname: stevedonov
Registered: May, 2005

Re: Figure out the problem Posted: Feb 13, 2006 11:16 PM
Reply to this message Reply
> How's that so much better than the existing solution,
> putting the def before the call? That way it isn't
> limited to the last argument either.

It's true that the Boo map builtin is backwards for this very reason. It is a matter of taste; it reads better to have the applied function following the operation, especially as the block becomes larger.

Also, one doesn't have to name the damn function ;)

steve d.

Morel Xavier

Posts: 73
Nickname: masklinn
Registered: Sep, 2005

Re: Figure out the problem Posted: Feb 14, 2006 8:40 AM
Reply to this message Reply
>
> sum = 0
> > newlist = map(range(0,10)) def (x):
> > sum += x
> > return sum

>
> How's that so much better than the existing solution,
> putting the def before the call?
Well, the advantages of this solution could be listed as:

* removes the necessity to name the inner function (the anonymous one, called by the named function)
* more closely links the inner and the outer (map, filter, ...) functions, creating something like a single expression instead of two related expressions (function creation and function use)
* allows for the garbage collection of the anonymous function as soon as the outer function has been executed (yeah, it's extremely dubious i know)

> That way it isn't
> limited to the last argument either.
Which is the biggest drawback of the method (unless you want to use magic such as what I posted in an earlier post), that drawback nonetheless seems to have been fairly well accepted by the Boo and Ruby communities (Ruby works the same way, and does use magic to boot since the "block" argument has a specific prefix).

The biggest problem here is that the Boo version wouldn't be backwards compatible in python, every single function that could use it would have to be modified and (as I already pointed it) I'm not sure it'd play well with *args and **kwargs (I don't know how boo deals with that issue, steve, does it deal with it?)

Steve Donovan

Posts: 24
Nickname: stevedonov
Registered: May, 2005

Re: Figure out the problem Posted: Feb 14, 2006 10:36 PM
Reply to this message Reply
> I'm not sure it'd play well with *args and **kwargs

It doesn't play well, and there doesn't seem any way around that. Although you don't have to use *args so much in Boo since it's so easy to pass an array literal (which corresponds fairly closely to a tuple in Python).

The thing to note about def blocks in Boo is that they are expressions. So you'll also see this idiom a lot - it attaches an action to an event.


button.Clicked += def():
print "somebody clicked me"


steve d.

Eivind Eklund

Posts: 49
Nickname: eeklund2
Registered: Jan, 2006

Re: Figure out the problem Posted: Feb 17, 2006 3:30 AM
Reply to this message Reply
Guido wrote:
>> sum = 0
>> newlist = map(range(0,10)) def (x):
>> sum += x
>> return sum
>
> How's that so much better than the existing solution,
> putting the def before the call? That way it isn't limited
> to the last argument either.

In Ruby and Perl (evil though it is), I feel that I get benefit from having the code text follow how I think about this. I often (mostly?) end up using blocks or anonymous subs (perl) sort of the way I use the statement I give a "while" loop. Can you imagine having to define a method/function before calling "while", and then do while (expr, method)?

I can't say anything about how "Pythonic" something is - I came to Ruby before Python, and unfortunately haven't been able to motivate myself to learn Python yet.

Eivind.

Guido van van Rossum

Posts: 359
Nickname: guido
Registered: Apr, 2003

Re: Figure out the problem Posted: Feb 17, 2006 1:19 PM
Reply to this message Reply
[Eivind]
> In Ruby and Perl (evil though it is), I feel that I get
> benefit from having the code text follow how I think about
> this. I often (mostly?) end up using blocks or anonymous
> subs (perl) sort of the way I use the statement I give a
> "while" loop. Can you imagine having to define a
> method/function before calling "while", and then do while
> (expr, method)?

Python has a for loop which can iterate over a generator. If the callback is not squirreled away for later use (like a GUI callback) but just used "in-line" (like a Ruby foreach body or a Perl sort callback), in theory it should be possible to refactor the code that calls the callback to be a generator that yields to the body of the for loop. Especially in Python 2.5 where yield can also return an expression. Perhaps this would be another argument to implement "continue <expr>" after all, so the for-loop body block can use this to pass a value back to the generator.

Anyway, I believe that Python has other ways to prevent the awkward ordering that you mention.

Yet another approach (which works in any old Python version) would of course be to make the callback a method, and pass a bound method:
  def initialize(self):
some_object.set_callback(self.callback)

def self.callback(self):
<callback goes here>

David Conrad

Posts: 2
Nickname: dconrad
Registered: Feb, 2006

Re: Language Design Is Not Just Solving Puzzles Posted: Feb 27, 2006 2:45 PM
Reply to this message Reply
I absolutely agree that double-colon is nasty, and having an alternate way, like with braces, to define a block is unpythonic. But consider the following:

x = 7

Multi-line expression, now, in Python 2.4:

y = (x + 1 +
2 * x)

Multi-line, but not multi-statement, lambda, now, in Python 2.4:

f = (lambda n: n + 1 +
2 * n)

Multi-line lambda, repurposing comma inside the parens:

f = (lambda n: n = n + 1 +
2 * n, print n, return n)

I don't think this *quite* works, but maybe it will give someone some inspiration. I don't think you can classify it as completely unpythonic, because of the way parenthesized expressions can span lines already. I don't know where I could have possibly gotten the idea to wrap lambdas in parentheses....

Vladimir Goff

Posts: 2
Nickname: xonix
Registered: Mar, 2006

Re: Language Design Is Not Just Solving Puzzles Posted: Mar 5, 2006 6:46 PM
Reply to this message Reply
I think, that variant


newlist = map(f, range(10)) with:
def f(x):
global sum
sum+=x
return sum


that i saw in Kay Schluehr post is quite not bad, except that I think it is better to use the existing statment in rather then with. Thus we don't need to introduce a new key-word.

Here are some more examples of this construction:

#===================

a = map( f, [1,2,3] ) in:
def f(n):
print n
return n+1



#====================

def add_funcs( f1, f2, arg ):
return f1( arg ) + f2( arg )

sum = add_funcs( f1, f2, 5 ) in:
def f1(n):
return n+1
def f2(n):
return n**n



#======================

# Or even thus:

sum = add_funcs( f1, f2, 5 ) in:
def f1(n):
return n+1
def f2(n):
return n**n
def add_funcs( f1, f2, arg ):
return f1( arg ) + f2( arg )



#=======================

map( f, range(10) ) in:
def f(n):
print n,'*',n,'=',n*n

#=======================


The advantages of such approach are:
1) Functions are anonimous, that is they are not visible in outside scope.
2) Thus can be defined more then one anonimous function in one construction.
3) No new key-words are introduced in language

The fact, that we nevertheless have to name our anonimous functions doesn't seem unreasonable, because in list comprehensions we have also name intermediate element.

Disadvantages:
I don't see ones... Or am I wrong?

What you think?

Kenneth Tilton

Posts: 1
Nickname: demonkenny
Registered: May, 2006

Re: Language Design Is Not Just Solving Puzzles Posted: May 5, 2006 6:42 PM
Reply to this message Reply
"And there's the rub: there's no way to make a Rube Goldberg language feature appear simple. "

But the language feature is not RG if one is using parens or braces. So the RGism is the indentation-sensitivity, which is a neat idea but just does not scale to very handy apps such as multi-statement lambdas. well... you said it /could/ be made to work, but that it would be hard for the lexer.. hey, do I tell you my problems?

:)

kenny

Richard Silverman

Posts: 1
Nickname: continuum
Registered: May, 2011

Re: Language Design Is Not Just Solving Puzzles Posted: May 7, 2011 1:04 PM
Reply to this message Reply
> Mathematicians don't mind these -- a proof is a proof
> is a proof, no matter whether it contains 2 or 2000 steps,

This is complete nonsense, as any mathematician (including this one) will tell you. The elegance, economy, and methods of a proof are of paramount importance, which is reflected in the fact that researchers spend a great deal of time coming up with improvements or entirely new proofs of existing results. By simplifying a proof, we often come to a better understanding of the underlying ideas. By finding a completely different proof, we often connect the problem to other areas of mathematics and find new ways of thinking about existing constructs. And developing a new method of proof may help to attack many other problems, and ultimately prove more valuable than the original result.

> or requires an infinite-dimensional space to prove
> something about integers.

This is just silly. Just because a problem looks easy, doesn't mean that it is. A sixth-grader can understand the statement of Fermat's Last Theorem, but it took hundreds of years and cutting-edge, sophisticated 20th-century mathematics to finally conquer it. You're appealing to your audience's naive sense that scary-sounding "infinite-dimensional" spaces must be overkill for proving something about simple, ordinary integers. The fact is: the former are not all that complicated, and the integers are anything but simple.

Flat View: This topic has 27 replies on 2 pages [ « | 1  2 ]
Topic: Introducing the ScalaTest Shell: a DSL for the Scala Interpreter Previous Topic   Next Topic Topic: Windows 7 ... Kind of Rocks

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use