SwiftのString(文字列) APIとの付き合い方

これは [Swift Tweets](https://swift-tweets.github.io/) の発表をまとめたものです。イベントのスポンサーとして Qiita に許可をいただいた上で、このような形（ツイートの引用）で投稿しています。

以下の内容は熟考した上での自分なりの見解でありますが、公式に記載されていないものが多く含まれています。もし誤りなど見つけたら指摘していただけると助かります。

---

<blockquote class="twitter-tweet"><p dir="ltr">それでは、「SwiftのString(文字列) APIとの付き合い方」の発表を始めます。
https://swift-tweets.github.io の発表概要に記載した通り、そこに挙げている3つの記事は理解済みの前提とします(そうでなくとも分かる話も多いと思いますが)。
 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820282557602217986"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">まずSwiftの文字列処理をコード例を交えながら見ていきます。SwiftのStringはCharacter・Unicode Scalar・UTF-16・UTF-8という4つのView(表現)を持っています。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820282690746232832"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">通常の文字列処理では書記素クラスタ表現であるCharacter Viewを主に扱うことになるはずです。
書記素クラスタとは、抽象文字すなわち目で見た一文字単位の集合です。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820282816688594945"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">CharacterViewはStringから`.characters`でアクセスできて、各種使用例はこれらのリファレンスに書かれていま
す:

- https://developer.apple.com/reference/swift/string
- https://developer.apple.com/reference/swift/string.characterview #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820282942488354816"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">リファレンスのOverviewにある通り一般的な文字列操作が一々面倒です。カウントするだけでもcharactersを介す必要があり、さらにIntによるsubscriptも不可でIndex型による操作を強いられます。 #swtws

https://gist.github.com/013284d6f82c203a912ef9a8ca97c584</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820283074667692032"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">こういった扱いのしにくさは、SwiftのString APIが厳密となっているトレードオフであるものの、とはいえ普段の
文字列処理の際に一々煩雑な記述を強いられるのは抵抗も感じます。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820283195543285760">
</a></blockquote>



<blockquote class="twitter-tweet"><p dir="ltr">この扱いにくさへどう対処するのが良いか、いくつかの観点で考察していきます。
まずCharacter Viewなど4つのViewに分かれているのは、「文字列」といっても色々な表現があることに依ります。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820283321431117828"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">それが予めきちんと分類されているのは良いですが、最も扱う頻度の多いCharacter Viewをデフォルトで直接扱いたくなってきます。
String APIを触っていると実は標準で中途半端にそうなっていることが見受けられます。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820283447465783296"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">例えば、StringからもIndexを取得できますが、それはCharacterViewのIndexのtypealiasとして定義されているため、実はcharactersを介して取得したものまったく同じです。 #swtws

https://gist.github.com/bedd7c8db9359ed90fe38610d08527fa</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820283580815327233"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">取得できるIndexが同一ということは、すなわちStringはデフォルトでCharacter View扱いとなっているとみなせるのではないでしょうか。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820283700642385920"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">カウントも、Index距離を利用することで、charactersを介さずCharacter Viewのcountと同じものを取得することが可能です。 #swtws

https://gist.github.com/b9018816e92b415166912024382e93b2</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820283832016343040"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">以上のようにStringから直接取得したIndexはCharacter ViewのIndex操作に使えるので、Indexはcharactersを介さずに済み少しシンプルな記述とできます。 #swtws

https://gist.github.com/d6e1ecadb623735cfe8cf95270b218bc</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820283963721691136"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">また、Stringには `substring` メソッドもあるので、次のように書くこともできます(パフォーマンスは少し劣る)。いずれの方法にせよ、characters介さなくて済むところは省略すると多少楽になります。 #swtws

https://gist.github.com/364c61015d47a63b20028336db806223</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820284090192494592"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">以上のように、APIの作り的にも挙動的にもStringはデフォルトでCharacter View扱いとみなせ、かつそれを利用して多少楽になると思っていますが、まだ多少違和感が残っています。
一番不思議なのは、Stringに対して直接`count`できないことです。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820284216126541824"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">これは、StringがBidirectionalCollection・RangeReplaceableCollectionに準拠するようにすれば、ほぼcharactersと同じメソッドを直接呼べるようになります。 #swtws

https://gist.github.com/dcd7058ec47adffe52f1f933ec98deee</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820284347555057665"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">これを施すとcountだけでなく、コレクション操作や、`prefix`・`suffix`などInt指定で部分文字列取得できるようになったりと色々便利になります。 #swtws

https://gist.github.com/922fb77651f1f1ea37f5c0062560ce8d</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820284478140518401"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">ただ、これは罠もありそうなので、注意して取り扱った方が良さそうです。詳しくは https://medium.com/swift-column/swift-string-16245b2723b4#.achuihxel に書きましたが、`var`で定義した文字列に`removeFirst(_:)`を使うとクラッシュして対処が必要でした。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820284595614597120"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">なので、この方法を用いるかどうかの判断はお任せします。僕は、文字列内容によってクラッシュすることは無さそう・開発段階で罠も充分検知できるだろう、と感じているので実際に活用しています。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820284721397571589"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">一旦まとめると、Stringは元々Character Viewをデフォルトとみなしているようなのでcharactersプロパティを省略することで多少簡潔に書けること、さらにStringをコレクション系のプロトコルに準拠させるとより強力になることを紹介しました。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820284847386038272"></a></blockquote>


<blockquote class="twitter-tweet"><p dir="ltr">次に、Indexの取り扱いについてです。今までのコード例を見れば分かる通り、Intで直接subscript操作出来ずに、startIndex・endIndexからのoffsetで辿っていく作りになっているのが面倒です。 #swtws<p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820284973164806144"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">もちろんこれも理由があって、僕は主な理由は高コストな操作であることを意識させるようなAPIとなっているからだと思っています。 #swtws</p>&mdash;@_mono <a href="https://twitter.com/_mono/status/820285099040083969"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">StringおよびそのViewはRandomAccessCollectionではなくBidirectionalCollectionということもポイントです:
- https://developer.apple.com/reference/swift/randomaccesscollection
- https://developer.apple.com/reference/swift/bidirectionalcollection #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820285224898547713"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">特にCharacter Viewにおいて抽象文字すなわち目で見た何文字かという概念で文字列を走査・カウントするのは、それらの文字部分に至るまで先頭あるいは終端からすべて走査していく必要があります。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820285350614421505"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">この性質が顕著に表れているのが`count`プロパティで、その計算量はO(n)です。
APIデザインガイドラインには、プロパティは `O(1)` であるべきで、そうでない場合はドキュメントに書くように、記載されていてちょうどその例外にあたります。
#swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820285489420718080"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">`count`に限らず、同様に多くの文字列アクセスはその性質上 `O(n)` となっています。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820285615006588928"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">Swiftでは所望のIndex取得のAPIを始端・末端からのO(n)の走査であることを意識させて、Indexを用いたsubscriptなどの部分文字列取得処理はO(1)という設計になっています。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820285740776947712"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">文字列終端付近のIndexを始端から辿るとほぼ文字列全スキャンとなりますが、終端からアクセスするとO(1)に近い効率の良い処理となります。 #swtws

https://gist.github.com/aa10c3cee112e26d4d4aedf53269b01f</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820285886998794241"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">文字列終端付近のIndexを始端から辿るとほぼ文字列全スキャンとなりますが、終端からアクセスするとO(1)に近い効率の良い処理となります。 #swtws

https://gist.github.com/aa10c3cee112e26d4d4aedf53269b01f</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820285886998794241"></a></blockqu

<blockquote class="twitter-tweet"><p dir="ltr">しかし他のIntでsubscriptアクセスできる言語では文字列アクセスは非効率というわけではないです。例えばRubyだと次の書き方はともに文字列の最後を取得する処理ですが、後者のように高効率に書くことができます。 #swtws

https://gist.github.com/26b3b999a0281c9ecd0f9076f50f461f</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820286011448012801"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">このように、Indexで文字列範囲を指定するのは、パフォーマンス担保のための必然ではなく、単に高コストな操作であることを意識しやすいようになっているだけということだと思っています。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820286133179293696"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">また、SwiftのStringはCharacter Viewベースになっていることを意識しながら扱えば、IndexではなくIntで直接部分文字列の範囲指定しても破綻しないです。 #swtws

https://gist.github.com/70b0423cca0c43b70a7b5993ef5eed47</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820286267350880256"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">とはいえ、せっかくSwiftがパフォーマンスに気を使ったAPI設計にしているのに、`str[1..&lt;3]` のようにアクセスできる`subscript`などを追加してしまうのはちょっと躊躇します。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/82028638647330816

<blockquote class="twitter-tweet"><p dir="ltr">前述の通りパフォーマンスを意識させることが本質ということは、それを明示すれば良いということで、次のようにラベル付き(sequentialAccessとしました)のsubscriptを定義すれば良いのではと思いました。 #swtws

https://gist.github.com/6c6d837cd75dffdf63a656ec50b81314</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820286523559985152"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">ラベルで通常の挙動とは違うことを明示するのは https://github.com/apple/swift-evolution/blob/master/proposals/0080-failable-numeric-initializers.md のイニシャライザーでも提案されていますし、分かりやすいかなと思っています。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820286642111942656"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">文字列の始端からベタに走査する処理にのみ対応していて、`str[sequentialAccess: -1]` などで終端から効率よく辿れるようになどもサポートする余地もありますが、パフォーマンス気になる処理は標準APIをベタに使えば良いかなとも思ったり。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820286767752327168"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">一応 https://github.com/mono0926/SwiftyStringExtension で公開していますが、まだこっそり自分のプロジェクトに使っているだけで公にはリリースしていないです。利用する場合、罠が潜んでいる可能性もあるので、ご注意ください。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820286893816352769">
</a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">SwifterSwift では、ラベル無しのsubscriptメソッドを追加していますが、標準APIのごとくカジュアルにパフォーマンス問題になりそうな記述ができてしまうので、ちょっと危険かなと思いました(便利ですが)。
https://github.com/omaralbeik/SwifterSwift/blob/master/Source/Extensions/StringExtensions.swift#L279-L310 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820287031972491264"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">また、IntでStringの要素にアクセスして良いかという懸念はパフォーマンス以外にもNSStringとの相互運用にもありそうです。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820287157885468672"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">次の場合StringにRange&lt;Int&gt;でアクセスできてしまうと「元のNSStringの部分文字列」と「NSRangeをtoRangeという標準メソッドで変換してStringから取得した部分文字列」が食い違います。 #swtws

https://gist.github.com/7f97f53234c4567acde4140106b13313</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820287288986857472"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">UITextViewなど扱っていると、APIから返ってくるレンジがNSRangeだったりするので、それを安易にStringに適用してしまうと取得できる文字列を間違えたりクラッシュしてしまうことなどにつながります。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820287410529398784"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">標準のsubstringメソッドは、Range&lt;String.index&gt;を受けるようになっていてRange&lt;Int&gt;は受け付けないため、先ほどのミスはコンパイルエラーで防げます。Stringを「便利」にした際はこのあたりにも気を付ける必要が出てきます。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820287536421404672"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">ちなみにどう対処するのが良いかというと、2つの方法が考えられます。
1つめは、StringをNSStringにキャストしてからNSRangeで部分文字列取得するやり方です。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820287662242156545"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">2つめは、NSRangeはUTF16のIndex範囲であるので、それを元に適切なRange&lt;Int&gt;に変換して、Stringから部分文字列取得するやり方 ( https://medium.com/swift-column/swift-string-16245b2723b4#.achuihxel に記載 )です。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820287788159406080"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">NSプレフィックス系の型を極力扱いたくなかったので、僕は後者を選択していますが1つめのやり方の方が素直な気もしています🤔 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820287926391033856"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">以上で、現状のSwiftのString APIの扱いのしにくさの本質はどこにあるのかの説明と、それに対する自分のアプローチを紹介しました。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820288052232736770"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">別解としては、 @koher さんがこっそり公開している https://github.com/koher/easy-text のアプローチも良いなと思いました。
初期化時にStringのCharacter Viewを、Arrayとして保持してしまう、という富豪的な実装になっています。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820288178120630276"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">イニシャライザーで文字列全スキャンするためO(n)となっていて( https://github.com/koher/easy-text/blob/master/Sources/Text.swift#L4-L6 )イレギュラーなので実際ライブラリとして公開する場合、その旨をコメントに書いてあると良いかなと思いました。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820288304037793792"></a></blockquote>

【補足】
次の議論もあり、特に明記せずにイニシャライザーで処理しても許容範囲の計算量かもしれません。

<blockquote class="twitter-tweet" data-lang="en"><p lang="ja" dir="ltr"><a href="https://twitter.com/_mono">@_mono</a> もちろん1億倍のようなケースは許容できないと思いますが、大抵のケースでカジュアルに使っても問題にならなさそうな係数だろうなという認識です。↓のStringのinitと変わらないですよね？ <a href="https://twitter.com/hashtag/swtws?src=hash">#swtws</a><a href="https://t.co/tOAv3xGXUS">https://t.co/tOAv3xGXUS</a></p>&mdash; koher (@koher) <a href="https://twitter.com/koher/status/820323001954537476">January 14, 2017</a></blockquote>

とはいえ、[Character Viewの全スキャンはこのパフォーマンス測定結果見ても分かる通り、まあまあ高コストです](https://gist.github.com/mono0926/6839352ed11136f0d1a860e5390e2806)。


---補足終わり---

<blockquote class="twitter-tweet"><p dir="ltr">また、他の言語でもおそらく文字列の初期化時にその全スキャンがかかるようになっているのは珍しいはずなので取り扱いには注意ですが、普段多く扱うような大した長さでは無い文字列処理はすごくやりやすくなりそうで良いと思いました。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820288433616666624"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">あるいは、`NSString`にキャストするとIntで範囲指定できるようになりますが、抽象文字がUTF16一つで表現できる時しか使えなかったり微妙です(そもそもNSプレフィックスの型は極力使わない方が良いですね) #swtws

https://gist.github.com/e33b86ffb0a77d8ad6de7899a0225a2a</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820288565800091655"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">さきほどのNSStringのコード例見ると分かる通り、そういえばObjective-C時代から文字列処理はやりにくくて、それに開発者が慣れてしまっている感もあるかなと思いました(　´･‿･｀)
今後Swiftの標準APIが改善されていくのを期待しています。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820288686587723776"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">https://github.com/apple/swift-evolution/blob/master/README.md の「String re-evaluation」という項目にも注目です。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820288812475518976"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">Swift 4で文字列周りに変更ありそうな記述ですが、あまり動きが無いので間に合わず5以降になるかもと思っています。

&gt; Swift 4 seeks to make strings more powerful and easier-to-use... #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820288938321424385"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">以上、改めてSwiftの文字列処理に向き合ってみましたが、現状初学者が触れる際の最も大きな関門の一つになる程度には扱いにくいと思いました。Swift 3までの変更の多さもあいまって、適当にぐぐって所望の文字列処理をするまでかなり苦労しそうです。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820289064226041856"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">少し枠が余ったので、最後にSwiftに限らずですが悩ましい文字列のカウント問題について触れていきます。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820289190160048128"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">Swiftは後発なだけあって、良く出来ています。Viewで表現が分かれているのは前述の通りですが、次の&quot;🇯🇵&quot;のように複数のコードポイント(unicode scalar)を組み合わせたものにも概ね対応しています。 #swtws

https://gist.github.com/f2a86f6c2ab88ee9162e2732ab85215f</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820289328261664771"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">ただ、未対応のものもあって、👍🏼(肌トーン付き)や👩‍👩‍👧‍👦(複数絵文字の連結)は、characters.countでは複数扱いになってしまいます。 #swtws

https://gist.github.com/e358c2fb62eec262beb65bace48cdddd</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820289457605611522"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">このあたりは自前でやるしかないかというとそうではなく、 `enumerateSubstrings(in:options:_:)` にて列挙すると、ともに正しく1文字扱いされます。

https://developer.apple.com/reference/swift/string/1643111-enumeratesubstrings #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820289577726291970"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">ただ、このメソッドで厳密に数えるのが常に正解かというと、特にマルチプラットフォームの場合は必ずしもそうではなく各プラットフォーム・データベースの扱いやすさなど踏まえて、良い感じに妥協仕様にするのが現実的かなと思っています。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820289703551172608"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">ちなみに僕のTwitter名は、現在&quot;🐶Monor Swift🐶🍎💻📱⌚️&quot;にしていますが、ブラウザでは入力出来たもののiOS版では20文字オーバーと判定され編集できなくて不便で困っています。NSStringでカウント(UTF16でのカウント)してそうです👀 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820289829606866944"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">新しめの絵文字などのカウントに追従できていないのは仕方ないですが、せめてプラットフォームで揃える努力はして欲しいなと思いました。 #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820289957902192640"></a></blockquote>

<blockquote class="twitter-tweet"><p dir="ltr">最後ちょっと余談になりましたが、発表は以上です。
ごTweet聴ありがとうございました(　´･‿･｀) #swtws</p>&mdash; @_mono <a href="https://twitter.com/_mono/status/820290086289838080"></a></blockquote>