[Python-ideas] Reference variable in assignment: x = foo(?)

Haoyi Li haoyi.sg at gmail.com
Fri Jul 12 06:21:23 CEST 2013


If you look up "Lenses" in the context of Haskell/Scala, you'll see they're
something similar. It's not exactly the same, but the basic idea is to
reify a gettable/settable variable slot into a first class value. You can
then pass around the object to pass around the get/set-ability, or create
higher-order functions like transform that operate on the reified "slot":

// pseudo-scala to increment something; a macro like this doesn't exist
// but it wouldn't be too hard to write
lens(var).transform(_ + 1)              // increment a local
lens(var.member).transform(_ + 1) // increment a member
lens(var(0)(1)).transform(_ + 1)      // increment an array; array accesses
in scala use round braces

// could use operator overloading/implicits to make it more concise
var ** (_ + 1)              // increment a local

Generally these lenses are used for updating nested immutable data
structures (it gets really verbose/unDRY normally) but it's something
similar to what you want, so if you're looking for this sort of thing, that
would be the place to start. None of this is going to end up in python any
time soon, because it's all still pretty researchy and a solid
implementation is still more "PhD" rather than "weekend hack".

--------------------------------------------------------------------------------------------------------------------------

Another possible solution for the

value = expensive(b) if expensive(b) else default

problem, if you don't want a statement to assign to a temporary variable,
is to use a `let` expression

// raw version
value = (lambda res: res if res else default)(expensive(b))

// with a helper function `let`
value = let(expensive(b))(lambda res: res if res else default)

I'd get skewered at code review if i ever wrote this manually, but I've
actually used this quite a lot in auto-generated code (i.e. macros) where I
want to "assign" to a local value but am unable to create a statement. In
fact, if you want to you can forego assignments entirely in your program
and use nested `let` bindings for everything since they're basically
equivalent.

Then you can start putting the braces outside the `let(...)` as in `(let
...)` because you'll be basically be writing Lisp.

-Haoyi


On Fri, Jul 12, 2013 at 11:02 AM, Joao S. O. Bueno <jsbueno at python.org.br>wrote:

> On 11 July 2013 21:07, David Mertz <mertz at gnosis.cx> wrote:
> > On Thu, Jul 11, 2013 at 4:57 PM, Joao S. O. Bueno <jsbueno at python.org.br
> >
> > wrote:
> > > ...
> >> Like in:
> >>   value = expensive_function(b)  if expensive_function(b) else
> >> default_value
> >>
> >> (of course this is a trivial example - but nonetheless it would require
> an
> >> extra "if" statement to avoid the double call)
> >
> >
> > How about:
> >
> >   value = expensive_function(b) or default_value
> >
> > One call, exact same behavior as you request.  Available since Python
> 1.0.
>
> Because, as a I said, that was a naive example - if the predicate was:
>   value = expensive_function(b)  if expensive_function(b)  > threshold
> else  default_value
>
> There is no way "or" would work -
> Anyway - just forget about it -let's see where this e-mail thread leads
>
> (I worked around this particular issue with a couple of helper simple
> functions
> to push the value to a list and return it back )
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> http://mail.python.org/mailman/listinfo/python-ideas
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20130712/e78418a0/attachment.html>


More information about the Python-ideas mailing list