On 7 November 2016 at 02:32, Nathaniel Smith <[email protected]> wrote: > On Sun, Nov 6, 2016 at 5:06 AM, Eric V. Smith <[email protected]> wrote: >> Creating a new thread, instead of hijacking the PEP 532 discussion. >> >> From PEP 532: >> >>> Abstract >>> ======== >>> >>> Inspired by PEP 335, PEP 505, PEP 531, and the related discussions, this >>> PEP >>> proposes the addition of a new protocol-driven circuit breaking operator >>> to >>> Python that allows the left operand to decide whether or not the >>> expression >>> should short circuit and return a result immediately, or else continue >>> on with evaluation of the right operand:: >>> >>> exists(foo) else bar >>> missing(foo) else foo.bar() >> >> Instead of new syntax that only works in this one specific case, I'd prefer >> a more general solution. I accept being "more general" probably seals the >> deal in killing any proposal! >> >> I realize the following proposal has at least been hinted at before, but I >> couldn't find a specific discussion about it. Since it applies to the >> short-circuiting issues addressed by PEP 532 and its predecessors, I thought >> I'd bring it up here. It could also be used to solve some of the problems >> addressed by the rejected PEP 463 (Exception-catching expressions). See also >> PEP 312 (Simple Implicit Lambda). It might also be usable for some of the >> use cases presented in PEP 501 (General purpose string interpolation, aka >> i-strings). >> >> I'd rather see the ability to have unevaluated expressions, that can later >> be evaluated. I'll use backticks here to mean: "parse, but do not execute >> the enclosed code". This produces an object that can later be evaluated with >> a new builtin I'll call "evaluate_now". Obviously these are strawmen, and >> partly chosen to be ugly and unacceptable names and symbols in the form I'll >> discuss here. > > If we're considering options along these lines, then I think the local > optimum is actually a "quoted-call" operator, rather than a quote > operator. So something like (borrowing Rust's "!"): > > eval_else!(foo.bar, some_func()) > > being sugar for > > eval_else.__macrocall__(<unevaluated thunk of foo.bar>, > <unevaluated thunk of some_func()>) > > You can trivially use this to recover a classic quote operator if you > really want one: > > def quote!(arg): > return arg > > but IMO this way is more ergonomic for most use cases (similar to your > '&' suggestion), while retaining the call-site marking that "something > magical is happening here" (which is also important, both for > readability + implementation simplicity -- it lets the compiler know > statically when it needs to retain the AST, solving the issue that > Greg pointed out). > > Some other use cases: > > Log some complicated object, but only pay the cost of stringifying the > object if debugging is enabled: > > log.debug!(f"Message: {message_object!r}") > > Generate a plot where the axes are automatically labeled "x" and > "np.sin(x)" (this is one place where R's plotting APIs are more > convenient than Python's): > > import numpy as np > import matplotlib.pyplot as plt > x = np.linspace(0, 10) > plt.plot!(x, np.sin(x)) > > What PonyORM does, but without the thing where currently their > implementation involves decompiling bytecode...: > > db.select!(c for c in Customer if sum(c.orders.price) > 1000) > > Filtering out a subset of rows from a data frame in pandas; 'height' > and 'age' refer to columns in the data frame (equivalent to > data_frame[data_frame["height"] > 100 and data_frame["age"] < 5], but > more ergonomic and faster (!)): > > data_frame.subset!(height > 100 and age < 5) > > (IIRC pandas has at least experimented with various weird lambda hacks > for this kind of thing; not sure what the current status is.) > > Every six months or so I run into someone who's really excited about > the idea of adding macros to python, and I suggest this approach. So > far none of them have been excited enough to actually write a PEP, but > if I were going to write a PEP then this is the direction that I'd > take :-). >
Oh great! Good to know I am not alone thinking in this direction. I have however one minor problem here: the problem is that "!" sign is almost invisible in the code, unless there is syntax highlighting which paints it in some very bright color. On the other hand I am not sure if it *must* be very visible... So to make it more distinctive in code I would propose something like: macros<>( x, y ) macros>( x, y ) macros::( x, y ) And those are already used operators, sad :( It would look so neat... But probably still possible to do? Mikhail _______________________________________________ Python-ideas mailing list [email protected] https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
