Reputation: 28104
From the Swift REPL, how do I get the static type of an expression?
For instance, in Haskell, I can use :type
to get the type of an expression:
Prelude> :type "hello"
"hello" :: [Char]
Prelude> :type (1 + 1)
(1 + 1) :: Num a => a
This is indicating that the type of "hello" is a list of Char
, and the type of (1 + 1) is some type a
in the type class Num
.
There is no obvious way to do this on the Swift REPL but I think it might be possible with the facilities the language already provides. Here is what I've figured out so far. I would be delighted if anyone else holds the missing piece of the puzzle.
These are the various alternatives, none of which is quite right:
As the name implies, dynamicType returns the dynamically determined type of the instance, not the static type of the expression which evaluates to the instance. Also, it does not seem to work from the REPL for Swift types:
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
This function (suggested by a contributor who may wish to remain nameless?) returns a string with the name of the type of foo. However, it evaluates the expression foo. Also, it does not always return the static type, as one can see by running the script below, where the de-mangling function will give the name of one of the randomly computed dynamic types A or B instead of the statically determinable type 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)")
What sounds like the closest thing was a suggestion of @jckarter on Twitter to to define the following function:
func staticType<T>(@autoclosure () -> T) -> T.Type { return T.self }
Since the function captures its argument in a closure, the argument is not evaluated since the closure is never called. However, this has two drawbacks:
If we know how to get the name of a MetaType, for ObjC and Swift types, that would be enough to make this last approach work, at least in scripts if not the REPL.
Upvotes: 2
Views: 483
Reputation: 51911
Swift REPL automatically prints the type and the result of the expression.
1> 1 + 1
$R0: Int = 2
So maybe this can be used:
1> ({ 1 + 1 })
$R0: (() -> Int) = ($__lldb_expr8`__lldb_expr_1.(closure #1) at repl.swift:1)
^^^
or
1> reflect({ 1 + 1 }).valueType
$R0: Any.Type = () -> Int
^^^
2> ({ 1 + 1 }).dynamicType as Any.Type
$R1: Any.Type = () -> Int
Finally, a little bit tweaking 3. a custom generic function:
1> func typeof<T>(@autoclosure () -> T) -> Any.Type { return T.self }
2> typeof(1 + 1)
$R0: Any.Type = Swift.Int
Upvotes: 1