在map()中使用init()

时间:2015-11-25 01:01:59

标签: swift swift2

TL; DR

为什么这不起作用?

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这种语法也更具可读性和优雅性)

1 个答案:

答案 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