Code blocks

Discussion in 'Python' started by David Mertz, Oct 13, 2003.

  1. David Mertz

    David Mertz Guest

    Back over in that same endless Lisp thread, the idea of codeblocks came
    up. Several variations were discussed, with some different opinions on
    just how ugly or bearable the syntax was (I don't think any of them
    registered as "wonderful" by anyone).

    I think that codeblocks, a la Ruby, Smalltalk, xBase, would be kinda
    nice to have. But the thing I like about them isn't really that they
    can be inlined, but rather simply that the operate without defining a
    new (nested) scope. Basically, codeblocks just amount to
    boilerplate--except possibly paramaterized... and shorter, of course.

    So for that, I would suggest a new scopeless pseudo-function syntax.
    E.g.:

    block foo(this, that, other):
    x = this+that
    y = this*other
    z = x // (y-that)

    Using this is like a function, but the names wind up in the calling
    namespace:

    def bar(someblock):
    a, b, c = (4, 5, 6)
    someblock(a,b,c)
    return x,y,z

    vals = bar(foo) #-> (9, 24, 0)

    That is, I have no desire for blocks to be nameless, just for them to be
    passable as first class objects.

    Yours, David...

    --
    mertz@ _/_/_/_/_/_/_/ THIS MESSAGE WAS BROUGHT TO YOU BY:_/_/_/_/ v i
    gnosis _/_/ Postmodern Enterprises _/_/ s r
    ..cx _/_/ MAKERS OF CHAOS.... _/_/ i u
    _/_/_/_/_/ LOOK FOR IT IN A NEIGHBORHOOD NEAR YOU_/_/_/_/_/ g s
    David Mertz, Oct 13, 2003
    #1
    1. Advertising

  2. David Mertz wrote:
    ...
    > So for that, I would suggest a new scopeless pseudo-function syntax.
    > E.g.:
    >
    > block foo(this, that, other):
    > x = this+that
    > y = this*other
    > z = x // (y-that)
    >
    > Using this is like a function, but the names wind up in the calling
    > namespace:


    Calling rather than defining? For some reason this seems strange
    to me. Maybe it's just the vague memory of dynamic scoping being
    a rather bad thing, but aren't there more use cases for affecting the
    defining scope (which you DO know intimately when you're defining)
    than for defining the calling scope (which in general you'd treat as a
    black box?

    > def bar(someblock):
    > a, b, c = (4, 5, 6)
    > someblock(a,b,c)
    > return x,y,z
    >
    > vals = bar(foo) #-> (9, 24, 0)
    >
    > That is, I have no desire for blocks to be nameless, just for them to be
    > passable as first class objects.


    Yes, renouncing namelessness could perhaps be a reasonable compromise.
    But let's consider use cases -- e.g. a "with this file" HOF. If a block's
    variables were in the _defining_ scope, I could change the current:

    def blahblah(filename):
    f = open(filename)
    try:
    x = someprocessingwith(f)
    y = somemorewith(f)
    finally:
    f.close()
    # proceed, using x and y

    into:

    def blahblah(filename):
    block computexy(f):
    x = someprocessingwith(f)
    y = somemorewith(f)
    do_with_file(filename, computexy)
    # proceed, using x and y

    using do_with_file as a black-box HOF, though it would typically be

    def do_with_file(filename, thecallable):
    f = open(filename)
    try:
    return thecallable(f)
    finally:
    f.close()

    and similarly for doing things while holding a lock, etc, etc. Basically,
    the kind of things you do with code-block passing in Smalltalk, Ruby &c.

    What different set of interesting use-cases would be enabled by
    having the block's apparently-local variables live in the namespace
    of the caller rather in that of the definer?


    Alex
    Alex Martelli, Oct 13, 2003
    #2
    1. Advertising

  3. David Mertz

    Simon Burton Guest

    On Mon, 13 Oct 2003 16:31:27 -0400, David Mertz wrote:

    ....
    > So for that, I would suggest a new scopeless pseudo-function syntax.
    > E.g.:
    >
    > block foo(this, that, other):
    > x = this+that
    > y = this*other
    > z = x // (y-that)
    >
    > Using this is like a function, but the names wind up in the calling
    > namespace:
    >
    > def bar(someblock):
    > a, b, c = (4, 5, 6)
    > someblock(a,b,c)
    > return x,y,z
    >
    > vals = bar(foo) #-> (9, 24, 0)
    >
    > That is, I have no desire for blocks to be nameless, just for them to be
    > passable as first class objects.
    >
    > Yours, David...


    Yeah, right on!
    I often hack code realtime, and wish i could name a chunk of code
    without having to return/accept huge (and often changing) tuples of stuff...

    Anyway, now that i think about this, it should be possible to lookup
    the calling context's locals and insert the current locals. Then
    wrap this in a function, "expose", say. One could even do this with
    the arguments and write an "absorb" function:


    def foo():
    absorb()
    x = this+that
    y = this*other
    z = x // (y-that)
    expose()

    Then maybe later on when the code has cooled down sufficiently, one could
    revert to the more informative args/return mechanics.

    Simon.
    Simon Burton, Oct 14, 2003
    #3
  4. David Mertz

    David Mertz Guest

    |> block foo(this, that, other):
    |> x = this+that
    |> y = this*other
    |> z = x // (y-that)
    |> def bar(someblock):
    |> a, b, c = (4, 5, 6)
    |> someblock(a,b,c)
    |> return x,y,z
    |> vals = bar(foo) #-> (9, 24, 0)

    |Anyway, now that i think about this, it should be possible to lookup
    |the calling context's locals and insert the current locals.
    | def foo():
    | absorb()
    | x = this+that
    | y = this*other
    | z = x // (y-that)
    | expose()

    It's not too hard to look up the call stack to GET the binding from the
    calling context. I.e.

    >>> def about_caller():

    ... import inspect
    ... print inspect.currentframe(1).f_locals
    ...
    >>> def somefunc():

    ... x, y, z = 1, 2, 3
    ... about_caller()
    ...
    >>> somefunc()

    {'y': 2, 'x': 1, 'z': 3}

    Actually, you could define this in a utility 'absorb()' function (which
    would look at 'currentframe(2)' instead of 1). The problem is that
    there's no good way to put values back INTO the calling context. So I
    can't see a way to write the 'expose()' function.

    Btw. In answer to Alex' concern about dynamic scoping--which admittedly
    my suggestion basically amounts to: I think the main use of a "block"
    (or whatever name might be used) is that certain code might be used
    between many local contexts. If you just define a block within a
    particular function 'spam()', that hardly helps you when you want to do
    the same steps in 'eggs()'.

    In a way, a block amounts to a poor-man's macro, since it IS an
    expansion of sorts. But to my mind, it isn't nearly as dangerous as
    macros can be. Then again, as I proposed it, it might be non-obvious
    when a call is to a block versus when it is to a function. So maybe
    some special syntax would be needed at the point of the call also.

    Of course, as I envision it, a block might also do a bit of inspection
    of its context (as in the 'about_caller()' function above)... so maybe
    it really is skating too close to the perils of macros, which Alex and I
    pretty much agree on.

    Yours, David...

    --
    mertz@ _/_/_/_/ THIS MESSAGE WAS BROUGHT TO YOU BY: \_\_\_\_ n o
    gnosis _/_/ Postmodern Enterprises \_\_
    ..cx _/_/ \_\_ d o
    _/_/_/ IN A WORLD W/O WALLS, THERE WOULD BE NO GATES \_\_\_ z e
    David Mertz, Oct 14, 2003
    #4
  5. On Mon, 13 Oct 2003 16:31:27 -0400, rumours say that
    (David Mertz) might have written:

    >I think that codeblocks, a la Ruby, Smalltalk, xBase, would be kinda
    >nice to have. But the thing I like about them isn't really that they
    >can be inlined, but rather simply that the operate without defining a
    >new (nested) scope. Basically, codeblocks just amount to
    >boilerplate--except possibly paramaterized... and shorter, of course.


    I had such an idea too, perhaps could be useful.

    The definition syntax I imagined was:
    <block_name>:
    # do something here
    pass

    and running the code block was:
    <block_name>

    that is, without the colon at the end.
    No scopes added, just a kind of code compilation and 'exec' use with
    syntactic sugar, so they could represent plain code objects.
    The block names are definitely local in a function (so the code snippet
    / block could do LOAD_FAST for the local variables it references), and
    no arguments would be allowed.

    That was my idea, but parts of it can be changed.

    For more info about implementation proposal, see:
    http://groups.google.com/groups?selm=
    --
    TZOTZIOY, I speak England very best,
    Ils sont fous ces Redmontains! --Harddix
    Christos TZOTZIOY Georgiou, Oct 17, 2003
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. John Cantley
    Replies:
    2
    Views:
    12,043
    ant177
    Dec 14, 2005
  2. Arjen
    Replies:
    3
    Views:
    424
    Scott Allen
    Feb 27, 2005
  3. Microsoft

    Controls that contain code: Code Blocks Not Supported

    Microsoft, Dec 14, 2005, in forum: ASP .Net Building Controls
    Replies:
    1
    Views:
    400
    Anthony Williams
    Dec 14, 2005
  4. matt
    Replies:
    1
    Views:
    238
    George Ogata
    Aug 6, 2004
  5. Steven Taylor
    Replies:
    9
    Views:
    235
    Brian Candler
    Apr 27, 2009
Loading...

Share This Page