Thank you very much for your reply!

 

I wasn't familiar with MacroPy. It's a good idea to implement NSE using it. I'll work on it.

 

Sometimes it's necessary not to evaluate the expression. Two such applications of NSE in R are as follows:

 

1. Data-tables have cleaner syntax. For example, letting dt be a data-table with a column called price, one can retrieve items cheaper than $1 using the following: dt [price < 1]. Pandas syntax requires something like dt[dt.price < 1]. This is currently inevitable as the expression is evaluated *before* __getitem__ is invoked. Using NSE, dt.__getitem__ can, first, add its columns to locals() dictionary and then evaluate the expression in the new context.

 

2. Pipe-lining in R is also much cleaner. Dplyr provided an operator %>% which passes the return value of its LHS as the first argument of its RHS. In other words, f() %>% g() is equivalent to g(f()). This is pretty useful for long pipelines. The way that it works is that the operator %>% changes AST and then evaluates the modified expression. In this example, evaluating g() is undesirable.

 

 

From: Andrew Barnert <abarnert@yahoo.com>
Date: Saturday, July 13, 2019 at 4:26 PM
To: Nima Hamidi <hamidi@stanford.edu>
Cc: "python-ideas@python.org" <python-ideas@python.org>
Subject: Re: [Python-ideas] Non-standard evaluation for Python

 

On Jul 13, 2019, at 12:16, Nima Hamidi <hamidi@stanford.edu> wrote:

 

In the following, I sketch how I think this can be implemented:

  1. Let BoundExpression be a class containing an ast.Expression as well as locals and globals dictionaries. BoundExpression can also have an eval method that evaluates its expression using its locals and globals dictionaries.
  2. Let `x` be the short form for BoundExpression("x", locals(), globals()). Then, the plot function can be implemented in a way that plot(`x`, `y`) draws scatter plot of x and y and also, labels the axes correctly. No need to provide labels explicitly anymore.
  3.  A more challenging idea is to let developers decide whether their functions need NSE or not. For example, when a function is defined as def f(`x`), for any method call like f(x), the first argument should be wrapped with a BoundExpression instance.

Would it be easy to build something like this on top of a more general macro system, like MacroPy? If so, you could create a proof of concept using existing Python and get useful feedback. As it is, with just an explanation and a single example, it’s hard to really evaluate the idea.

 

Also, what happens if the expression contains, say, a := assignment? In that case, calling eval against locals() doesn’t have the same effect as normal evaluation. Is that a problem, or is that behavior that people would and should expect when they ask for a bound expression instead of a value?

 

In your example, it seems like you could evaluate it normally and pass in the value along with the AST, avoiding that problem, and making everything a lot simpler. I can imagine uses where that wouldn’t be sufficient, but they all seem like the kind of thing that demands a full macro system, so I’m not sure they’re relevant. Do you have examples where you need to eval on demand?

 

For that matter, it seems like your example could be handled by just defining `x` to mean, say, ('x', x), without needing a live AST at all. What are the examples where the string form of the expression isn’t sufficient but this proposal is?