R中干净、简单的功能工厂
简短示例。我通过使用不同的“规格”测试函数,探索函数的行为,R中干净、简单的功能工厂,r,functional-programming,R,Functional Programming,简短示例。我通过使用不同的“规格”测试函数,探索函数的行为,f(规格)。我亲手写下了一个规范,spec1,并且正在创建新的规范作为它的变体。为此,我决定编写一个函数: spec1 = list(fy = list(a = 1), fx = list(f1 = function(x) 10-x, f2 = function(x) 2-x)) make_spec = function(f = function(x) 10-x, xtheta = 2) list(fy = list(a =
f(规格)
。我亲手写下了一个规范,spec1
,并且正在创建新的规范作为它的变体。为此,我决定编写一个函数:
spec1 = list(fy = list(a = 1), fx = list(f1 = function(x) 10-x, f2 = function(x) 2-x))
make_spec = function(f = function(x) 10-x, xtheta = 2)
list(fy = list(a = 1), fx = list(f1 = f, f2 = function(x) xtheta-x))
res1 = make_spec()
# first problem: they don't match
all.equal(res1,spec1)
# [1] "Component “fx”: Component “f2”: target, current do not match when deparsed"
# ^ this happens, even though...
res1$fx$f2(4) == spec1$fx$f2(4)
# TRUE
# second problem: res1 is fugly
res1
# $fy
# $fy$a
# [1] 1
#
#
# $fx
# $fx$f1
# function (x)
# 10 - x
# <environment: 0x000000000f8f2e20>
#
# $fx$f2
# function (x)
# xtheta - x
# <environment: 0x000000000f8f2e20>
str(res1)
# even worse
旁注。我不知道“函数工厂”在这里是否合适,因为我不是计算机科学家,但它似乎是相关的。我只找到了。函数的封装环境不同,导致输出/解压的差异。因此,要获得所需的输出,需要做两件事:
- 使环境相同
- 将封闭环境中的变量替换为函数体
make_spec <- function(f = function(x) 10-x, xtheta = 2) {
e <- parent.frame()
fixClosure <- function(func)
eval(eval(substitute(substitute(func)), parent.frame()), e)
list(fy = list(a = 1), fx = list(
f1 = fixClosure(f),
f2 = fixClosure(function(x) xtheta-x)
))
}
spec1 <- list(fy = list(a = 1), fx = list(f1 = function(x) 10-x, f2 = function(x) 2-x))
res1 <- make_spec()
all.equal(res1, spec1)
[1] TRUE
make_spec实际上,您似乎不喜欢R,并且正在寻找另一种语言,可能是Scala或erlang。。str
函数相当复杂,但当然欢迎您重写它。这将是一个大型项目,远远高于合理的SO问题。试图在不使用eval
和substitute
的情况下在该语言上编程的想法似乎有悖常理,毫无道理。@42-感谢您的反馈。嗯,避免eval
和substitute
在我的优先级列表中是很低的,但是如果我只是愚蠢地忽略了一些避免它们的方法,我很想知道。你可以使用library(pryr)
,res1$fx@Chris获得第1部分(笨拙,因为你返回的不仅仅是一个函数),这很方便,谢谢!我还得再看看那个包裹。你可以在你发布的链接上看到更多。正如@jenesaisquoi所指出的,奇怪的打印(和all.equal)行为是因为R函数和闭包如何使用环境。谢谢。我对这里使用的eval和substitute很满意,我喜欢这种方法。我将把这个问题留一段时间,因为我暂时没有机会对我原来的问题应用任何解决方案。
make_spec <- function(f = function(x) 10-x, xtheta = 2) {
e <- parent.frame()
fixClosure <- function(func)
eval(eval(substitute(substitute(func)), parent.frame()), e)
list(fy = list(a = 1), fx = list(
f1 = fixClosure(f),
f2 = fixClosure(function(x) xtheta-x)
))
}
spec1 <- list(fy = list(a = 1), fx = list(f1 = function(x) 10-x, f2 = function(x) 2-x))
res1 <- make_spec()
all.equal(res1, spec1)
[1] TRUE