从Swift REPL,我如何获得表达式的静态类型?

时间:2014-11-20 16:14:54

标签: swift

从Swift REPL中,我如何获得表达式的静态类型?

例如,在Haskell中,我可以使用:type来获取表达式的类型:

Prelude> :type "hello"
"hello" :: [Char]

Prelude> :type (1 + 1)
(1 + 1) :: Num a => a

这表明"你好"的类型是Char的列表,(1 + 1)的类型是类型类a中的某种类型Num

在Swift REPL上没有明显的方法可以做到这一点,但我认为这可能是语言已经提供的设施。这是我到目前为止所知道的。如果其他人掌握了这个难题的遗失,我会很高兴。

这些是各种选择,其中没有一个是正确的:

1。 dynamicType

顾名思义,dynamicType返回动态确定的实例类型,而不是表达式计算实例的静态类型。此外,它似乎不适用于Swift类型的REPL:

1> 1.dynamicType
error: could not fetch result -- Couldn't apply expression side effects : Couldn't dematerialize result: corresponding symbol wasn't found
2> struct Foo { let val:Int = 1 }
3> let f = Foo()
4> f.dynamicType
error: could not fetch result -- Couldn't apply expression side effects : Couldn't dematerialize result: corresponding symbol wasn't found

2。 _stdlib_getDemangledTypeName(富)

此函数(由可能希望保持无名的贡献者建议?)返回一个名为foo类型的字符串。但是,它会计算表达式foo。此外,它并不总是返回静态类型,正如人们可以通过运行下面的脚本看到的那样,其中de-mangling函数将给出一个随机计算的动态类型A或B的名称,而不是静态可确定的类型Any:

#!/usr/bin/swift
import Foundation

class Letter { } ; class A : Letter {} ; class B : Letter {}
func randomAny() -> Any { println("side-effecting!"); return (arc4random() % 2) == 0 ? A() : B() }
let x : Any = randomAny()  // x has the static type of Any
let typeNameOfX = _stdlib_getDemangledTypeName(x)
println("the constant x with static type Any reports a type name of : \(typeNameOfX)")

3。自定义通用函数

听起来最接近的是@jckarter在推特上建议定义以下功能:

func staticType<T>(@autoclosure () -> T) -> T.Type { return T.self }

由于函数在闭包中捕获其参数,因此不会计算参数,因为从不调用闭包。但是,这有两个缺点:

  1. 在REPL中调用它只会产生错误。
  2. 在脚本中调用它会返回一个MetaType实例,似乎没有一般的方法可以从MetaType实例转到人类可读的字符串,指示实例描述的类型。
  3. 如果我们知道如何获取MetaType的名称,对于ObjC和Swift类型,这足以使最后一种方法起作用,至少在脚本中如果不是REPL。

1 个答案:

答案 0 :(得分:1)

Swift REPL自动打印表达式的类型和结果。

  1> 1 + 1
$R0: Int = 2

所以也许这可以用:

  1> ({ 1 + 1 })
$R0: (() -> Int) = ($__lldb_expr8`__lldb_expr_1.(closure #1) at repl.swift:1)
            ^^^

  1> reflect({ 1 + 1 }).valueType
$R0: Any.Type = () -> Int
                      ^^^
  2> ({ 1 + 1 }).dynamicType as Any.Type
$R1: Any.Type = () -> Int

最后,稍微调整 3。自定义通用功能

  1> func typeof<T>(@autoclosure () -> T) -> Any.Type { return T.self } 
  2> typeof(1 + 1)
$R0: Any.Type = Swift.Int