为什么这不起作用?
my_curve = function (expr, from = NULL, to = NULL, n = 101, add = FALSE,
type = "l", xname = "x", xlab = xname, ylab = NULL, log = NULL,
xlim = NULL, fill="red", ...)
{
sexpr <- substitute(expr)
if (is.name(sexpr)) {
expr <- call(as.character(sexpr), as.name(xname))
}
else {
if (!((is.call(sexpr) || is.expression(sexpr)) && xname %in%
all.vars(sexpr)))
stop(gettextf("'expr' must be a function, or a call or an expression containing '%s'",
xname), domain = NA)
expr <- sexpr
}
if (dev.cur() == 1L && !identical(add, FALSE)) {
warning("'add' will be ignored as there is no existing plot")
add <- FALSE
}
addF <- identical(add, FALSE)
if (is.null(ylab))
ylab <- deparse(expr)
if (is.null(from) || is.null(to)) {
xl <- if (!is.null(xlim))
xlim
else if (!addF) {
pu <- par("usr")[1L:2L]
if (par("xaxs") == "r")
pu <- extendrange(pu, f = -1/27)
if (par("xlog"))
10^pu
else pu
}
else c(0, 1)
if (is.null(from))
from <- xl[1L]
if (is.null(to))
to <- xl[2L]
}
lg <- if (length(log))
log
else if (!addF && par("xlog"))
"x"
else ""
if (length(lg) == 0)
lg <- ""
if (grepl("x", lg, fixed = TRUE)) {
if (from <= 0 || to <= 0)
stop("'from' and 'to' must be > 0 with log=\"x\"")
x <- exp(seq.int(log(from), log(to), length.out = n))
}
else x <- seq.int(from, to, length.out = n)
ll <- list(x = x)
names(ll) <- xname
y <- eval(expr, envir = ll, enclos = parent.frame())
if (length(y) != length(x))
stop("'expr' did not evaluate to an object of length 'n'")
if (isTRUE(add))
lines(x = x, y = y, type = type, ...)
else plot(x = x, y = y, type = type, xlab = xlab, ylab = ylab,
xlim = xlim, log = lg, ...)
polygon(x,y, col=fill) # Add filled area under curve
invisible(list(x = x, y = y))
}
我喜欢在Swift中使用的一个非常酷的功能是能够通过传递一个init方法将一个东西的集合转换为另一个东西(假设存在"abcdefg".characters.map(String.init) // error: type of expression is ambiguous without more context
类型的东西)。
以下是将元组列表转换为init()
实例的示例。
ClosedInterval
该示例还利用了这样一个事实:只要元组与函数的参数列表匹配,我们就可以将参数元组作为单个参数传递。
这是另一个例子,这次将数字列表转换为字符串实例。
[(1,3), (3,4), (4,5)].map(ClosedInterval.init)
不幸的是,下一个例子不起作用。在这里,我试图将一个字符串拆分为单字符串列表。
(1...100).map(String.init)
"abcdefg".characters.map(String.init) // error: type of expression is ambiguous without more context
应该在map()
的列表上运行(事实上,我能够在游乐场验证Swift推断正确的[Character]类型传递到Character
)。
map
绝对可以从String
实例化。
Character
有趣的是,如果角色各自都在自己的数组中,这就有效。
let a: Character = "a"
String(a) // this works
或同等的:
"abcdefg".characters.map { [$0] }.map(String.init)
我知道我可以这样做:
let cx2: [[Character]] = [["a"], ["b"], ["c"], ["d"]]
cx2.map(String.init)
但我特意试着理解为什么"abcdefg".characters.map { String($0) }
不起作用(IMO这种语法也更具可读性和优雅性)
答案 0 :(得分:14)
Simplified repro:
String.init as Character -> String
// error: type of expression is ambiguous without more context
这是因为String
有两个初始值设定项接受一个Character
:
init(_ c: Character)
init(stringInterpolationSegment expr: Character)
据我所知,当使用初始化程序作为值时,无法消除它们的歧义。
至于(1...100).map(String.init)
,String.init
被称为Int -> String
。虽然有两个初始值设定项接受一个Int
:
init(stringInterpolationSegment expr: Int)
init<T : _SignedIntegerType>(_ v: T)
通用类型弱而不是显式类型。因此编译器在这种情况下选择stringInterpolationSegment:
一个。您可以通过命令确认+点击.init
。