Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R中干净、简单的功能工厂_R_Functional Programming - Fatal编程技术网

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


旁注。我不知道“函数工厂”在这里是否合适,因为我不是计算机科学家,但它似乎是相关的。我只找到了。

函数的封装环境不同,导致输出/解压的差异。因此,要获得所需的输出,需要做两件事:

  • 使环境相同
  • 将封闭环境中的变量替换为函数体
然而,这样做的话,你们会得到双倍剂量的eval/你们不想要的替代品,所以也许会有另一种选择

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