也许这更像是日志,而不仅仅是函数式编程,但我想知道是否有更像purrr的方式来实现输入和输出/诊断消息的消息。
这对我很有用,因为我想在生产中使用sparklyr,并对分区查询的作业状态进行记录。
library(magrittr)
# Helper to list input params with output
helper = function(x, y, z) {
c(query = x, params = y, z)
}
# For single parameters
log_results = function(param, functions, adjective) {
# Cross the input vectors to apply each function to each parameter set
crossed_args = purrr::transpose(purrr::cross2(param, functions))
crossed_params = crossed_args[[1]] %>% unlist
crossed_function_names = crossed_args[[2]] %>% unlist()
# Parse to the query to wrap it with quietly
parsed_functions = purrr::map(crossed_function_names, ~ adjective(eval(parse(text = .x))))
# Tidy container for function calls
df = dplyr::data_frame(function_name = crossed_function_names, f = parsed_functions, param = crossed_params)
# Execute to get query results
results_log = purrr::map2(df$f, df$param, ~ .x(.y))
# Output results log as message
purrr::pmap(.l = list(df$function_name, df$param, results_log), helper) %>% str
}所有这些操作都是创建一个逐行作业的表,以便分派并返回带有诊断消息的作业。它被转储到日志中,因此如果出现故障,我可以检查哪个作业失败了。
log_results_quietly = purrr::partial(log_results, adjective = purrr::quietly)
> log_results_quietly(c(-1, 3, 4, 5), c("exp", "log"))
List of 8
$ :List of 6
..$ query : chr "exp"
..$ params : num -1
..$ result : num 0.368
..$ output : chr ""
..$ warnings: chr(0)
..$ messages: chr(0)
$ :List of 6
..$ query : chr "exp"
..$ params : num 3
..$ result : num 20.1
..$ output : chr ""
..$ warnings: chr(0)
..$ messages: chr(0)
$ :List of 6
..$ query : chr "exp"
..$ params : num 4
..$ result : num 54.6
..$ output : chr ""
..$ warnings: chr(0)
..$ messages: chr(0)
...我认为invoke可能会有所帮助,但我不能让它与quietly友好相处。
任何关于如何更好地做到这一点的建议都是值得感谢的。谢谢
发布于 2017-04-03 23:27:00
除非我遗漏了什么,否则它可以像这样简单地重写:
cross(list(query = functions, params = param)) %>%
map(~ c(.x, adjective(eval(parse(text = .x$query)))(.x$param)))我不明白为什么你先transpose() cross()的输出,然后再map2()它,在cross()之后直接map()似乎更简单。
另外,您真的希望您的函数只具有通过str()打印内容并返回NULL的副作用吗?我建议您返回列表,然后根据函数的结果调用str()。
类似于:
log_results_2 <- function(param, functions, adjective) {
cross(list(query = functions, params = param)) %>%
map(~ c(.x, adjective(eval(parse(text = .x$query)))(.x$param)))
}
log_results_quietly_2 = purrr::partial(log_results_2, adjective = purrr::quietly)
res <- log_results_quietly_2(c(-1, 3, 4, 5), c("exp", "log"))
str(res)(请注意,它的顺序与您的不同,因为我首先使用functions调用了cross()。它可以很容易地调整)
# List of 8
# $ :List of 6
# ..$ query : chr "exp"
# ..$ params : num -1
# ..$ result : num 0.368
# ..$ output : chr ""
# ..$ warnings: chr(0)
# ..$ messages: chr(0)
# $ :List of 6
# ..$ query : chr "log"
# ..$ params : num -1
# ..$ result : num NaN
# ..$ output : chr ""
# ..$ warnings: chr "production de NaN"
# ..$ messages: chr(0)
# $ :List of 6
# ..$ query : chr "exp"
# ..$ params : num 3
# ..$ result : num 20.1
# ..$ output : chr ""
# ..$ warnings: chr(0)
# ..$ messages: chr(0)
# ...我也不确定你说的“和quietly()玩得好”是什么意思。一开始我担心我会在懒惰的评估上遇到问题,但我没有。
如果您想使用invoke(),可以使用invoke_map()替换函数中的map2(df$f, df$param, ~ .x(.y))行
all.equal(
purrr::map2(df$f, df$param, ~ .x(.y)),
invoke_map(df$f, df$param)
)
# [1] TRUEhttps://stackoverflow.com/questions/42785537
复制相似问题