この記事はyurue Advent Calendar1日目の投稿です!
AdventCalendar初めての投稿に加え、Qiitaの投稿初心者なので、わかりづらい部分があると思いますので、
その際はご指摘くださいm(_ _)m
Swiftには下記の標準出力関数が用意されています。
普段よく使うprint関数でも見慣れない引数があるのではないでしょうか。
public func print<Target>(_ items: Any..., separator: String = default, terminator: String = default, to output: inout Target) where Target : TextOutputStream
public func debugPrint<Target>(_ items: Any..., separator: String = default, terminator: String = default, to output: inout Target) where Target : TextOutputStream
public func dump<T>(_ value: T, name: String? = default, indent: Int = default, maxDepth: Int = default, maxItems: Int = default) -> T
public func dump<T, TargetStream>(_ value: T, to target: inout TargetStream, name: String? = default, indent: Int = default, maxDepth: Int = default, maxItems: Int = default) -> T where TargetStream : TextOutputStream
中でも今回は、変数の中身を詳細に出力することができるdump関数を紹介したいと思います。
#引数
value: T
value には中身を確かめたい変数を入れます。
今回はできるだけ多くネストした変数として、重連結リストを利用します。
class Node {
let key: Int
var prev: Node?
var next: Node?
init(key: Int, prev: Node?, next: Node?) {
self.key = key
self.prev = prev
self.next = next
}
}
let n0 = Node(key: 1, prev: nil, next: nil)
let n1 = Node(key: 2, prev: n0, next: nil)
n0.next = n1
let n2 = Node(key: 3, prev: n1, next: n0)
n1.next = n2
n0.prev = n2
printで試しに出力してみると、中身が全然わかりませんね。
print(n0) //__lldb_expr_69.Node
ここで、dumpを使うと、かなり詳細に出力してくれます。
dump(n0)
/*
▿ __lldb_expr_69.Node #0
- key: 1
▿ prev: Optional(__lldb_expr_69.Node)
▿ some: __lldb_expr_69.Node #1
- key: 3
▿ prev: Optional(__lldb_expr_69.Node)
▿ some: __lldb_expr_69.Node #2
- key: 2
▿ prev: Optional(__lldb_expr_69.Node)
▿ some: __lldb_expr_69.Node #0
▿ next: Optional(__lldb_expr_69.Node)
▿ some: __lldb_expr_69.Node #1
▿ next: Optional(__lldb_expr_69.Node)
▿ some: __lldb_expr_69.Node #0
▿ next: Optional(__lldb_expr_69.Node)
▿ some: __lldb_expr_69.Node #2
*/
to target: inout TargetStream
where TargetStream : TextOutputStream
とあるように、TargetStreamはTextOutputStream を継承したものである必要がありそうです。
TextOutputStream がわからなかったので調べてみました。公式リファレンス
リファレンスによるとTextOutputStreamはprotocolとして宣言されており、
String型, Substring型はこのprotocolに準拠しているそうです。
ということで、String型の値引数として関数に渡してみたいと思います。
inoutなので、C言語でいうポインタのように&をつけて渡すようです。
var stream: String = ""
dump(n0, to: &stream, name: "", indent: 5, maxDepth: 5, maxItems: 5)
dump(stream)
String型として宣言されたstreamに文字列が追加されていますね。
print(stream)
/*
▿ : __lldb_expr_113.Node #0
- key: 1
▿ prev: Optional(__lldb_expr_113.Node)
▿ some: __lldb_expr_113.Node #1
- key: 3
(2 more children)
(1 more child)
*/
試しにdumpでも同様にやってみましたが、改行は無視されるようです。
dump(stream)
// - " ▿ : __lldb_expr_113.Node #0\n - key: 1\n ▿ prev: Optional(__lldb_expr_113.Node)\n ▿ some: __lldb_expr_113.Node #1\n - key: 3\n (2 more children)\n (1 more child)\n"
name: String? = default
行頭のクラス名の前にラベルを付けることができます。
ログが増えまくってきたときに使うと便利かも。
dump(n1, name: "hogehoge", indent: 5, maxDepth: 5, maxItems: 5)
/*
▿ hogehoge: __lldb_expr_36.Node #0
- key: 2
▿ prev: Optional(__lldb_expr_36.Node)
▿ some: __lldb_expr_36.Node #1
- key: 1
(2 more children)
(1 more child)
*/
試しにnilを入れてみてもnameを指定しない場合と変わらなかったのでdefaultはnilのようですね
dump(n1, name: nil, indent: 5, maxDepth: 5, maxItems: 5)
/*
▿ __lldb_expr_40.Node #0
- key: 2
▿ prev: Optional(__lldb_expr_40.Node)
▿ some: __lldb_expr_40.Node #1
- key: 1
(2 more children)
(1 more child)
*/
indent: Int = default
全体的なインデントの深さを変更できるみたいです。
各行のインデントが変えれればいいのに。
恐らくdefaultは0です。
dump(n1, name: nil, indent: 0, maxDepth: 5, maxItems: 5)
/*
▿ __lldb_expr_42.Node #0
- key: 2
▿ prev: Optional(__lldb_expr_42.Node)
▿ some: __lldb_expr_42.Node #1
- key: 1
(2 more children)
(1 more child)
*/
maxDepth: Int = default
どこまで追うかを決められます。
dump(n1, name: nil, indent: 0, maxDepth: 0, maxItems: 5) //▹ __lldb_expr_50.Node #0
dump(n1, name: nil, indent: 0, maxDepth: 1, maxItems: 5)
/*
▿ __lldb_expr_52.Node #0
- key: 2
▹ prev: Optional(__lldb_expr_52.Node)
▹ next: Optional(__lldb_expr_52.Node)
*/
dump(n1, name: nil, indent: 0, maxDepth: 2, maxItems: 5)
/*
▿ __lldb_expr_54.Node #0
- key: 2
▿ prev: Optional(__lldb_expr_54.Node)
▹ some: __lldb_expr_54.Node #1
▿ next: Optional(__lldb_expr_54.Node)
(1 child)
*/
maxItems: Int = default
出力する行数を指定できます。
maxItems+1の行数が最大で出力されます。
maxItemsに出力が収まらない場合は**(2 more children)**のようにあと何件あるかが出力されます。
dump(n1, name: nil, indent: 0, maxDepth: 5, maxItems: 2)
/*
▿ __lldb_expr_68.Node #0
- key: 2
(2 more children)
*/
どこまでもループするのかと思ったら、一度表示された要素はそれ以上深く追わないようです。
各要素には#0のように番号が振られているので、これを見るとわかりやすそうです。
dump(n1, name: nil, indent: 0, maxDepth: 5, maxItems: 100)
/*
▿ __lldb_expr_70.Node #0
- key: 2
▿ prev: Optional(__lldb_expr_70.Node)
▿ some: __lldb_expr_70.Node #1
- key: 1
▿ prev: Optional(__lldb_expr_70.Node)
▿ some: __lldb_expr_70.Node #2
- key: 3
▹ prev: Optional(__lldb_expr_70.Node)
▹ next: Optional(__lldb_expr_70.Node)
▿ next: Optional(__lldb_expr_70.Node)
▿ some: __lldb_expr_70.Node #0
▿ next: Optional(__lldb_expr_70.Node)
▿ some: __lldb_expr_70.Node #2
*/
明日は @Tsuyoposon です!
よろしくお願いします〜〜!