如何在R中执行每一行代码之前运行一个特定的函数?

jq6vz3qz  于 2023-05-20  发布在  其他
关注(0)|答案(2)|浏览(144)

在R语言中,是否可以在每个命令之前运行一段代码?
只是我的用例的一个例子(不是实际的用例)。在每个命令之前打印hi

> print(2)
> print(1)

应给予

hi
2
hi
1

因此,应该有一个函数beforeTaskCall(print("hi")),它将在每行之前调用print("hi")
我发现了addTaskCallback,它会在每个命令后运行一个函数。

g52tjvyc

g52tjvyc1#

要在命令之前运行一段代码,您可以重新定义一元运算符并将其放置在命令之前。

`~` <- function(x) {print("hi"); eval(substitute(x))}

~print(2)
#[1] "hi"
#[1] 2

~print(1)
#[1] "hi"
#[1] 1

其他可能的一元运算符是-+?!
或者使用二元运算符,以防它可以放在函数之后

`?` <- function(x, .) {print("hi"); eval(substitute(x))}

print(2) ?.
#[1] "hi"
#[1] 2

另一种选择是将命令存储为字符串并迭代它们。

s <- c(r"(print(2)
print(1))")

for(x in strsplit(s, "\n")[[1]]) {
  print("hi")
  eval(parse(text=x))
}
#[1] "hi"
#[1] 2
#[1] "hi"
#[1] 1

或者使用addTaskCallback,它在之后调用函数,但也许它可以在这个设置中使用。

invisible(id <- addTaskCallback(function(...) {print("hi"); TRUE}))
#[1] "hi"
print(2)
#[1] 2
#[1] "hi"
invisible(removeTaskCallback(id))
print(1)
#[1] 1
3hvapo4f

3hvapo4f2#

方法一:trace

使用trace将任意R表达式(R代码)插入到函数内的任何位置。

f <- function(x) {
    print(x * 10)
    print(x * 100)
} # Our original function f
m <- expression(print("hello"), print("world")) # An expression m we want to insert into function f
# m <- quote({print("hello"); print("world")}) # Alternative way of defining m
# m <- substitute({print("hello"); print("world")}) # Alternative way of defining m
trace(f, tracer = m, print = FALSE) # Insert expression m at the beginning of function f
f # Check that this function is in trace mode, and read the instruction for seeing tracing code
body(f) # See that our code is inserted correctly
f(3)
[1] "hello"
[1] "world"
[1] 30
[1] 300

untrace(f) # Remove all tracing code
f(3)
[1] 30
[1] 300

使用这种方法,您可以使用tracetracerexitat参数在函数内部的任何位置插入代码,甚至可以使用edit = TRUE参数交互式编辑函数:

开头

trace(f, tracer = m, print = FALSE)
body(f)
{
    .doTrace(expression(print("hello"), print("world")))
    {
        print(x * 10)
        print(x * 100)
    }
}

结束

trace(f, exit = m, print = FALSE)
body(f)
{
    on.exit(.doTrace(expression(print("hello"), print("world"))))
    {
        print(x * 10)
        print(x * 100)
    }
}

内部

trace(f, m, at = 3, print = FALSE)
body(f)
{
    print(x * 10)
    {
        .doTrace(expression(print("hello"), print("world")))
        print(x * 100)
    }
}

互动

trace(f, edit = TRUE, print = FALSE)
# supply your custom version of f using an editor
body(f) # for checking

方法二:基于body(f)构建新函数

f <- function(x) {
    print(x * 10)
    print(x * 100)
} # Our original function f
h_f <- f # copy function f as template
body(h_f) <- substitute({print("hello"); print("world"); m}, list(m = body(f))) # change only body(h_f) to suit our needs
# body(h_f) <- bquote({print("hello"); print("world"); .(body(f))}) # Alternative way of defining body(h_f)
h_f # to check the resulting h_f function
#function (x) 
#{
#    print("hello")
#    print("world")
#    {
#        print(x * 10)
#        print(x * 100)
#    }
#}

h_f(3)
[1] "hello"
[1] "world"
[1] 30
[1] 300

相关问题