論理式を貼り付ける機能が欲しい
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
これ以上分解して操作することはできませんでした。引用されていない側を定義することは、達成するのがさらに困難です。これを達成する簡単な方法はありますか?