［翻訳］lazyeval vignette: 非標準評価

この文書は Hadley Wickham によるRパッケージ [`lazyeval`](https://cran.r-project.org/web/packages/lazyeval/) (version 0.2.0) のビネット "[Non-standard evaluation](https://cran.r-project.org/web/packages/lazyeval/vignettes/lazyeval.html)" の日本語訳です．
文中の注は原著者によるものと訳者によるものがあり，訳者によるものには__［訳注］__マークを付しています[^translater_env]．

License: [GPL-3](https://opensource.org/licenses/GPL-3.0)

----

<!-- This document describes lazyeval, a package that provides principled tools to perform non-standard evaluation (NSE) in R. You should read this vignette if you want to program with packages like dplyr and ggplot2[^1], or you want a principled way of working with delayed expressions in your own package. As the name suggests, non-standard evaluation breaks away from the standard evaluation (SE) rules in order to do something special. There are three common uses of NSE: -->
この文書では，Rで非標準評価（non-standard evaluation, NSE）を行うための，原理に則ったツールである`lazyeval`について述べます．もしあなたがdplyrやggplot2[^1]といったパッケージを用いてプログラミングをしたい場合，あるいは自分のパッケージで遅延評価を利用するための原理に則った方法が欲しい場合には，このビネットを読むべきです．非標準評価はその名の通り，特殊なことを行うために標準評価（standard evaluation, SE）のルールから逸脱します．NSEの一般的な用途には以下の3つがあります．

<!-- 1.  __Labelling__ enhances plots and tables by using the expressions -->
<!--     supplied to a function, rather than their values. For example, note the -->
<!--     axis labels in this plot: -->
<!-- 1.  __Non-standard scoping__ looks for objects in places other than the current -->
<!--     environment. For example, base R has `with()`, `subset()`, and `transform()`  -->
<!--     that look for objects in a data frame (or list) before the current  -->
<!--     environment: -->
<!-- 1.  __Metaprogramming__ is a catch-all term that covers all other uses of  -->
<!--     NSE (such as in `bquote()` and `library()`). Metaprogramming is so called  -->
<!--     because it involves computing on the unevaluated code in some way. -->
1.  __ラベル__ ． 関数に与えた値ではなく，表現式（expression）を使ってラベルを付けると図表が分かりやすくなります．例として，次のプロットの軸ラベルに注目してください．

    
    ```r
    par(mar = c(4.5, 4.5, 1, 0.5))
    grid <- seq(0, 2 * pi, length = 100)
    plot(grid, sin(grid), type = "l")
    ```
    
    ![unnamed-chunk-2-1.png](https://qiita-image-store.s3.amazonaws.com/0/58917/752050a7-bb78-c77d-96c8-e20c8125899f.png)

2.  __非標準スコープ__ によってオブジェクトが現在の環境以外の場所で検索されます．たとえばbase Rには，オブジェクトを現在の環境より先にデータフレーム（またはリスト）の中で探す`with()`，`subset()`，`transform()`があります．
    
    ```r
    df <- data.frame(x = c(1, 5, 4, 2, 3), y = c(2, 1, 5, 4, 3))
    
    with(df, mean(x))
    #> [1] 3
    subset(df, x == y)
    #>   x y
    #> 5 3 3
    transform(df, z = x + y)
    #>   x y z
    #> 1 1 2 3
    #> 2 5 1 6
    #> 3 4 5 9
    #> 4 2 4 6
    #> 5 3 3 6
    ```

3.  __メタプログラミング__ はその他のNSEの用途（`bquote()`や`library()`等）を何でも含む用語です．なぜメタプログラミングと呼ぶかというと，未評価のコードに対して何らかの方法で計算を行うからです．

<!-- This document is broadly organised according to the three types of non-standard evaluation described above. The main difference is that after [labelling], we'll take a detour to learn more about [formulas]. You're probably familiar with formulas from linear models (e.g. `lm(mpg ~ displ, data = mtcars)`) but formulas are more than just a tool for modelling: they are a general way of capturing an unevaluated expression.  -->
この文書は，大まかにはこれら3種類の非標準評価の用途に沿って構成されています．主な違いはラベルの後でフォーミュラ（formula）[^tr1]についてさらに学ぶために寄り道をするところです．おそらく線形モデル（たとえば`lm(mpg ~ displ, data = mtcars)`）のフォーミュラにはなじみがあるでしょうが，フォーミュラはモデリングのための単なるツール以上のものであり，未評価の表現式を捕捉（capture）するための汎用的な方法なのです．

<!-- The approaches recommended here are quite different to my previous generation of recommendations. I am fairly confident these new approaches are correct, and will not have to change substantially again. The current tools make it easy to solve a number of practical problems that were previously challenging and are rooted in [long-standing theory](http://repository.readscheme.org/ftp/papers/pepm99/bawden.pdf). -->
ここで推奨する方法は著者が以前推奨していたものとは大きく異なりますが，新しい方法のほうが正しく，再び本質的に変更を加える必要は生じないだろうと確信しています[^tr2]．現在のツールは以前には困難だった多くの実用的な問題を容易に解決できますし，[伝統ある理論](http://repository.readscheme.org/ftp/papers/pepm99/bawden.pdf)に立脚しているものです．

<!-- [^1]: Currently neither ggplot2 nor dplyr actually use these tools since I've only just figured it out. But I'll be working hard to make sure all my packages are consistent in the near future. -->
[^1]: 今のところ著者自身が理解したばかりなので，ggplot2もdplyrもこれらのツールを実際には使っていませんが，著者のすべてのパッケージが近い将来に整合的になるように努力します．

[^tr1]: __［訳注］__"formula"は「モデル式」と訳されることが多いと思うが，ここではモデリング以外にもformulaが使えるということが主題なので，「フォーミュラ」とした．

[^tr2]: __［訳注］__著者の以前の考え方は[__ここ__](https://cran.r-project.org/web/packages/lazyeval/vignettes/lazyeval-old.html)で知ることができる．日本語での解説はたとえば[__ここ__](http://keiku.hatenablog.jp/entry/2016/02/21/221831)で読むことができる．


<!-- ## Labelling -->
## ラベル

<!-- In base R, the classic way to turn an argument into a label is to use `deparse(substitute(x))`: -->
base Rで引数をラベルにする典型的なやり方は`deparse(substitute(x))`を使うことです．


```r
my_label <- function(x) deparse(substitute(x))
my_label(x + y)
#> [1] "x + y"
```

<!-- There are two potential problems with this approach: -->
この方法には潜在的な問題が2つあります．

<!-- 1.  For long some expressions, `deparse()` generates a character vector with  -->
<!--     length > 1: -->
<!-- 1.  `substitute()` only looks one level up, so you lose the original label if  -->
<!--     the function isn't called directly: -->
1.  長い表現式の中には，`deparse()`によって長さが1を超える文字ベクトルが生成されるものがあります．
        
    ```r
    my_label({
      a + b
      c + d
    })
    #> [1] "{"         "    a + b" "    c + d" "}"
    ```

2.  `substitute()`は1つ上の環境しか見に行かないので，関数を直接呼ばないと元のラベルが失われてしまいます．
    
    ```r
    my_label2 <- function(x) my_label(x)
    my_label2(a + b)
    #> [1] "x"
    ```

<!-- Both of these problems are resolved by `lazyeval::expr_text()`: -->
`lazyeval::expr_text()`によって両方の問題を解決することができます．


```r
my_label <- function(x) expr_text(x)
my_label2 <- function(x) my_label(x)
   
my_label({
  a + b
  c + d
})
#> [1] "{\n    a + b\n    c + d\n}"
my_label2(a + b)
#> [1] "a + b"
```

<!-- There are two variations on the theme of `expr_text()`: -->
`expr_text()`には2つの変種があります．

<!-- *   `expr_find()` find the underlying expression. It works similarly to  -->
<!--     `substitute()` but will follow a chain of promises back up to the original -->
<!--     expression. This is often useful for [metaprogramming]. -->
* `expr_find()`は引数の元々の表現式を見つけます．`substitute()`に似た動作をしますが，プロミスの連鎖を辿って最初の表現式まで戻っていきます．これはしばしばメタプログラミングに役立ちます．
  
<!-- *   `expr_label()` is a customised version of `expr_text()` that produces  -->
<!--     labels designed to be used in messages to the user: -->
* `expr_label()`はユーザへのメッセージ用にデザインされたラベルを生成するように`expr_text()`をカスタマイズしたものです．

    
    ```r
    expr_label(x)
    #> [1] "`x`"
    expr_label(a + b + c)
    #> [1] "`a + b + c`"
    expr_label(foo({
      x + y
    }))
    #> [1] "`foo(...)`"
    ```

<!-- ### Exercises -->
### 練習問題

<!-- 1.  `plot()` uses `deparse(substitute(x))` to generate labels for the x and y -->
<!--     axes. Can you generate input that causes it to display bad labels? -->
<!--     Write your own wrapper around `plot()` that uses `expr_label()` to compute -->
<!--     `xlim` and `ylim`. -->
<!-- 1.  Create a simple implementation of `mean()` that stops with an informative -->
<!--     error message if the argument is not numeric: -->
<!-- 1.  Read the source code for `expr_text()`. How does it work? What additional -->
<!--     arguments to `deparse()` does it use? -->
1.  `plot()`はx軸とy軸のラベルを生成するのに`deparse(substitute(x))`を使っています．`plot()`が不適切なラベルを表示するような入力を作成してください．`expr_label()`を使って`xlim`と`ylim`を計算する`plot()`のラッパー関数を書いてください．
    
2.  引数がnumericでない場合に有用なエラーメッセージを出して停止する，`mean()`の簡単な実装を作成してください．
    
    
    ```r
    x <- c("a", "b", "c")
    my_mean(x)
    #> Error: `x` is a not a numeric vector.
    my_mean(x == "a")
    #> Error: `x == "a"` is not a numeric vector.
    my_mean("a")
    #> Error: "a" is not a numeric vector.
    ```

3.  `expr_text()`のソースコードを読み，どのように機能しているか，また`deparse()`のどの引数を追加で使っているのか調べてください．

<!-- ## Formulas -->
## フォーミュラ

<!-- Non-standard scoping is probably the most useful NSE tool, but before we can talk about a solid approach, we need to take a detour to talk about formulas. Formulas are a familiar tool from linear models, but their utility is not limited to models. In fact, formulas are a powerful, general purpose tool, because a formula captures two things:  -->
非標準スコープはおそらくNSEのツールで最も有用なものですが，確固とした使用方法について語れるようになる前に，フォーミュラの話に寄り道しておく必要があります．フォーミュラは線形モデルで馴染み深いツールですが，その有用性はモデリングに限られたものではありません．実際には，フォーミュラは以下の2つのものを捕捉するので，強力で汎用的なツールとなっているのです．

<!-- 1. An unevaluated expression. -->
<!-- 1. The context (environment) in which the expression was created. -->
1. 未評価の表現式

2. 表現式が作成されたコンテクスト（環境）

<!-- `~` is a single character that allows you to say: "I want to capture the meaning of this code, without evaluating it right away". For that reason, the formula can be thought of as a "quoting" operator. -->
`~`は「このコードの意味を，今すぐに評価はせずに捕捉したい」と言うことを可能にする一文字なのです．このことから，フォーミュラはクオート（quoting）演算子だと考えることもできます．

<!-- ### Definition of a formula -->
### フォーミュラの定義

<!-- Technically, a formula is a "language" object (i.e. an unevaluated expression) with a class of "formula" and an attribute that stores the environment: -->
専門的に言うと，フォーミュラとは`language`オブジェクト（すなわち未評価の表現式）であって，クラスが`formula`であり，属性の中に環境を保持しているものです．


```r
f <- ~ x + y + z
typeof(f)
#> [1] "language"
attributes(f)
#> $class
#> [1] "formula"
#> 
#> $.Environment
#> <environment: R_GlobalEnv>
```

<!-- The structure of the underlying object is slightly different depending on whether you have a one-sided or two-sided formula: -->
フォーミュラが両側か片側かによって，内部のオブジェクトの構造が微妙に異なります．

<!-- *   One-sided formulas have length two: -->
* 片側フォーミュラの長さは2です

    
    ```r
    length(f)
    #> [1] 2
    # 1番目の要素は常に~
    f[[1]]
    #> `~`
    # 二番目の要素は右辺
    f[[2]]
    #> x + y + z
    ```

<!-- *   Two-sided formulas have length three: -->
* 両側フォーミュラの長さは3です

    
    ```r
    g <- y ~ x + z
    length(g)
    #> [1] 3
    # 1番目の要素はやはり~
    g[[1]]
    #> `~`
    # だが，2番目の要素は左辺
    g[[2]]
    #> y
    # そして，3番目の要素が右辺
    g[[3]]
    #> x + z
    ```

<!-- To abstract away these differences, lazyeval provides `f_rhs()` and `f_lhs()` to access either side of the formula, and `f_env()` to access its environment: -->
`lazyeval`はこの違いを捨象して，フォーミュラの両辺にアクセスするための`f_rhs()`と`f_lhs()`を提供します．さらに`f_env()`でフォーミュラの環境にもアクセスできます．


```r
f_rhs(f)
#> x + y + z
f_lhs(f)
#> NULL
f_env(f)
#> <environment: R_GlobalEnv>

f_rhs(g)
#> x + z
f_lhs(g)
#> y
f_env(g)
#> <environment: R_GlobalEnv>
```

<!-- ### Evaluating a formula -->
### フォーミュラの評価

<!-- A formula captures delays the evaluation of an expression so you can later evaluate it with `f_eval()`: -->
フォーミュラで表現式を捕捉し評価を遅延させておいて，後から`f_eval()`によって評価することができます．


```r
f <- ~ 1 + 2 + 3
f
#> ~1 + 2 + 3
f_eval(f)
#> [1] 6
```

<!-- This allows you to use a formula as a robust way of delaying evaluation, cleanly separating the creation of the formula from its evaluation. Because formulas capture the code and context, you get the correct result even when a formula is created and evaluated in different places. In the following example, note that the value of `x` inside `add_1000()` is used: -->
これにより，フォーミュラの作成を評価からきれいに分離して，フォーミュラを遅延評価のロバストな方法として使うことが可能になります．フォーミュラはコードとコンテクストを捕捉しているので，フォーミュラが作成されたのとは別の場所で評価された時にも正しい結果が得られます．次の例で`add_1000()`の中の`x`が使われていることに注目してください．


```r
x <- 1
add_1000 <- function(x) {
  ~ 1000 + x
}

add_1000(3)
#> ~1000 + x
#> <environment: 0x0000000008685f70>
f_eval(add_1000(3))
#> [1] 1003
```

<!-- It can be hard to see what's going on when looking at a formula because important values are stored in the environment, which is largely opaque. You can use `f_unwrap()` to replace names with their corresponding values: -->
フォーミュラを見ても，概して不明瞭な環境に重要な値が保存されているために，何が起きているのか理解するのが難しいことがあります．フォーミュラの中の名前を対応する値で置き換えるのに`f_unwrap()`が使えます．


```r
f_unwrap(add_1000(3))
#> ~1000 + 3
```

<!-- ### Non-standard scoping -->
### 非標準スコープ

<!-- `f_eval()` has an optional second argument: a named list (or data frame) that overrides values found in the formula's environment.  -->
`f_eval()`にはオプションとして2つ目の引数があります．フォーミュラの環境にある値を上書きするための名前付きリスト（またはデータフレーム）です．


```r
y <- 100
f_eval(~ y)
#> [1] 100
f_eval(~ y, data = list(y = 10))
#> [1] 10

# 環境とdata引数の変数を混ぜて使うことが可能
f_eval(~ x + y, data = list(x = 10))
#> [1] 110
# 関数を与えることも可能
f_eval(~ f(y), data = list(f = function(x) x * 3))
#> [1] 300
```

<!-- This makes it very easy to implement non-standard scoping: -->
これによって非標準スコープを実装することが非常に簡単になります．


```r
f_eval(~ mean(cyl), data = mtcars)
#> [1] 6.1875
```

<!-- One challenge with non-standard scoping is that we've introduced some ambiguity. For example, in the code below does `x` come from `mydata` or the environment? -->
非標準スコープの問題点として，ちょっとした曖昧性を持ち込んでしまったことがあります．
たとえば，以下のコードで`x`は`mydata`と環境のどちらからやって来るのでしょうか？


```r
f_eval(~ x, data = mydata)
```

<!-- You can't tell without knowing whether or not `mydata` has a variable called `x`. To overcome this problem, `f_eval()` provides two pronouns: -->
これは`mydata`が`x`という名前の変数を持っているかどうか知らなければわかりません．この問題を克服するために`f_eval()`は二つの代名詞を提供しています．

<!-- * `.data` is bound to the data frame. -->
<!-- * `.env` is bound to the formula environment. -->
* `.data`はデータフレームに束縛されます
* `.env`はフォーミュラの環境に束縛されます

<!-- They both start with `.` to minimise the chances of clashing with existing variables. -->
既存の変数名と衝突する可能性をできる限り小さくするため，どちらも名前は`.`で始まるようになっています．

<!-- With these pronouns we can rewrite the previous formula to remove the ambiguity: -->
これらの代名詞を使えば，先程のフォーミュラを曖昧さがないように書き直すことができます．


```r
mydata <- data.frame(x = 100, y = 1)
x <- 10

f_eval(~ .env$x, data = mydata)
#> [1] 10
f_eval(~ .data$x, data = mydata)
#> [1] 100
```

<!-- If the variable or object doesn't exist, you'll get an informative error: -->
変数オブジェクトが存在しない場合は，有用なエラーメッセージが出ます．


```r
f_eval(~ .env$z, data = mydata)
#> Error: Object 'z' not found in environment
f_eval(~ .data$z, data = mydata)
#> Error: Variable 'z' not found in data
```

<!-- ### Unquoting -->
### アンクオート

<!-- `f_eval()` has one more useful trick up its sleeve: unquoting. Unquoting allows you to write functions where the user supplies part of the formula. For example, the following function allows you to compute the mean of any column (or any function of a column): -->
`f_eval()`にはもう一つ有用なトリックが用意されています．アンクオート（unquoting）です．アンクオートによって，ユーザがフォーミュラの一部を与えることができる関数を書くことが可能になります．たとえば，次の関数では任意の列（あるいは列に対する任意の関数）の平均値を計算することができます．


```r
df_mean <- function(df, variable) {
  f_eval(~ mean(uq(variable)), data = df)
}

df_mean(mtcars, ~ cyl)
#> [1] 6.1875
df_mean(mtcars, ~ disp * 0.01638)
#> [1] 3.779224
df_mean(mtcars, ~ sqrt(mpg))
#> [1] 4.43477
```

<!-- To see how this works, we can use `f_interp()` which `f_eval()` calls internally (you shouldn't call it in your own code, but it's useful for debugging). The key is `uq()`: `uq()` evaluates its first (and only) argument and inserts the value into the formula: -->
これがどのように機能しているか見るのに，`f_eval()`が内部で呼んでいる`f_interp()`が使えます（あなた自身のコードの中ではこの関数を呼ぶべきではありませんが，デバッグには有用です）．鍵となるのは`uq()`です．`uq()`は第1の（そして唯一の）引数を評価して，その値をフォーミュラの中に挿入します．


```r
variable <- ~cyl
f_interp(~ mean(uq(variable)))
#> ~mean(cyl)

variable <- ~ disp * 0.01638
f_interp(~ mean(uq(variable)))
#> ~mean(disp * 0.01638)
```

<!-- Unquoting allows you to create code "templates", where you write most of the expression, while still allowing the user to control important components. You can even use `uq()` to change the function being called: -->
アンクオートによってコードの「テンプレート」を作成することが可能になります．テンプレートでは，表現式の大部分をあなたが書いておきながら，ユーザにも重要なコンポーネントを制御させることが可能です．呼ばれる関数を変更するために`uq()`を使うことさえできます．


```r
f <- ~ mean
f_interp(~ uq(f)(uq(variable)))
#> ~mean(disp * 0.01638)
```

<!-- Note that `uq()` only takes the RHS of a formula, which makes it difficult to insert literal formulas into a call: -->
`uq()`はフォーミュラの右辺だけを受け取ることに注意してください．これは与えたフォーミュラをそのまま呼び出し（call）に挿入することを難しくします．


```r
formula <- y ~ x
f_interp(~ lm(uq(formula), data = df))
#> ~lm(x, data = df)
```

<!-- You can instead use `uqf()` which uses the whole formula, not just the RHS: -->
かわりに，右辺だけでなくフォーミュラ全体を用いる`uqf()を`使うことができます．


```r
f_interp(~ lm(uqf(formula), data = df))
#> ~lm(y ~ x, data = df)
```

<!-- Unquoting is powerful, but it only allows you to modify a single argument: it doesn't allow you to add an arbitrary number of arguments. To do that, you'll need "unquote-splice", or `uqs()`. The first (and only) argument to `uqs()` should be a list of arguments to be spliced into the call: -->
アンクオートは強力ですが，単一の引数を変更することしかできず，任意の数の引数をさらに追加することはできません．それをやるためには，「アンクオート・スプライス（unquote-splice）」すなわち`uqs()`がが必要になります．`uqs()`の第1の（そして唯一の）引数は，呼び出しの中に接合（splice）される引数のリストでなければいけません．


```r
variable <- ~ x
extra_args <- list(na.rm = TRUE, trim = 0.9)
f_interp(~ mean(uq(variable), uqs(extra_args)))
#> ~mean(x, na.rm = TRUE, trim = 0.9)
```

<!-- ### Exercises -->
### 練習問題

<!-- 1.  Create a wrapper around `lm()` that allows the user to supply the  -->
<!--     response and predictors as two separate formulas. -->
<!-- 1.  Compare and contrast `f_eval()` with `with()`. -->
<!-- 1.  Why does this code work even though `f` is defined in two places? (And -->
<!--     one of them is not a function). -->
1. ユーザが説明変数と目的変数を2つの別々のフォーミュラで与えることができるような`lm()`のラッパー関数を作成してください．

1.  `f_eval()`を`with()`と比較，対照してください．

1. 次のコードが，`f`が2か所で定義されているにもかかわらず（しかも片方は関数ではないのに）動作するのはなぜでしょうか？

    
    ```r
    f <- function(x) x + 1
    f_eval(~ f(10), list(f = "a"))
    #> [1] 11
    ```

<!-- ## Non-standard scoping -->
## 非標準スコープ

<!-- Non-standard scoping (NSS) is an important part of R because it makes it easy to write functions tailored for interactive data exploration. These functions require less typing, at the cost of some ambiguity and "magic". This is a good trade-off for interactive data exploration because you want to get ideas out of your head and into the computer as quickly as possible. If a function does make a bad guess, you'll spot it quickly because you're working interactively. -->
非標準スコープ（non-standard scoping, NSS）はRの重要な構成要素です．というのも，これによってインタラクティブなデータ探索のための関数を書くのが容易になるからです．そのような関数では，ちょっとした曖昧さや「マジック」と引き換えにタイピングが少なくて済みます．このことは，インタラクティブなデータ探索においては良いトレードオフになっています．なぜなら，インタラクティブなデータ探索では頭の中のアイディアをできるだけ速くコンピュータで実現したいですし，もし関数が間違った推測をしても，インタラクティブに作業しているのですぐに間違った箇所の見当がつくからです．

<!-- There are three challenges to implementing non-standard scoping: -->
非標準スコープの実装には困難が3つあります．

<!-- 1.  You must correctly delay the evaluation of a function argument, capturing  -->
<!--     both the computation (the expression), and the context (the environment). -->
<!--     I recommend making this explicit by requiring the user to "quote" any NSS -->
<!--     arguments with `~`, and then evaluating explicit with `f_eval()`. -->
<!-- 1.  When writing functions that use NSS-functions, you need some way to -->
<!--     avoid the automatic lookup and be explicit about where objects should be -->
<!--     found. `f_eval()` solves this problem with the `.data.` and `.env`  -->
<!--     pronouns. -->
<!-- 1.  You need some way to allow the user to supply parts of a formula.  -->
<!--     `f_eval()` solves this with unquoting. -->
1.  計算（表現式）とコンテクスト（環境）の両方を捕捉し，関数の引数の評価を正確に遅延させなければいけません．著者としては，ユーザにすべてのNSS引数を`~`で「クオート」するよう要求して，計算とコンテクストが捕捉されていることを明示的にし，それから`f_eval()`で明示的に評価することを推奨します．
  
1.  NSS関数を使う関数を書くときには，オブジェクトの自動的な検索を避けて，どこでオブジェクトを見つけるべきかを明示的にする手段が必要です．`f_eval()`は`.data`と`.env`という代名詞によってこの問題を解決します．

1.  ユーザがフォーミュラの一部分を与えることができるようにするための手段が必要です．`f_eval()`はアンクオートによってこれを解決します．

<!-- To illustrate these challenges, I will implement a `sieve()` function that works similarly to `base::subset()` or `dplyr::filter()`. The goal of `sieve()` is to make it easy to select observations that match criteria defined by a logical expression. `sieve()` has three advantages over `[`: -->
これらの困難を説明するため，`base::subset()`や`dplyr::filter()`に似た働きをする`sieve()`という関数を実装します．`sieve()`の目的は，論理式で定義された条件に合致するオブザベーションを簡単に選択できるようにすることです．`sieve()`には`[`と比べて3つの利点があります．

<!-- 1.  It is much more compact when the condition uses many variables, because  -->
<!--     you don't need to repeat the name of the data frame many times. -->
<!-- 1.  It drops rows where the condition evaluates to `NA`, rather than filling  -->
<!--     them with `NA`s. -->
<!-- 1.  It always returns a data frame. -->
1. データフレームの名前を何度もくり返し書く必要がないので，条件式で多くの変数を使う場合にずっとコンパクトになります．

1.  条件式が`NA`と評価される行は，NAで埋めるのではなく除外します．
    
1. 常にデータフレームを返します．

<!-- The implementation of `sieve()` is straightforward. First we use `f_eval()` to perform NSS. Then we then check that we have a logical vector, replace `NA`s with `FALSE`, and subset with `[`. -->
`sieve()`の実装は単純明快です．まず`f_eval()`を使ってNSSを実行します．それから評価結果が論理ベクトルであることを確認して，`NA`を`FALSE`で置き換え，`[`で行を抽出します．


```r
sieve <- function(df, condition) {
  rows <- f_eval(condition, df)
  if (!is.logical(rows)) {
    stop("`condition` must be logical.", call. = FALSE)
  }
  
  rows[is.na(rows)] <- FALSE
  df[rows, , drop = FALSE]
}

df <- data.frame(x = 1:5, y = 5:1)
sieve(df, ~ x <= 2)
#>   x y
#> 1 1 5
#> 2 2 4
sieve(df, ~ x == y)
#>   x y
#> 3 3 3
```

<!-- ### Programming with `sieve()` -->
### `sieve()`によるプログラミング

<!-- Imagine that you've written some code that looks like this: -->
あなたが次のようなコードを書いたと思ってください．


```r
sieve(march, ~ x > 100)
sieve(april, ~ x > 50)
sieve(june, ~ x > 45)
sieve(july, ~ x > 17)
```

<!-- (This is a contrived example, but it illustrates all of the important issues you'll need to consider when writing more useful functions.) -->
（これはわざとらしく作った例ですが，もっと役に立つ関数を書くときに考える必要のある重要な問題点がすべて示されています．）

<!-- Instead of continuing to copy-and-paste your code, you decide to wrap up the common behaviour in a function:  -->
あなたはコードのコピペを続けるかわりに，共通のふるまいを関数にまとめることにします．


```r
threshold_x <- function(df, threshold) {
  sieve(df, ~ x > threshold)
}
threshold_x(df, 3)
#>   x y
#> 4 4 2
#> 5 5 1
```

<!-- There are two ways that this function might fail: -->
この関数は2つの点において不具合が生じるかもしれません．

<!-- 1.  The data frame might not have a variable called `x`. This will fail unless -->
<!--     there's a variable called `x` hanging around in the global environment: -->
<!-- 1.  The data frame might have a variable called `threshold`: -->
1. データフレームは`x`という名前の変数を持たないかもしれません．グローバル環境に`x`という名前の変数がない限り，不具合が生じます．
    
    
    ```r
    rm(x)
    df2 <- data.frame(y = 5:1)
    
    # Throws an error
    threshold_x(df2, 3)
    #> Error in eval(expr, envir, enclos):  オブジェクト 'x' がありません
    
    # Silently gives the incorrect result!
    x <- 5
    threshold_x(df2, 3)
    #>   y
    #> 1 5
    #> 2 4
    #> 3 3
    #> 4 2
    #> 5 1
    ```
    
1.  データフレームが`threshold`という名前の変数を持っているかもしれません．

    
    ```r
    df3 <- data.frame(x = 1:5, y = 5:1, threshold = 4)
    threshold_x(df3, 3)
    #>   x y threshold
    #> 5 5 1         4
    ```

<!-- These failures are partiuclarly pernicious because instead of throwing an error they silently produce the wrong answer. Both failures arise because `f_eval()` introduces ambiguity by looking in two places for each name: the supplied data and formula environment.  -->
これらの不具合は，エラーを出さずに無言で間違った答えを出すため，とりわけやっかいなものです．どちらの不具合も，`f_eval()`が各変数名を2箇所（与えられたデータと，フォーミュラの環境）で探すせいで曖昧性が持ち込まれたために生じたものです．

<!-- To make `threshold_x()` more reliable, we need to be more explicit by using the `.data` and `.env` pronouns: -->
`threshold_x()`の信頼性を高めるには，代名詞`.data`と`.env`を使って，もっと明示的にする必要があります．


```r
threshold_x <- function(df, threshold) {
  sieve(df, ~ .data$x > .env$threshold)
}

threshold_x(df2, 3)
#> Error: Variable 'x' not found in data
threshold_x(df3, 3)
#>   x y threshold
#> 4 4 2         4
#> 5 5 1         4
```

<!-- Here `.env` is bound to the environment where `~` is evaluated, namely the inside of `threshold_x()`. -->
ここで`.env`は`~`が評価された環境，すなわち`threshold_x()`の中に束縛されています．

<!-- ### Adding arguments -->
### 引数の追加

<!-- The `threshold_x()` function is not very useful because it's bound to a specific variable. It would be more powerful if we could vary both the threshold and the variable it applies to. We can do that by taking an additional argument to specify which variable to use.  -->
`threshold_x()`関数は特定の変数と結び付いているため，それほど有用ではありません．閾値と変数の両方を変更できればもっと強力になるでしょう．これは使う変数を指定するための引数を追加すれば可能です．

<!-- One simple approach is to use a string and `[[`: -->
単純な方法は文字列と`[[`を使うものです．


```r
threshold <- function(df, variable, threshold) {
  stopifnot(is.character(variable), length(variable) == 1)
  
  sieve(df, ~ .data[[.env$variable]] > .env$threshold)
}
threshold(df, "x", 4)
#>   x y
#> 5 5 1
```

<!-- This is a simple and robust solution, but only allows us to use an existing variable, not an arbitrary expression like `sqrt(x)`. -->
これは単純でロバストな解法ではありますが，使えるのは既にある変数だけで，`sqrt(x)`のような任意の式は使えません．

<!-- A more general solution is to allow the user to supply a formula, and use unquoting: -->
より一般的な解法は，ユーザがフォーミュラを与えられるようにして，アンクオートを使うことです．


```r
threshold <- function(df, variable = ~x, threshold = 0) {
  sieve(df, ~ uq(variable) > .env$threshold)
}

threshold(df, ~ x, 4)
#>   x y
#> 5 5 1
threshold(df, ~ abs(x - y), 2)
#>   x y
#> 1 1 5
#> 5 5 1
```

<!-- In this case, it's the responsibility of the user to ensure the `variable` is specified unambiguously. `f_eval()` is designed so that `.data` and `.env` work even when evaluated inside of `uq()`: -->
この場合には，`variable`が曖昧さなく指定されるように保証するのはユーザの責任です．`f_eval()`は`.data`と`.env`が`uq()`の中で評価されたときにも動作するように設計されています．


```r
x <- 3
threshold(df, ~ .data$x - .env$x, 0)
#>   x y
#> 4 4 2
#> 5 5 1
```

<!-- ### Dot-dot-dot -->
### ドット・ドット・ドット

<!-- There is one more tool that you might find useful for functions that take `...`. For example, the code below implements a function similar to `dplyr::mutate()` or `base::transform()`. -->
`...`を受け取る関数について，あなたが便利だと思うかもしれないもうひとつのツールがあります．たとえば以下のコードでは，`dplyr::mutate()`や`base::transform()`に似た関数を実装しています．


```r
mogrify <- function(`_df`, ...) {
  args <- list(...)
  
  for (nm in names(args)) {
    `_df`[[nm]] <- f_eval(args[[nm]], `_df`)
  }
  
  `_df`
}
```

<!-- (NB: the first argument is a non-syntactic name (i.e. it requires quoting with `` ` ``) so it doesn't accidentally match one of the names of the new variables.) -->
（注意：第1引数は構文違反の名前（つまり`` ` ``でクオートする必要あり）なので，新しく作られる変数の名前と誤って一致することはありません．）

<!-- `mogrifty()` makes it easy to add new variables to a data frame: -->
`mogrifty()`によってデータフレームに変数を追加するのが簡単になります．


```r
df <- data.frame(x = 1:5, y = sample(5))
mogrify(df, z = ~ x + y, z2 = ~ z * 2)
#>   x y z z2
#> 1 1 4 5 10
#> 2 2 2 4  8
#> 3 3 5 8 16
#> 4 4 1 5 10
#> 5 5 3 8 16
```

<!-- One problem with this implementation is that it's hard to specify the names of the generated variables. Imagine you want a function where the name and expression are in separate variables. This is awkward because the variable name is supplied as an argument name to `mogrify()`: -->
この実装の問題点のひとつは，作成される変数の名前を指定するのが難しいことです．変数名と式が別々の変数に入っている関数が欲しい場合を考えてみてください．作成される変数の名前は`mogrify()`の引数の名前として与えられるので，この関数はぎこちないものになります．


```r
add_variable <- function(df, name, expr) {
  do.call("mogrify", c(list(df), setNames(list(expr), name)))
}
add_variable(df, "z", ~ x + y)
#>   x y z
#> 1 1 4 5
#> 2 2 2 4
#> 3 3 5 8
#> 4 4 1 5
#> 5 5 3 8
```

<!-- Lazyeval provides the `f_list()` function to make writing this sort of function a little easier. It takes a list of formulas and evaluates the LHS of each formula (if present) to rename the elements: -->
`lazyeval`はこの種の関数を書くのを少し楽にするために`f_list()`を提供しています．この関数はフォーミュラのリストを受け取り，各フォーミュラに左辺があれば評価して，フォーミュラの名前をその評価値で置き換えます．


```r
f_list("x" ~ y, z = ~z)
#> $x
#> ~y
#> 
#> $z
#> ~z
```

<!-- If we tweak `mogrify()` to use `f_list()` instead of `list()`: -->
`list()`のかわりに`f_list()`を使って`mogrify()`に手を加えると次のようになります．


```r
mogrify <- function(`_df`, ...) {
  args <- f_list(...)
  
  for (nm in names(args)) {
    `_df`[[nm]] <- f_eval(args[[nm]], `_df`)
  }
  
  `_df`
}
```

<!-- `add_new()` becomes much simpler: -->
`add_new()`はずっと単純になります．


```r
add_variable <- function(df, name, expr) {
  mogrify(df, name ~ uq(expr))
}
add_variable(df, "z", ~ x + y)
#>   x y z
#> 1 1 4 5
#> 2 2 2 4
#> 3 3 5 8
#> 4 4 1 5
#> 5 5 3 8
```

<!-- ### Exercises -->
### 練習問題

<!-- 1.  Write a function that selects all rows of `df` where `variable` is  -->
<!--     greater than its mean. Make the function more general by allowing the -->
<!--     user to specify a function to use instead of `mean()` (e.g. `median()`). -->
<!-- 1.  Create a version of `mogrify()` where the first argument is `x`? -->
<!--     What happens if you try to create a new variable called `x`? -->
1.  `df`から`variable`がその平均値より大きい行をすべて選択する関数を書いてください．ユーザが使う関数を`mean()`以外（`median()`等）にも指定できるように関数を一般化してください．

1.  `mogrify()`の第1引数を`x`にしたものを作成してください．`x`という名前の変数を作成しようとするとどうなるでしょうか？

<!-- ## Non-standard evaluation -->
## 非標準評価

<!-- In some situations you might want to eliminate the formula altogether, and allow the user to type expressions directly. I was once much enamoured with this approach (witness ggplot2, dplyr, ...). However, I now think that it should be used sparingly because explict quoting with `~` leads to simpler code, and makes it more clear to the user that something special is going on. -->
場合によっては，フォーミュラを全く削除してしまい，ユーザが式を直接タイプできるようにしたいということがあるかもしれません．著者もかつてはこの方法に大いに心を奪われていましたが（`ggplot2`，`dplyr`，等々を見よ），今ではこの方法を使うのは控えめにすべきだと考えています．なぜなら，`~`による明示的なクオートの方がコードがより単純になり，何か特殊なことが起きているということがユーザにとってより明確になるからです．

<!-- That said, lazyeval does allow you to eliminate the `~` if you really want to. In this case, I recommend having both a NSE and SE version of the function. The SE version, which takes formuals, should have suffix `_`: -->
とは言え，あなたが本当に`~`を削除したいのであれば，`lazyeval`はそれを可能にします．その場合にはNSEとSEの両方のバージョンの関数を作ることを推奨します．フォーミュラを受け取るSEバージョンには`_`というサフィックスを付けるべきです．


```r
sieve_ <- function(df, condition) {
  rows <- f_eval(condition, df)
  if (!is.logical(rows)) {
    stop("`condition` must be logical.", call. = FALSE)
  }
  
  rows[is.na(rows)] <- FALSE
  df[rows, , drop = FALSE]
}
```

<!-- Then create the NSE version which doesn't need the explicit formula. The key is the use of `f_capture()` which takes an unevaluated argument (a promise) and captures it as a formula: -->
それから明示的なフォーミュラを必要としないNSEバージョンを作成します．鍵となるのは，未評価の引数（プロミス）を受け取り，それをフォーミュラとして捕捉する`f_capture()`の使い方です．


```r
sieve <- function(df, expr) {
  sieve_(df, f_capture(expr))
}
sieve(df, x == 1)
#>   x y
#> 1 1 4
```

<!-- If you're familiar with `substitute()` you might expect the same drawbacks to apply. However, `f_capture()` is smart enough to follow a chain of promises back to the original value, so, for example, this code works fine: -->
もし`substitute()`に馴染みがあれば，同じ欠点がこの関数にもあてはまると思うかもしれません．しかし`f_capture()`は充分に賢く，元々の値までプロミスの連鎖を辿っていくので，たとえば次のコードはうまく動きます．


```r
scramble <- function(df) {
  df[sample(nrow(df)), , drop = FALSE]
}
subscramble <- function(df, expr) {
  scramble(sieve(df, expr))
}
subscramble(df, x < 4)
#>   x y
#> 2 2 2
#> 1 1 4
#> 3 3 5
```

<!-- ### Dot-dot-dot -->
### ドット・ドット・ドット

<!-- If you want a `...` function that doesn't require formulas, I recommend that the SE version take a list of arguments, and the NSE version uses `dots_capture()` to capture multiple arguments as a list of formulas. -->
もしフォーミュラを要求しない`...`を使う関数が欲しければ，SEバージョンの関数は引数のリストを受け取るようにしておき，NSEバージョンでは複数の引数をフォーミュラのリストとして捕捉できるように`dots_capture()`を使うことを推奨します．


```r
mogrify_ <- function(`_df`, args) {
  args <- as_f_list(args)
  
  for (nm in names(args)) {
    `_df`[[nm]] <- f_eval(args[[nm]], `_df`)
  }
  
  `_df`
}

mogrify <- function(`_df`, ...) {
  mogrify_(`_df`, dots_capture(...))
}
```

<!-- ### Exercises -->
### 練習問題

<!-- 1.  Recreate `subscramble()` using `base::subset()` instead of `sieve()`. -->
<!--     Why does it fail? -->
1. `sieve()`のかわりに`base::subset()`を使って`subscramble()`を再度作成してください．うまくいかないのはなぜでしょうか？

<!-- ## Metaprogramming -->
## メタプログラミング

<!-- The final use of non-standard evaluation is to do metaprogramming. This is a catch-all term that encompasses any function that does computation on an unevaluated expression. You can learn about metaprogrgramming in <http://adv-r.had.co.nz/Expressions.html>, particularly <http://adv-r.had.co.nz/Expressions.html#ast-funs>. Over time, the goal is to move all useful metaprogramming helper functions into this package, and discuss metaprogramming more here. -->
非標準評価の最後の用途はメタプログラミングをすることです．これは未評価の表現式に対する計算をする関数なら何でも含む用語です．メタプログラミングについては<http://adv-r.had.co.nz/Expressions.html>，特に<http://adv-r.had.co.nz/Expressions.html#ast-funs>で学ぶことができます[^tr3]．時間をかけて，メタプログラミングに役立つヘルパー関数のすべてをこのパッケージに移し，ここでもっとメタプログラミングについて議論するのが目標です．

----

[^tr3]: __［訳注］__邦訳（__石田基広，市川太祐，高柳慎一，福島真太朗（訳）「[R言語徹底解説](http://www.kyoritsu-pub.co.jp/bookdetail/9784320123939)」共立出版__）では14章「表現式」と14.7節「再帰関数を用いた抽象構文木」に相当する．

[^translater_env]: __［訳注］__訳者の環境は以下の通り．
    
    ```r
    devtools::session_info()
    #> Session info --------------------------------------------------------------
    #>  setting  value                       
    #>  version  R version 3.3.1 (2016-06-21)
    #>  system   x86_64, mingw32             
    #>  ui       RTerm                       
    #>  language (EN)                        
    #>  collate  Japanese_Japan.932          
    #>  tz       Asia/Tokyo                  
    #>  date     2016-09-19
    #> Packages ------------------------------------------------------------------
    #>  package       * version  date       source                            
    #>  assertthat      0.1      2013-12-06 CRAN (R 3.3.1)                    
    #>  devtools        1.12.0   2016-06-24 CRAN (R 3.3.1)                    
    #>  digest          0.6.10   2016-08-02 CRAN (R 3.3.1)                    
    #>  evaluate        0.9      2016-04-29 CRAN (R 3.3.1)                    
    #>  formatR         1.4      2016-05-09 CRAN (R 3.3.1)                    
    #>  htmltools       0.3.5    2016-03-21 CRAN (R 3.3.1)                    
    #>  knitr           1.14     2016-08-13 CRAN (R 3.3.1)                    
    #>  lazyeval      * 0.2.0    2016-06-12 CRAN (R 3.3.1)                    
    #>  magrittr        1.5      2014-11-22 CRAN (R 3.3.1)                    
    #>  memoise         1.0.0    2016-01-29 CRAN (R 3.3.1)                    
    #>  Rcpp            0.12.6   2016-07-19 CRAN (R 3.3.1)                    
    #>  RevoUtils       10.0.1   2016-08-24 local                             
    #>  RevoUtilsMath * 8.0.3    2016-04-13 local                             
    #>  rmarkdown       1.0.9013 2016-09-05 Github (rstudio/rmarkdown@5d05a39)
    #>  stringi         1.1.1    2016-05-27 CRAN (R 3.3.0)                    
    #>  stringr         1.1.0    2016-08-19 CRAN (R 3.3.1)                    
    #>  tibble          1.2      2016-08-26 CRAN (R 3.3.1)                    
    #>  withr           1.0.2    2016-06-20 CRAN (R 3.3.1)                    
    #>  yaml            2.1.13   2014-06-12 CRAN (R 3.3.1)
    ```