Swift地图问题

时间:2015-03-08 16:57:20

标签: swift

尝试理解地图,然后写一个来测试它,

func map<A, B>(x: A?, f: A -> B) -> B? {
  if let x1 = x {
    return f(x1)
  }
  return nil
}

let test1 = [1, 2, 3, 4]
println(test1)
let test2 = map(test1, { $0 + 1 })
println(test2)

let test3: [Int?] = [5, nil, 7, 8]
println(test3)//[{Some "aaa"}, {Some "bbb"}, nil, {Some "ccc"}]
let test4 = map(test3, { $0 + 1 })
println(test4) //"Optional(0x00007fb7ea61e190)"

但为什么test4无法输出值,只显示一个指针?

1 个答案:

答案 0 :(得分:5)

指针说明

这里发生的是你正在将数组隐式转换为指针,这是出于C兼容目的。

通常,您无法将1添加到数组中。我的意思是,这样做意味着什么?但是,Swift确实将数组隐式转换为指针,因此您可以将数组传递给C函数:

import Darwin
// prints out “hello” using a standard C function that takes a char*
puts([104,101,108,108,111,0])

可以为指针添加整数(做好ol'指针算术):

// x will be an UnsafePointer<Int>
let x = [1,2,3] + 1

现在,为了阻止你意外地执行此操作,只有假设才能处理文字:

let a = [104,101,108,108,111,0]
// error: binary operator '+' cannot be applied to operands of type '[Int]' and 'Int'
let x = a + 1

但是当使用泛型函数时,这种转换仍然会发生(可能是无意的)。

地图问题

从您的定义看,您正在尝试为选项编写map版本 - 也就是说,需要一个可选项,并在内容中映射内容。

但是,不是映射选项,而是将它用于序列。事实上,在您的代码段中,在let test2 = map(test1, { $0 + 1 })行上,您根本没有调用map - 您正在调用采用序列的标准库版本(并返回一个数组)。尝试在那里放一个assert(false) - 你会发现第一次没有调用它。

选项的映射和数组的映射在概念上非常相似。这是因为选项和数组都是“仿函数” - 可以“映射”的东西的名称。将它们视为容器 - 包含其他类型的类型。在可选项的情况下,它们包含或不包含值。在数组的情况下,它们包含任意数量的值。但是在这两种情况下,有一个函数可以应用于“内容”,同时将它们留在“容器”中。

请考虑以下代码。它有两个映射,用于序列和选项,并依次应用它们。最后一个例子似乎是你在问题的最后一个案例中寻找的 - 在一个选项数组的每个成员上映射加一。这实际上是两张地图,一张在另一张中。

func mymap<A, B>(x: A?, transform: A -> B) -> B? {
    println("map for optionals called!")
    if let x1 = x {
        return transform(x1)
    }
    return nil
}

func mymap<S: SequenceType, T>(source: S, transform: S.Generator.Element -> T) -> [T] {
    println("map for sequences called!")
    var result: [T] = []
    for x in source {
        result.append(transform(x))
    }
    return result
}

let test1 = [1, 2, 3, 4]
// prints "map for sequences called!"
let test2 = mymap(test1, { $0 + 1 })
println(test2) // prints

let test3: Int? = 5
// prints "map for optionals called!"
let test4 = mymap(test3, { $0 + 1 })
println(test4) // Optional(6)

let test5: [Int?] = [1, nil, 3, 4]
// prints "sequences called" followed by 4 "optionals called"
let test6 = mymap(test5) { mymap($0) { i in i + 1 } }
println(test6) // [Optional(2), nil, Optional(4), Optional(5)]