Magnolia Tech

いつもコードのことばかり考えている人のために。

Scala3学習メモ: 新しい制御記法

Scala3では、“quiet” syntaxと呼ばれるPythonっぽい新しい記法が導入されていて、括弧が大幅に削減できるようになっています。

おそらく一番大きな変化点ですね。Scala3ベースの解説書である『Programming in Scala Fifth Edition』もすべてのコード例がこの記法に置き換わっているので、今後は統一されていくのでしょう。

ifの条件式に括弧が不要になり、代わりに条件式の終わりを示すthenというキーワードを置きます

$ cat test.scala
@main def example =
  val x = 1
  if x == 1 then
    println("one")
$ scala test.scala
one

(はてなブログのカラーシンタックスは既にthenをキーワードとしてハイライトするようになっているようですね)

whileの条件式に括弧が不要になり、代わりに条件式の終わりを示すdoというキーワードを置きます

$ cat test.scala
@main def example =
  var x = 1
  while x != 0 do
    x -= 1
    println("one")
$ scala test.scala
one

forやtryでも同様です。

クラスやメソッド定義でも括弧が不要になりました

$ cat test.scala
@main def example =
  Hello.hello()

object Hello:
  def hello() =
    println("hello")
$ scala test.scala
hello

C言語風のシンタックスから大きく変えてきたのが驚きですが、従来の記法もまだ使えます。

また、従来の形式のソースファイルを、scalac [ファイル名] -rewrite -indentというオプションを与えると、コンパイルと同時に元のソースコードを新しい形式に書き換えてくれます(コメント等はちゃんと残ります)。

$ cat oldstyle.scala
package example

object Test {
  var answer = 42
  def hello(): Unit = {
    if (answer == 42) {
      println("hello")
    }
  }
}

$ scalac oldstyle.scala -rewrite -indent
[patched file oldstyle.scala]

$ cat oldstyle.scala
package example

object Test:
  var answer = 42
  def hello(): Unit =
    if (answer == 42)
      println("hello")

元に戻したいときは、 -rewrite -no-indentで書き換えられます。また、特に何のオプションも与えなければ、一つのソースコードの中で従来の記法と新しい記法が混在していても問題ありませんが、-old-syntaxや、-new-syntaxというオプションをセットすることで、記法を強制できます(異なる記法はコンパイルエラー)。

なお、インデントだけだと可読性が悪い(インデントの階層がネストしている、コードの行が長い)場合には、オプションとしてendというキーワードを差し込めます。rubyのendと違うのは、後ろに閉じたい内容を書かないといけないところです。ifを閉じるなら、end ifだし、fooというメソッドの定義を閉じたい時には、end fooとなります。従来のbraceであれば一発で対応関係を確認する方法がエディタに用意されていましたが、これでは独自のプラグインを書かないと分からないですね

package example

object Test:
  var answer = 42
  def hello(): Unit =
    if (answer == 42)
      println("hello")
      val x = 1
    end if
  end hello

公式ドキュメントには-rewrite -new-syntax-rewrite -old-syntaxで書き換えられる、という記載があるのですが、どうもできないようです(記述誤りか?)

なお、当然ですが、インデントの法則が完全に変わってしまうので、例えばvim-scalaのようなScala3に対応していないプラグインではインデントが崩れてしまいます。

僕らはいつまでUSB Type-Cケーブルを選ぶのに迷うのだろう…まだ迷っている人のための覚え書き - 2021年、夏

自分用の買い物メモ、Thunderbolt4ケーブルが続々とリリースされてきたので、2021年夏用にアップデート。

いつもの「全部同じじゃないですか」案件。


USB Type-Cケーブルの選び方は難しい…あらゆる規格をサポートするけど、あらゆる規格を”同時に”サポートするわけではないので、主にケーブル長や用途などで上手く選ばないと、使えなかったり、無駄に高いケーブルを選ぶことになってしまう

そんなことを起こさないためのメモ

あれこれ迷わないための”全部入り”

  • 低速から高速まで色々な周辺機器の接続に使う(USB2.0, USB3.2, USB4, Thunderbolt3, 4)
  • ディスプレイ接続に使う(DisplayPort)
  • 給電に使う(最大100W)

などなどを考えると、Thunderbolt4のケーブルを選ぶと全部対応している。長さは2.0mまで選べる。

Thunderboltのマークと規格を示す数字がコネクタに刻印(「⚡︎ 4」)されているものを選んでおくと後で「これ何の規格のケーブルだっけ?」とならないので便利。USB規格のケーブルは何も規格の種類を示す刻印がなかったり、最大転送速度を示す刻印しか無く、タグをつけておかないと確実に分からなくなる。

価格は0.8mで3000円程度、2.0mだと倍の6000円くらい。

Thunderbolt3は長さによってパッシブケーブル、アクティブケーブルといったケーブルの種類の違いが有ったけど、Thunderbolt4はその違いは無い。また規格上USB PDによる100Wまでの給電対応は必須ではなかった(でもたいてい対応していた)けど、Thunderbolt4は規格上必ず100W対応している...つまり、迷うことなく、分かりやすい。

Thunderbolt4ケーブル、全部入りなので迷うことがない分便利だが、値段は単なるケーブルとして見るとちょっと高いので、用途を絞れば選択肢が広がる。

Type-Cケーブルを使う主な用途と言えば、USB PDによる給電か、給電+ディスプレ接続か、そして本来のデータ転送となるが、Thunderbolt4の規格が示す40GB/sの転送速度が必要になる場面はあまり無いので用途に合わせて選んだ方が良い。

USB PD給電のためのケーブル選び

  • 使っているUSB PD充電器の仕様を確認し、3Aを越える電流に対応しているか確認する。

  • 3Aを超えない場合、USB 2.0規格かつ、USB PD対応で60Wとか、3Aまでと書かれている安価なケーブルを探す。

USB2.0かつ、3Aまでだと規格上、eMarkerチップが不要なため価格も安いし(1000円くらい)、製品の選択肢も多い。念のためにUSB PDサポートと書かれているものを選んだ方が良い(規格上、非対応、ということはないけど、念のため)。

短いケーブルはUSB PD対応のモバイルバッテリ接続に便利だし、壁や机の下のコンセントに刺したUSB PD充電器から電源を取る場合は、少なくとも1.8mは欲しいところ。

  • 3Aを越える場合は、USB 2.0規格かつ、USB PD対応で100Wとか、5Aまでと書かれているケーブルを探す。

eMarkerチップの分だけ多少高い(1600円〜1800円くらい)。Windows PCの場合、必要なワット数がスペックから分からないことも多いので、不安ならとりあえず5A対応のものを買っておけば間違いは無い。

  • 長いケーブルは巻いて収納することを考慮してケーブルの硬さなどに注意、なるべくしなやかに巻けるケーブルを選ぶ。

ディスプレイ接続のためのケーブル選び

  • 「オルタネートモード(Alternate Mode)対応」「ディスプレイ接続用」と明記されているか確認する

  • 給電を併用する場合、ディスプレイ側がサポートしている電流を確認(3A、5A)

だいたい2000円くらいで買える。

  • 2.0mまでならUSB 3.2 Gen 1x1(USB3.0、USB 3.1 Gen1)対応のケーブルが比較的安価

USB 3.2 Gen 2x1(USB 3.1 Gen 2)、USB 3.2 Gen 2x2は規格上、ケーブル長が1.0mに制限されるので、規格上2.0mまで対応しているUSB 3.0(USB 3.1 Gen1)対応のケーブルを探した方が良いけど、あまり製品の種類は無い模様。

データ転送(周辺機器接続用)のType-Cケーブル選び

  • USB 3.1、UBS3.2、USB4、Thunderbolt3,4といった規格のケーブルを周辺機器が対応する規格に合わせて買う(それは、そう)。

最近はUSB 3.2 Gen 2x1(USB 3.1 Gen2)対応の安価なストレージも増えてきたので、間違ってUSB 3.0(USB 3.1 Gen1)やUSB2.0までしかサポートしていないケーブルを買わないように注意が必要。

おわりに

Type-Cコネクタを使った規格がどんどん増えていって、全然分からなくなってきた。特にUSB 3.xの名称は非常にわかりづらく、混乱し易い……USB 3.0、USB 3.1、USB 3.2、USB4と詳しい人じゃないとまず分からないし、同じ規格に複数の名前がついている(USB 3.0とUSB 3.2 Gen1が同じと言われても...)。さらに、USBのケーブルを探すのに、Thunderbolt3や、4という規格のケーブルを買うといいよ、と言われても詳しく無い人にとって完全に意味不明になってきた。

だけど、自分の用途に合ったケーブルを選ぶようにしましょう。迷ったらThunderbolt4ケーブルを買っておきましょう、お金で解決。

学ぼうとしたことが頭にぜんぜん入ってこないとき

自分は割と「ゆっくり音読する」が一番効果が有る(と信じている)のだけど、人に依ってはただ黙読するだけで理解できる人もいるし、その回数に違いが有ったり、ノートに自分なりの解釈をまとめ直さないとダメだったり、技術書だったら実際にコードを書いたりそのソフトウェアを動かしてみないといけなかったり...それぞれ人によって集中するポイントが違っているので決定的な方法は無いけど、いずれにしても突然何かが分かることは無いので、それぞの方法や、時間のかけ方でやっていくしかないんだなって思った。

その他にも静かな場所じゃないとダメ、逆にカフェくらいのノイズが無いとダメ、音楽無いとダメとか...人それぞれ条件が有って、面白い。

WEB+DB PRESS総集編[Vol.1~120]

わずか2970円で過去のWEB+DB Pressが120冊揃うの、マジで便利なので、とりあえず買った方がいいですよ。

書き下ろしの「進化するプログラミング言語の魅力」というコラムも、良かったです。

『詳説データベース』は、2021年夏の課題図書

まさに2021年夏の課題図書といえる『詳説データベース』を読みました。

昔からOSやコンパイラなど、基本的なソフトウェアの構造や、技術的な課題とその解決方法を解説した技術書はたくさん有りましたが、本書は「現代的な」分散データベースの内部構造で必要なデータ構造や、分散処理における障害の可能性、検知、それらへの対応方法について詳細に、広範囲に解説されている点で今までになかった内容となっています。

ただこの本を読む順番は人によって大きく異なってくると思った方がいいかと。

扱っているテーマの一つ一つがかなりディープなので、読む人の知識レベルや興味によって大きく変わり、必ずしも先頭から最後までを一気に読むには向いていない、というか、それができる人はそもそもこの本を読む必要が無い人なのでは?と言えるくらい「深い」です。

個人的には、8章と9章を最初にじっくり読むのが一番入りやすかったですね。

というわけで、この本を読むだけでもいいし、挙げられている参考文献も一緒に読むのもいいし、みんなで読書会で盛り上がってもいいし、解説されているデータベースを実際に動かすのもいいし、実際に実装してみるのもいいし...と人それぞれ楽しみ方がある本だなと思いますので、データベースの内部構造に興味が無い人もぜひ読んでみるといいと思いました。

「Anker Nano II 65W」を購入 - 最小の65W対応のUSB PD充電器

発売前に予約していた「Anker Nano II 65W」が届きました。普段Appleの純正61Wの充電器を持ち歩いていて、それ一つでPCもタブレットスマホもカバーしていましたが、さすがに大きさがちょっと不満でした。

「Anker Nano II 65W」は、Ankerの新しいUSB PDの充電器シリーズ。

AnkerのUSB PD充電器、あまりに種類が多いし、同時期に似たような機種がリリースされているので分かりづらいけど、Nano IIシリーズが出て「とりあえず自分の機器のスペックに合わせて買っておけ」って言えるようになったかも。

65W版の出力は以下の通り、スマホからタブレット、PCまでこの小ささでカバーしてくれます。

5.0V=3.0A / 9.0V=3.0A / 15.0V=3.0A / 20.0V=3.25A (最大 65W)

ちなみに、使っているとそれなりに発熱はするので、設置場所は気をつけた方が良いと思います。

このサイズなら、持ち運ぶ充電器を切り替えることができそうです。

ちなみに、7/23現在、65W版は売り切れですが、45W版と30W版は在庫が有ります。

とりあえず、2021年7月現在で、USB PD充電器を選ぶ時に迷ったらこれを買っておけば良さそうです。


相変わらずUSB PD、充電器の出力側はスペックがそれなりに書かれているのに、特にPC側はどの入力に対応しているのか分からない機種が多いのは変わらないですね...手元のDellのPC、今年のモデルでもどれが充足しているのかさっぱり分かりません。低い出力の充電器に繋ぐと「低出力」ってだけ教えてくれるんですけどね...

あと、USB Type-Cケーブルは相変わらず混沌としているのでThunderbolt3ケーブルか、Thunderbolt4ケーブルを買っておくのがおすすめなのは変わらないですね...

以下の記事も参考にしてみてください。

blog.magnolia.tech

blog.magnolia.tech

Scalaの識別子(クラス名、メソッド名、変数名)に使える文字・使えない文字

Scalaでは、クラス名、メソッド名、変数名などの「識別子」に漢字・ひらがな・カタカナが使えます。

scala> val 変数 = 42
val 変数: Int = 42

scala> def 引数を倍にするメソッド(引数: Int): Int = 引数 * 2
def 引数を倍にするメソッド(引数: Int): Int

scala> val 答え = 引数を倍にするメソッド(変数)
val 答え: Int = 84

でも意外と使えない文字が有ります。

scala> val 質問・回答 = "しつもん・かいとう"
1 |val 質問・回答 = "しつもん・かいとう"
  |      ^
  |      illegal character '\u30fb'
1 |val 質問・回答 = "しつもん・かいとう"
  |                       ^
  |                       expression expected but eof found

scala> val 𠮷野家 = "よしのや"
1 |val 𠮷野家 = "よしのや"
  |    ^
  |    illegal character '\ud842'
1 |val 𠮷野家 = "よしのや"
  |     ^
  |     illegal character '\udfb7'
1 |val 𠮷野家 = "よしのや"
  |                 ^
  |                 '=' expected, but eof found

1つ目は、"・(中黒)"が使われています。

2つ目は、”𠮷野家"の1文字目が"吉"ではなく"𠮷"になっています(看板の通りですね)。

識別子に使える文字は?

Scalaコンパイラは、識別子に使える文字を、JavaCharacter.isUnicodeIdentifierStartと、Character.isUnicodeIdentifierPartを使って判定しています。

文字通りStartが1文字目を判定し、Partが2文字目以降を判定するのに使われます。

ドキュメントから少し引用してみましょう。

Character.isUnicodeIdentifierStart

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Character.html#isUnicodeIdentifierStart(char)

  • isLetter(codePoint) returns true
  • getType(codePoint) returns LETTER_NUMBER. Note: This method cannot handle supplementary characters. To support all Unicode characters, including supplementary characters, use the isUnicodeIdentifierStart(int) method.

isLetterJavaのCharacterクラスが提供するメソッドで、以下の文字が対象となります。

  • UPPERCASE_LETTER
  • LOWERCASE_LETTER
  • TITLECASE_LETTER
  • MODIFIER_LETTER
  • OTHER_LETTER

つまり、UnicodeのCategoryにおける6種類の属性を持つものが利用できることが分かります。漢字やひらがな、カタカナ等はほとんど対応しますね。

また、Scalaでは、記号のみから成る識別子を特別扱いしていて、Character.isUnicodeIdentifierStartの判定とは別に特定のASCII記号と、Unicodeの「Symbol, Other」「Symbol, Math」に該当する記号のみから成る識別子を許可しています。

例えば、以下の変数名は有効です(絵文字は「Symbol, Other」に該当する)。

scala> val ☃️ = "ゆきだるま"
val ☃: String = ゆきだるま

そして、最後に大事なことが書かれていますね。そう、Character.isUnicodeIdentifierStartにはcharを引数に取るものと、intを引数に取るものの2種類があり、charを引数に取る方ではUnicodesupplementary charactersがサポートされていないのです。

Character.isUnicodeIdentifierPart

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Character.html#isUnicodeIdentifierPart(char)

次に、Character.isUnicodeIdentifierPartを見てみましょう。

  • it is a letter
  • it is a connecting punctuation character (such as '_')
  • it is a digit
  • it is a numeric letter (such as a Roman numeral character)
  • it is a combining mark
  • it is a non-spacing mark
  • isIdentifierIgnorable returns true for this character. Note: This method cannot handle supplementary characters. To support all Unicode characters, including supplementary characters, use the isUnicodeIdentifierPart(int) method.

少し使える文字が増えました。数字やアンダースコアや、が増えているのがわかるかと思います。

ただ、表記方法が違うので分かりづらいですが、Character.isUnicodeIdentifierStartで使える文字は全て使えます。

そして、やはり引数にcharを取る方では、supplementary charactersがサポートされていません。

なぜ使えないか?

中点(なかぐろ)

https://www.compart.com/en/unicode/U+30FB

こちらを参照すると分かりますが、Unicodeのカテゴリが「Other Punctuation」になっているためです。

𠮷野家

𠮷野家の「𠮷」は「Supplementary Ideographic Plane」に属しています。

https://www.compart.com/en/unicode/U+20BB7

なので、現在の実装では正しく判定できません。

Scalaコンパイラサロゲートペア文字を正しく認識し、BMP(Basic Multilingual Plane)以外の文字も識別子として扱えるようになればいいのですが。

同様の理由で、Unicodeの絵文字群のうち、かなりの文字が「supplementary characters」なので、識別子として使えません。先程の☃️は使えましたが、顔文字はダメですね。

scala> val  😂 = "泣いて笑って"
1 |val  😂 = "泣いて笑って"
  |     ^
  |     illegal character '\ud83d'
1 |val  😂 = "泣いて笑って"
  |      ^
  |      illegal character '\ude02'
1 |val  😂 = "泣いて笑って"
  |                 ^
  |                 '=' expected, but eof found

というタイミングで、Scala2に「supplementary characters」を使えるようにするPRが作られました。

Accept supplementary characters by som-snytt · Pull Request #9687 · scala/scala · GitHub

Scala3にもポートされることが期待されています。

早く使えるようになるといいですね!

文字コードへの理解

絵文字の普及でBMP以外の面のサポートがだいぶ進みましたが、まだまだ意外なところでサポートが進んでいないことがわかりますね。

BMPとか、supplementary charactersについて知りたい方は、下記の本がおすすめです。全部書いてあります。