1

論理式を貼り付ける機能が欲しい

paste_logic(a == b, c > q, f < g, sep = and) 
# should return
# expr(a == b & c > q & f < g)

また、(関数呼び出しではなく) 回旋中に遅延引用符を外し、理想的にはどちら側を制御したいと思いますか?

paste_expr(paste_expr(a == b, c > q, f < g, sep = and, side = right)
# should return
# expr(a == !!b & c > !!q & f < !!g)

最初の目標に向かって私が得た解決策は次のとおりです。

paste_logic <- function(sep, ...) {
  dots <- enquos(...)
  sep <- enexpr(sep)
  dispatch <- function(symbol) if (symbol == expr(and)) `&` else `|`
  if (length(dots) == 1) {
    dots[[1]]
  } else {
    expr(`!!`(dispatch(sep))(!!(dots[[1]]), !!paste_logic(sep, !!!dots[-1])))
  }
}
paste_logic(and, a > b, c == d, k == f) 
# returns
# .Primitive("&")(~a > b, .Primitive("&")(~c == d, ~k == f))

a <- 1
b <- 2
c <- 3
d <- 3
k <- 9
f <- 10

eval_tidy(paste_logic(and, a > b, c == d, k == f))
# returns FALSE
eval_tidy(paste_logic(or, a > b, c == d, k == f))
# returns TRUE

どちらも予想通りです。

このコードを改善して 2 番目の目標 (返された式で引用符を外す) を達成する方法についていくつか質問があります。

Q1 . else {...}最後のクロージャのこの部分では:

expr(`!!`(dispatch(sep))(!!(dots[[1]]), !!paste_logic(sep, !!!dots[-1])))

!!演算子をラップするか、UQ関数を使用するには、素数記号を使用する必要があります。単純に、!!(dispatch(sep))または完全な関数定義をこのように指定すると

paste_logic <- function(sep, ...) {
  dots <- enquos(...)
  sep <- enexpr(sep)
  dispatch <- function(symbol) if (symbol == expr(and)) `&` else `|`
  if (length(dots) == 1) {
    dots[[1]]
  } else {
    expr(!!(dispatch(sep))(!!(dots[[1]]), !!paste_logic(!!sep, !!!dots[-1])))
  }
}
paste_logic(or, a > b, c == d, k == f)

エラーを返します

Error: Quosures can only be unquoted within a quasiquotation context.

  # Bad:
  list(!!myquosure)

  # Good:
  dplyr::mutate(data, !!myquosure)

グローバル環境でのテスト

a <- 1
b <- 2
c <- `&`
expr(!!(c)(!!a, !!n))

エラーなしで正常に動作し、 を返しますTRUE。では、なぜ私のコードではこれが機能せず、使用する必要があるの<prime>!!<prime>でしょうか?

Q2 . 論理演算子の前置機能バージョンを使用する必要があるため、最終的な式は への再帰関数呼び出し.Primitive("&")です。

関数の外部からシンボルとして&andを渡す方法はありますか?|expr(a == b & c > q & f < g)

&関数本体と|一緒に、ensymまたは関数本体内でラップするだけで、enexpr次のようなエラーが発生します。Error: unexpected '&' in "expr(&"

Q3 . このソリューションは、次のような返された式内での引用符の解除をサポートしていません。

expr(a == !!b & c > !!q & f < !!g)

それぞれdots[[i]]が単一の式であるため、a == bこれ以上分解して操作することはできませんでした。引用されていない側を定義することは、達成するのがさらに困難です。これを達成する簡単な方法はありますか?

4

2 に答える 2