AQUOS sense8とProCaおよびダイソー保護ガラス

私は当初このブログをKnowHow系とするつもりだったのに…は兎も角また場末レビュー。
脱695で話題のsense8を弄くる機会を得た!が、取り上げるのはアクセサリーである

いつの間にやら100円均一ショップでも、iPhone以外の保護ガラスを売り出していて
Pixel、sense、Galaxy各1種くらいなものの、8用ガラスが7/6でも使えるならば逆も然り
取り合えず画面保護したいが、1000円前後から悩む間にコレ付けるかと、まず装着前 背景は真っ白な印刷用紙なので、写り自体が微妙ではあるのだが、IGZO液晶と違い
ナチュラルより標準が似合う感じだ。(日没後の室内で輝度50%、色温度標準)
肉眼でもナチュラルは気持ち黄味が強く色褪せを感じる

取り出したるはダイソーの耐衝撃 画面保護ガラス BLUE LIGHT REDUCING

ダイソー製品はクリーナー付属が多く、埃の舞いにくい風呂などでソコソコ綺麗に貼れる 同シリーズ含め、ブルーライトカットの例に漏れず太陽光を青く反射するのは分かっていたが… 左の縁が白く光り、装着後を示している。直射日光下(右)でこれだけ青みがかるガラスも
日没後の室内で見る限りでは、間に合わせの消耗品として及第点と言えよう

サイズは黒ベゼルよりも上下左右が1mmずつくらい小さい程度。
画面がフラットなので同サイズから63mm×141mmまでの商品なら代用できそうだが
このサイズ帯はiPhone11用が多く切欠の形状が合わず、15用でも縦が不足気味となる

思わぬ所に落とし穴

一見するとフロントカメラ部はパンチホールの保護ガラスと思いきや
貼り付けてから気付いたところ、カメラも保護されている。
では丸く見えるのはなんだ?とシリコン側を封じていたシートを見ると確かに穴 カメラ部はシリコンが無いのかしらんが、これでは吸着側に皮脂が付きかねんよ!

ケースも手配が済んでいないゆえに、機会があればまた次回
そういえばKPH40は予定調和のごとく伸縮部のプラがバラバラになったね
2mm未満のネジにナットでも咬まそうか?

後日、装着後に直射日光を当ててみた

室内で輝度100%アウトドアビューだが、凄まじい青さ。右は厚いカーテンを閉めた状態だ
しかし屋外では陰に入ってもダメ、晴れていれば日中は青くなるだろう。車内でも怪しい
なお上下に黒い帯が出ているが、走査線っぽいもので、ガラスや画面の異常・影ではない

もう一つの落とし穴?

着用してしばらくしてから気づいたのだが、どうも吸着力が弱いようだ
というのも剥がれてきたりはしないものの、ふと見るとズレている事がある
両の親指で軽く押して動かすと、指の動きには付いてこないが僅かにズレる
貼り直さずに微調整が出来ると思えば、絶妙な塩梅と言えなくもないが…
ブルーライトカットがシリコン部らしき影響なのか、意図的に弱めなのか?

それはそれとして、とりあえずケースも

兎にも角にもレンズフィルムなしでも気軽に置けることを考え、分厚いケースProCaを用意
背面パネルを付けなくとも既にカメラより厚いですが、この状態は外縁部にバリ感が出ます
本体はTPUらしいですが、Spigenリキッド・エアーよりも硬質でスキーブーツを思わせます

パネルを付けスマホを収めると、ケースが内側に縮まず、パネルが固定されるのですが
ケース本体が硬質な事も相まって、一度付けるとスマホを取り外す場合には難儀します

指紋センサーを兼ねた電源ボタンへのアクセスは問題なく、音量ボタンの裏にも突起があり
個別のボタン操作に特段の難は無いと思いますが、音量上下同時押しは固めかもしれません

またパネル表面は白物家電が如くツルツルであり、黒は指紋が目立ちそう&白も殺風景です
ingrem版にはキャラクターパネルも有るので、柄物が良ければ…でも剥げるか?どうかな?

ただ…「耐衝撃」だの「超! 保護」を謳っても重いです。スマホ本体と合計で220g程度になり
画面から落とした場合は、自重により被害が拡大するんじゃないか?という懸念を抱きました

KOSS KPH40 Utility (Rhythm Beige)

ネタは色々あると書いておきながら、この体たらく。そう、歳を取ると思い立っても―
という訳で今回はKOSS KPH40のレビュー…というより紹介、お耳に自信は無いから話半分で なぜコレかというと、長年愛用していたゼンハイザーPMX95が断線したゆえに

PMX95開封直後どうか忘れましたけど、側圧が皆無かつ両耳にジャストフィットでした。
コード内に補強糸も同封されており、引っ張りには強かったものの、外装が極薄メッシュ
その上から早晩ボロボロになるクリアチューブを被せた構造で、屈曲に弱かったのです。
水平に近い状態で浮かすか、垂直かつ低位置にしないと、1.2mのコードが折れ気味に垂れ
本体根元のブッシュがあまり役立たない事もあって、生涯を終えました

とりあえず先代PMX90(分解清掃中にハンダ部が断線)を引っ張り出し、小手で以て応急。
今聴くと低音控えめだが、若干シャリ感?フレームがやわく、フィット感もPMX95に及ばず

しかしネックバンドの絶滅傾向は認識していたものの、オンイヤー自体も同じ道を辿るのか?
Porta ProSporta Proが有名だけど、このタイプのバンドは伸ばすほど回り込んで側圧が増す。
ワタシ頭蓋でかいんですよ、眼鏡で言うとW-ACTIONくらいのレンズ+ブリッジが130mm近く
かつテンプルが外側に撓らないと入らないくらい。大抵の眼鏡は、まずこめかみで詰まる

以前から跡継ぎを探すもののKSC75は耳掛けが弾け飛ぶ運命、 KTXPro1KPH30iもHmm…
だが折しも軽量シンプル!フラット!出てるやんけ、でも国内代理店ない⇒Amazon.com!! 2週間掛かるよ、とか云われつつ1週間で到着。当時の為替で約5400円+通常送料1700円ほど。
Amazon.co.jp並行輸入らしき物は発注時から8000円越えでしたし、ステルスブラックのみ
到着後に見たらリズムベージュも出現していたけれど、倍近い値段設定で吹き出しました。
モバイル番号とクレジットかデビットが有れば、届け先はローマ字で作法に従うだけです

そんなこんなで漸く本題です(前置きが長い)

パッケージの潰れは梱包されず包装配送ゆえか(販売KOSS、発送Amazon.com、国内はヤマト)
ベージュというよりカーキ?この部分だけがステンレス鋼のようで、両横で上下を独立調整
リズムベージュはコードの接続部も色が別れており、左右やパーツが分かり易いです。
黒い接合部はプラで耐久性が気掛かりですが、ハウジングは上下左右に傾き耳にフィット
適度な側圧と軽さにより、バンドを後ろで装着しても落ちないがコードが頬に当たります。
このフラットケーブルは摘まんだ感じが細いきしめんの様で、収納状態からして既に癖付き
両出しケーブルが25cm程度、付属の4極2.5mm♂⇔3極3.5mm♂は85cm程度で端子は金色
2.5mmジャックはかなり固く、引っ張られた時にここが抜ける事はまず考えられません

音に関しては他のKOSS製品を持ってませんが、国内外でPORTA系と評価が見つかるので
伝統的なKOSSサウンドでしょう、たぶん。パッド構造は高汎用性、ユニットもそっくり?
PMX95の開封直後と似たような、低音がボワボワした篭もり感を覚えたりもしたのですけど
暫くしたら鳴らしておいたら物が馴染んだのか耳が馴染んだのか、まあまあ良い塩梅です

使用環境としてはデスクトップPCにSound Blaster Zを刺してボリューム10(-34.0dB)
SBXプロファイル、イコライザー、全回路OFF!と解りづらいネタを挟みつつASIOで
ロスレス音源(といってもハイレゾではないCD-DAレベル)を中心に流していますが
個人的には低音の主張を少し抑え…と思うもののヴォーカルやヴァイオリンといった
中音の艶やかな伸びも十分に感じられ、送料以外の文句は無いかなといった印象です

ポータブルヘッドフォンだけに、スマホや携帯ゲーム機の方が迫力の上がり代は有るか?
あ、もちろん開放型の上にオンイヤーだから音漏れも外界の音もし放題ですよ(ニッコリ)

あとがき

ちなみにSound Blaster Zなんぞと、サウンドカードを付けているのは音質というより
メーカー製PCかつオンボードサウンドドライバーが割と碌でもなかったからです。
当時のCreativeも五十歩百歩だって?ともかく現代のオンボードDACへ不満がなければ
一般的にサウンドカードは不要でしょう、下手に載せてもCPUクロック変動でノイズ等。 Beamformingマイク付属で録音機能は音声向けが充実し、そちらの方が重宝したことも?

話は戻るんだけどKPH40の紹介としながらも、マイベストフ(ェイバリ)ィットはPMX95
やはりバンドは頭上より頸椎近くが望ましい、本体根元の断線をMMCX化という手もあるが…
廃番してるから他人にお奨めできないし、手間なので着脱式の後継モデルを出して欲しい所
時代の流れからすると、もし出てもBluetoothベースの有線兼用とかで割高になってしまうか?

Python matchステートメントとバイトコード

Google検索が劣化し、次の検索結果を表示していますを抑制するnfpr=1
含まれないを無効化するっぽいnirf=1を駆使してもワード分割が酷くなり
Googleまでもがクォートを案内するが、完全一致は複数形やスペースなど表現の揺らぎさえ消える
結果をまとめサイトが跋扈する昨今、別コミュニティでノウハウを残したい

という事でネタは色々あるのだけど、久しぶりにPythonコードを書いていて
あー任天堂switchしたいと思いきや、いつの間にか実装されてたので検証

# coding=mbcs
from __future__ import absolute_import, division, print_function
import dis

def pattern(var1):
    match var1:
        case 100:
            print("百")
        case 1000:
            print("千")
        case _:
            print("その他")

dis.dis(pattern)

しかし1行目はダメな例として書いた。coding=mbcsは通るがWindows専用で
システムロケール(CP_ACP)を指すため、別環境ではスクリプトと整合性を失う
実行環境に即したファイル読み書きなどを行うときに使うエンコーディング
utf-8と指定すべき所、ダメ文字を抱えていてもcp932が便利な場合も有る

2行目はmatch文を使う以上関係のない、言わずもがな2系で動かすお呪いだが
unicode_literalsは非推奨という点で記述した、代表的にはr"\u"が転ける
RAW文字列リテラルunicodeになると2系はUnicodeエスケープが有効になり
3系はuも付くと忽ち文法エラーになるが、ファイルパス等にbrは宜しくない
またsys.stdoutasciiな場合とかを筆頭に2系はbytesファーストなので
unicode_literalsimportせず、適宜ubを接頭しておくのが良さげ?

バイトコード

閑話休題match文を知るには言語リファレンスを読むのが正攻法ではあるが
実際どういう動きをするかは個人的にバイトコードを調べるのが手っ取り早い

  6           0 LOAD_FAST                0 (var1)     # var1

  7           2 DUP_TOP                               # var1 var1
              4 LOAD_CONST               1 (100)      # var1 var1 100
              6 COMPARE_OP               2 (==)       # var1 var1==100
              8 POP_JUMP_IF_FALSE       12 (to 24)    # var1
             10 POP_TOP

  8          12 LOAD_GLOBAL              0 (print)    # print
             14 LOAD_CONST               2 ('百')     # print '百'
             16 CALL_FUNCTION            1            # None
             18 POP_TOP
             20 LOAD_CONST               0 (None)     # None
             22 RETURN_VALUE

  9     >>   24 LOAD_CONST               3 (1000)     # var1 1000
             26 COMPARE_OP               2 (==)       # var1==1000
             28 POP_JUMP_IF_FALSE       21 (to 42)

 10          30 LOAD_GLOBAL              0 (print)    # print
             32 LOAD_CONST               4 ('千')     # print '千'
             34 CALL_FUNCTION            1            # None
             36 POP_TOP
             38 LOAD_CONST               0 (None)     # None
             40 RETURN_VALUE

 11     >>   42 NOP

 12          44 LOAD_GLOBAL              0 (print)    # print
             46 LOAD_CONST               5 ('その他') # print 'その他'
             48 CALL_FUNCTION            1            # None
             50 POP_TOP
             52 LOAD_CONST               0 (None)     # None
             54 RETURN_VALUE

コメントは筆者によるスタックの変遷を示す。おわかりいただけるだろうか?
スタックの複製を除けば、if-elif-else文とほとんど変わらないのである

  6           0 LOAD_FAST                0 (var1)
              2 LOAD_CONST               1 (100)
              4 COMPARE_OP               2 (==)
              6 POP_JUMP_IF_FALSE       10 (to 20)

  7           8 LOAD_GLOBAL              0 (print)
             10 LOAD_CONST               2 ('百')
             12 CALL_FUNCTION            1
             14 POP_TOP
             16 LOAD_CONST               0 (None)
             18 RETURN_VALUE

  8     >>   20 LOAD_FAST                0 (var1)
             22 LOAD_CONST               3 (1000)
             24 COMPARE_OP               2 (==)
             26 POP_JUMP_IF_FALSE       20 (to 40)

  9          28 LOAD_GLOBAL              0 (print)
             30 LOAD_CONST               4 ('千')
             32 CALL_FUNCTION            1
             34 POP_TOP
             36 LOAD_CONST               0 (None)
             38 RETURN_VALUE

 11     >>   40 LOAD_GLOBAL              0 (print)
             42 LOAD_CONST               5 ('その他')
             44 CALL_FUNCTION            1
             46 POP_TOP
             48 LOAD_CONST               0 (None)
             50 RETURN_VALUE

LOAD_FASTDUP_TOPに成って得られるパフォーマンスは乏しいだろう
しかしmatch文はswitch文に非ず、構造的パターンマッチであるという
何れにも該当しなかった節がdefaultelseでないのもソレ故とScala

シーケンスパターン

立ち返って言語リファレンスを見やる、そしてサンプルを逆アッセンボー

  6           0 LOAD_CONST               1 ((100, 200))

  7           2 DUP_TOP
              4 MATCH_SEQUENCE
              6 POP_JUMP_IF_FALSE       22 (to 44)
              8 GET_LEN
             10 LOAD_CONST               2 (2)
             12 COMPARE_OP               2 (==)
             14 POP_JUMP_IF_FALSE       22 (to 44)
             16 UNPACK_SEQUENCE          2
             18 LOAD_CONST               3 (100)
             20 COMPARE_OP               2 (==)
             22 POP_JUMP_IF_FALSE       22 (to 44)
             24 LOAD_CONST               4 (300)
             26 COMPARE_OP               2 (==)
             28 POP_JUMP_IF_FALSE       23 (to 46)
             30 POP_TOP

  8          32 LOAD_GLOBAL              0 (print)
             34 LOAD_CONST               5 ('Case 1')
             36 CALL_FUNCTION            1
             38 POP_TOP
             40 LOAD_CONST               0 (None)
             42 RETURN_VALUE

  7     >>   44 POP_TOP

  9     >>   46 DUP_TOP
             48 MATCH_SEQUENCE
             50 POP_JUMP_IF_FALSE       46 (to 92)
             52 GET_LEN
             54 LOAD_CONST               2 (2)
             56 COMPARE_OP               2 (==)
             58 POP_JUMP_IF_FALSE       46 (to 92)
             60 UNPACK_SEQUENCE          2
             62 LOAD_CONST               3 (100)
             64 COMPARE_OP               2 (==)
             66 POP_JUMP_IF_FALSE       46 (to 92)
             68 LOAD_CONST               6 (200)
             70 COMPARE_OP               2 (==)
             72 POP_JUMP_IF_FALSE       47 (to 94)
             74 LOAD_FAST                0 (flag)
             76 POP_JUMP_IF_FALSE       47 (to 94)
             78 POP_TOP

 10          80 LOAD_GLOBAL              0 (print)
             82 LOAD_CONST               7 ('Case 2')
             84 CALL_FUNCTION            1
             86 POP_TOP
             88 LOAD_CONST               0 (None)
             90 RETURN_VALUE

  9     >>   92 POP_TOP

 11     >>   94 MATCH_SEQUENCE
             96 POP_JUMP_IF_FALSE       67 (to 134)
             98 GET_LEN
            100 LOAD_CONST               2 (2)
            102 COMPARE_OP               2 (==)
            104 POP_JUMP_IF_FALSE       67 (to 134)
            106 UNPACK_SEQUENCE          2
            108 LOAD_CONST               3 (100)
            110 COMPARE_OP               2 (==)
            112 POP_JUMP_IF_FALSE       67 (to 134)
            114 STORE_FAST               1 (y) # <- !

 12         116 LOAD_GLOBAL              0 (print)
            118 LOAD_CONST               8 ('Case 3, y: ')
            120 LOAD_FAST                1 (y)
            122 FORMAT_VALUE             0
            124 BUILD_STRING             2
            126 CALL_FUNCTION            1
            128 POP_TOP
            130 LOAD_CONST               0 (None)
            132 RETURN_VALUE

 11     >>  134 POP_TOP

 13         136 NOP

 14         138 LOAD_GLOBAL              0 (print)
            140 LOAD_CONST               9 ('Case 4, I match anything!')
            142 CALL_FUNCTION            1
            144 POP_TOP
            146 LOAD_CONST               0 (None)
            148 RETURN_VALUE

おっと…見慣れない命令MATCH_SEQUENCEの出現だ、がドキュメント曰く

If TOS is an instance of collections.abc.Sequence
and is not an instance of str/bytes/bytearray
(or, more technically: if it has the Py_TPFLAGS_SEQUENCE flag set in its tp_flags),
push True onto the stack. Otherwise, push False.

これは後述する特殊化を含めた判定に過ぎず、それ以降は要素毎の比較だ
とすれば真価の発揮は専用命令があるMATCH_KEYSMATCH_CLASSなのか

しかし今回それは割愛、先の特殊化判定。私は行内容の判別を書いていた
それでmatch文に巧く書き直せないかと思ったのだが…リファレンス曰く

If the subject value is an instance of str, bytes or bytearray the sequence pattern fails.

These classes accept a single positional argument,
and the pattern there is matched against the whole object rather than an attribute.

つまりbytearrayでさえシーケンス扱いには成らず、部分一致も不可
memoryviewやアンパックすれば可能だが、そんな事よりin演算子
位置で決まればスライス、又はstartswith()find()した方が良い
split()で扱える場合でも、行頭判別で特定行のみ処理なら非効率だ
論拠Erlangへの言及はある、バイナリパターンマッチもしたいです
そんな訳で私のユースケースインパクトを与える代物ではなかった

言語リファレンス

とはいえ冗長な記述を推敲できる糖衣構文だ、但し要注意なのが文法
matchに与えるsubject_exprstar_named_expression等とされ
これは式のリストに近しく見えるが、case節へ書くのはpatterns
間違っても式expressionではなく、switchRubywhen節と違う

言語リファレンスのサンプルを逆アセンブルした先の結果も示すとおり
コード中に出てくるcase節のyへはSTORE_FAST、つまり代入している
ここへ書いた変数は参照元ではなく代入先で、capture_patternになる
関数オーバーロードにおける仮引数と考えればシグネチャの様な感じか
参照元value_patternとなるケースは、メンバー参照のみとなっている

またNoneTrueFalseも特殊でliteral_patternに分類されるが
この定数というかシングルトン、キーワードにはis演算子が使われる

match True:
    case 1 as x:
        print(x)
  1           0 LOAD_CONST               0 (True)

  2           2 DUP_TOP
              4 LOAD_CONST               1 (1)
              6 COMPARE_OP               2 (==)
              8 POP_JUMP_IF_FALSE       11 (to 22)
             10 STORE_NAME               0 (x)

  3          12 LOAD_NAME                1 (print)
             14 LOAD_NAME                0 (x)
             16 CALL_FUNCTION            1
             18 POP_TOP
             20 JUMP_FORWARD             1 (to 24)

  2     >>   22 POP_TOP

という場合にはマッチしても、下記だとマッチしないという仕様である

match 1:
    case True as x:
        print(x)
  1           0 LOAD_CONST               0 (1)

  2           2 DUP_TOP
              4 LOAD_CONST               1 (True)
              6 IS_OP                    0
              8 POP_JUMP_IF_FALSE       11 (to 22)
             10 STORE_NAME               0 (x)

  3          12 LOAD_NAME                1 (print)
             14 LOAD_NAME                0 (x)
             16 CALL_FUNCTION            1
             18 POP_TOP
             20 JUMP_FORWARD             1 (to 24)

  2     >>   22 POP_TOP

流れ落ちずbreakもなくor_patternを書くが、これも|演算子ではない
guardの後置ifは内包表記でas_patternwithexceptでお馴染み
wildcard_patterncapture_patternの破棄するバージョンなだけだ

所懐

switchしたいと思って出逢ったmatchだったが、ちょっと複雑だった
Elixirのパターンマッチングも鑑みれば、些かPythonicさに欠けるか?
これを否定する気は無いが、3.10~という新しさは時間が解決しても
Windowsだと7が期限切れとはいえ、3.9以降をインストールできない
api-ms-win-core-path-l1-1-0.dllの関数参照は数個で代替可能…

10へと半ば強制更新したMicrosoftの暴挙は環境均一化に寄与したが
AF_UNIXを実装してもSOCK_DGRAMが欠けるからかPythonは未対応
Python3の肝はやはりasyncioだと思うが、これもかなり制限がある
セイウチ演算子が導入され、7でも動く3.8分水嶺的な魅力があり
徒にmatch文を使うのは躊躇われる。だがエラー改良は素晴らしい!!