aboutsummaryrefslogtreecommitdiffhomepage
path: root/docs/feed.xml
blob: 5fbdb0e754c5975dbd007e6b56fa4d0821f83048 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>REPL: Rest-Eat-Program Loop</title>
    <link>https://blog.nsfisis.dev/</link>
    <description>Recent content on REPL: Rest-Eat-Program Loop</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>ja-JP</language>
    <lastBuildDate>Wed, 31 Mar 2021 01:36:49 +0900</lastBuildDate><atom:link href="https://blog.nsfisis.dev/feed.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>PHP カンファレンス沖縄で出題されたコードゴルフの問題を解いてみた</title>
      <link>https://blog.nsfisis.dev/posts/2022-08-27/php-conference-okinawa-code-golf/</link>
      <pubDate>Sat, 27 Aug 2022 18:55:28 +0900</pubDate>
      
      <guid>https://blog.nsfisis.dev/posts/2022-08-27/php-conference-okinawa-code-golf/</guid>
      <description><![CDATA[ <h1 id="はじめに">はじめに</h1>
<p>本日 <a href="https://phpcon.okinawa.jp/">PHP カンファレンス沖縄 2022</a> が開催された (らしい)。</p>
<p>カンファレンスには参加できなかったものの、懇親会の LT で出題されたコードゴルフの問題が Twitter に流れてきたので、解いてみた。</p>
<p>ツイート: <a href="https://twitter.com/m3m0r7/status/1563397620231712772">https://twitter.com/m3m0r7/status/1563397620231712772</a><br>
スライド: <a href="https://speakerdeck.com/memory1994/php-conference-okinawa-2022-extra?slide=3">https://speakerdeck.com/memory1994/php-conference-okinawa-2022-extra?slide=3</a></p>
<h1 id="解">解</h1>
<p>細かいレギュレーションは不明だったので、勝手に定めた。</p>
<ul>
<li>コマンドライン引数の第1引数で受けとる</li>
<li>結果は標準出力に出す</li>
<li>コンマの直後にはスペースを1つ置く</li>
<li>末尾コンマは禁止</li>
<li>数字でないものは入ってこないものとする</li>
<li>負数は入ってこないものとする</li>
</ul>
<p>書いたものがこちら:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php">[<span style="color:#f92672">&lt;?</span><span style="color:#a6e22e">php</span> $n<span style="color:#f92672">=</span>$argv[<span style="color:#ae81ff">1</span>];<span style="color:#66d9ef">foreach</span>([<span style="color:#ae81ff">1e4</span>,<span style="color:#ae81ff">5e3</span>,<span style="color:#ae81ff">2e3</span>,<span style="color:#ae81ff">1e3</span>,<span style="color:#ae81ff">500</span>,<span style="color:#ae81ff">100</span>,<span style="color:#ae81ff">50</span>,<span style="color:#ae81ff">10</span>,<span style="color:#ae81ff">5</span>,<span style="color:#ae81ff">1</span>]<span style="color:#66d9ef">as</span>$x)<span style="color:#66d9ef">for</span>(;$n<span style="color:#f92672">&gt;=</span>$x;$n<span style="color:#f92672">-=</span>$x)$r[]<span style="color:#f92672">=</span>$x;<span style="color:#66d9ef">echo</span> <span style="color:#a6e22e">implode</span>(<span style="color:#e6db74">&#39;, &#39;</span>,$r<span style="color:#f92672">??</span>[]);<span style="color:#75715e">?&gt;</span><span style="color:#960050;background-color:#1e0010">]
</span></code></pre></div><p>しめて 123 バイトとなった (末尾改行を含めずにカウント)。</p>
<p>こちらは改行とスペースを追加したバージョン:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php">[<span style="color:#f92672">&lt;?</span><span style="color:#a6e22e">php</span>

$n <span style="color:#f92672">=</span> $argv[<span style="color:#ae81ff">1</span>];
<span style="color:#66d9ef">foreach</span> ([<span style="color:#ae81ff">1e4</span>, <span style="color:#ae81ff">5e3</span>, <span style="color:#ae81ff">2e3</span>, <span style="color:#ae81ff">1e3</span>, <span style="color:#ae81ff">500</span>, <span style="color:#ae81ff">100</span>, <span style="color:#ae81ff">50</span>, <span style="color:#ae81ff">10</span>, <span style="color:#ae81ff">5</span>, <span style="color:#ae81ff">1</span>] <span style="color:#66d9ef">as</span> $x)
  <span style="color:#66d9ef">for</span> (; $n <span style="color:#f92672">&gt;=</span> $x; $n <span style="color:#f92672">-=</span> $x)
    $r[] <span style="color:#f92672">=</span> $x;
<span style="color:#66d9ef">echo</span> <span style="color:#a6e22e">implode</span>(<span style="color:#e6db74">&#39;, &#39;</span>, $r <span style="color:#f92672">??</span> []);

<span style="color:#75715e">?&gt;</span><span style="color:#960050;background-color:#1e0010">]
</span></code></pre></div><h1 id="使用したテクニック">使用したテクニック</h1>
<h2 id="指数表記">指数表記</h2>
<p>割と多くの言語のゴルフで使えるテクニック。<code>e</code> を用いた指数表記で、大きな数を短く表す。このコードでは <code>10000</code>、<code>5000</code>、<code>2000</code>、<code>1000</code> を指数表記している。</p>
<h2 id="foreach-や-for-の中身を1つの文に">foreach や for の中身を1つの文に</h2>
<p><code>foreach</code>、<code>for</code>、<code>if</code> などの後ろには、通常 <code>{</code> を続けて複数の文を連ねるが、中身の文を1つにしてしまえば、<code>{</code> と <code>}</code> を省略できる。C言語などでも使える。</p>
<h2 id="r-に初期値を入れない">$r に初期値を入れない</h2>
<p>PHP では、<code>$r[] = ...</code> のような配列の末尾に追加する式を実行したとき、<code>$r</code> が未定義だった場合は <code>$r</code> を勝手に定義して空の配列で初期化してくれる。これを利用すると、<code>$r = [];</code> のような初期化が不要になる。</p>
<p>ただし、プログラムに 0 が渡されるとループを一度も回らないので、<code>$r</code> が未定義になってしまい、<code>implode()</code> に渡すところでエラーになる。それを防ぐために <code>$r ?? []</code> を使っている。</p>
<p>もし 0 が渡されたケースを無視するなら、これが不要になるので 4 バイト縮む。</p>
<h2 id="php-タグの外に文字列を置く">PHP タグの外に文字列を置く</h2>
<p>PHP では、<code>&lt;?php</code> <code>?&gt;</code> で囲われた部分の外側にある文字列は、そのまま出力される。今回のケースでは、先頭と末尾に必ず <code>[</code> と <code>]</code> を出力するので、そのまま書いてやればよい。</p>
<h1 id="おわりに">おわりに</h1>
<p>最後になりましたが、<a href="https://twitter.com/m3m0r7">めもりー</a> さん、楽しい問題をありがとうございました。</p>
]]></description>
    </item>
    
    <item>
      <title>PHPerKaigi 2022</title>
      <link>https://blog.nsfisis.dev/posts/2022-05-01/phperkaigi-2022/</link>
      <pubDate>Sun, 01 May 2022 09:41:39 +0900</pubDate>
      
      <guid>https://blog.nsfisis.dev/posts/2022-05-01/phperkaigi-2022/</guid>
      <description><![CDATA[ <h1 id="はじめに">はじめに</h1>
<p>2022-04-09 から 2022-04-11 にかけて開催された、<a href="https://phperkaigi.jp/2022/">PHPerKaigi 2022</a> に、一般参加者として参加した。
弊社<a href="https://www.dgcircus.com/">デジタルサーカス株式会社</a> はダイヤモンドスポンサーとなっており、スポンサー枠のチケットを使わせていただいた。</p>
<p>昨年のレポートは<a href="/posts/2021-03-30/phperkaigi-2021">こちら</a>。</p>
<h1 id="感想">感想</h1>
<h2 id="厳選おすすめトーク">厳選おすすめトーク</h2>
<p>多くの素晴らしいトークの中から、特におすすめのものを 5つ選んだ。是非聞いてほしい。引用部分は、リンク先プロポーザルから引用している。</p>
<p><a href="https://fortee.jp/phperkaigi-2022/proposal/ef8cf4ed-63fe-42f8-8145-b3e70054458b">予防に勝る防御なし - 堅牢なコードを導く様々な設計のヒント</a></p>
<blockquote>
<p>PHP はバージョンを追う毎に型宣言、例外、表明、列挙型などの機能が大幅に強化され、堅牢なコードを書くための機能が充実してきました。それらの機能はどう使うと効果的なのでしょうか。</p>
<p>本講演では PHP 8.1 をベースにして、誤りを想定してチェックするのではなく、そもそも誤りにくい設計とはどのようなものか、つまり「予防」の観点を軸足に、堅牢なコードを導くための様々な設計のヒントをご紹介します。</p>
</blockquote>
<p><a href="https://fortee.jp/phperkaigi-2022/proposal/db00d49e-0dd6-453f-b54b-f731d112f10e">PHPのエラーを理解して適切なエラーハンドリングを学ぼう</a></p>
<blockquote>
<p>PHPを使ってるとよく遭遇する Fatal error / Parse error / Warning / Notice 理解していますか?<br>
これらのエラー文を理解することで、すぐにエラーの原因に気付き適切に対象できる様になります!<br>
またそれらを理解した上でのエラーハンドリングを学びましょう。</p>
</blockquote>
<p><a href="https://fortee.jp/phperkaigi-2022/proposal/4a7e3ded-9134-4919-955c-ec7bf4491c0d">エラー監視とテスト体制への改善作戦</a></p>
<blockquote>
<p>毎日流れてくるエラーに皆さんはどう向き合ってますか?<br>
エラーを出さない事が一番ですが、完全に塞ぐ事は難しいと考えます。<br>
サービス運用の中で本番環境から発生するエラー(サーバー・クライアントサイド・サードパーティ起因のエラー)への監視体制と、<br>
エラー・バグ防御のためチームで行っているテストコード文化づくりの話をします。</p>
</blockquote>
<p><a href="https://fortee.jp/phperkaigi-2022/proposal/6f47daf8-c78f-4fb1-9b99-e9656e6fe7f7">ISUCON11のPHP実装は、何を考え、どのようにして作られていたのか</a></p>
<blockquote>
<p>昨年開催されたISUCON11にて問題(参考実装)のPHPへの移植を担当させていただきました。</p>
<p>最終的なソースコードこそシンプルなWebアプリケーションではありますが、その裏には<br>
・「(私の思う)良い設計」を実現するための意思決定<br>
・「ISUCONの問題」という位置付けに由来する取捨選択<br>
・移植中に遭遇したトラブルとその解決策<br>
といった文脈や葛藤が存在しています。</p>
<p>本発表はそれらを共有することで<br>
・PHPアプリケーションの設計、実装事例として役立ててもらう<br>
・ISUCONの言語移植に興味を持ってもらう<br>
・ISUCON問題移植の「実装や設計の練習をする教材」としての可能性を知ってもらう<br>
ことを目的とします。</p>
</blockquote>
<p><a href="https://fortee.jp/phperkaigi-2022/proposal/5a260e4e-542d-4d82-849d-ef3d6cb7c854">チームの仕事はまわっていたけど、メンバーはそれぞれモヤモヤを抱えていた話──40名の大規模開発チームで1on1ログを公開してみた</a></p>
<blockquote>
<p>サイボウズの大企業向けグループウェアのGaroon(ガルーン)は、PHPで開発されている20年目の製品です。ガルーン開発チームは日本で40名、ベトナムで50名の計90名ほどのチームになっています。また、コロナ禍でフルリモートでの活動がこの2年ほど継続してきました。</p>
<p>フルリモートになっても仕事はまわっており、継続的にリリースはしていましたが、一方でお互いの考えていることや感じている問題意識が見えづらくなり、モヤモヤを抱えているメンバーが増えていました。</p>
<p>このセッションでは、そういう状況で私がチーム外からジョインし、聴き役に徹しながら見える化することで状況を改善していった取り組みを紹介します。同じように大きなチームやリモートワークで難しさを感じている人に、難しさの原因への気づきや取り組みへのヒントがあれば幸いです。</p>
</blockquote>
<h2 id="トークン問題の作成">トークン問題の作成</h2>
<p>今回は、PHPer チャレンジ用に弊社のトークン問題を 3題作成した。こちらについては<a href="/posts/2022-04-09/phperkaigi-2022-tokens">別途記事にしている</a>ので、そちらを参照されたい。</p>
<h2 id="phper-チャレンジ">PHPer チャレンジ</h2>
<p><a href="https://fortee.jp/phperkaigi-2022/challenge">1位</a>になった。<br>
また、賞品として <a href="https://www.amazon.co.jp/dp/B08MQNJC9Z">Echo Show 15</a> をいただいた。</p>
<h2 id="カンファレンス全体への感想">カンファレンス全体への感想</h2>
<p><a href="/posts/2021-03-30/phperkaigi-2021">去年の参加レポ</a> では、こんなことを書いた。</p>
<blockquote>
<p>1つ個人的な反省点としては、(中略) Discord しかりアンカンファレンスしかり「このイベントのこの瞬間にしかないコンテンツ」に触れずに、後から見返せる発表やスライドに注力してしまった、ということだ。発表の詳細な見直しはあとからできるのだから、今しかできないことを考えるべきだった。<br>
まあ初カンファレンスだし、とお茶を濁しておこう。</p>
</blockquote>
<p>この反省を踏まえ、今年は積極的にほかの場 (公式の Discord サーバや、アンカンファレンス) にも参加した。<br>
これにより、参加体験の質がはるかに向上した。特に Discord に関しては、登壇者ご本人による補足や、質問への回答などがおこなわれる (ことが多い) ため、特別な理由のない限り、発言はしないまでも参加はしておいたほうが良いと思われる。</p>
<p>なお、アンカンファレンスについては、1日目の終わりに<a href="https://fortee.jp/phperkaigi-2022/unconference/view/d332797a-8921-4706-a7e2-ee72640c9b5e">トークン問題の解説放送</a>もおこなった。</p>
<p>また、今年はオフラインとオンラインのハイブリッド開催であったが、去年の全オンラインと比べて、オンライン参加の体験が落ちていなかったのは、特筆すべきであろう。
今年は 3回目のワクチン接種が間に合わなかったこともあり現地参加は見送ったのだが、来年は是非オフラインで参加したい。</p>
<h1 id="そして来年へ">そして来年へ……?</h1>
<p>PHPerKaigi 2023 があるかどうか存じ上げないが、あるとすれば、次の 4つを目標としたい。</p>
<ul>
<li>プロポーザルを出す</li>
<li>PHPer チャレンジのトークン問題を 5題作成する</li>
<li>現地に行く</li>
<li>PHPer チャレンジで圧勝する</li>
</ul>
<hr>
<p>最後になりましたが、PHPerKaigi のスタッフ、スポンサー、スピーカーのみなさん、素敵な時間をありがとうございました。</p>
<p>ではまた来年。</p>
]]></description>
    </item>
    
    <item>
      <title>term-banner: ターミナルにバナーを表示するツールを書いた</title>
      <link>https://blog.nsfisis.dev/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal/</link>
      <pubDate>Sun, 24 Apr 2022 13:22:52 +0900</pubDate>
      
      <guid>https://blog.nsfisis.dev/posts/2022-04-24/term-banner-write-tool-showing-banner-in-terminal/</guid>
      <description><![CDATA[ <h1 id="はじめに">はじめに</h1>
<p>こんなものを作った。</p>
<pre tabindex="0"><code>$ term-banner 'Hello, World!' 'こんにちは、' '世界!'
</code></pre><p><img src="https://raw.githubusercontent.com/nsfisis/term-banner/main/screenshot.png" alt="term-banner のスクリーンショット"></p>
<p>コマンドライン引数として渡した文字列をターミナルに大きく表示する。</p>
<p>リポジトリはこちら: <a href="https://github.com/nsfisis/term-banner">https://github.com/nsfisis/term-banner</a></p>
<h1 id="motivation">Motivation</h1>
<p>以前、<a href="https://github.com/nsfisis/big-clock-mode">big-clock-mode</a> という似たようなプログラムを書いた。
これは tmux の <code>:clock-mode</code> コマンドに着想を得たもので、<code>:clock-mode</code> よりも大きく現在時刻を表示する。</p>
<p><code>big-clock-mode</code> を開発したのは、次のようなシチュエーションで使うためである。
弊社では現在リモートワークが基本だが、web 会議などで画面共有しているときに、休憩を挟んで特定の時刻から再開する、ということがある。
こういったケースで、画面上に現在の時刻を大きめに表示しておくと、モニタから離れても遠くから時刻がわかるので便利である。</p>
<p>それこそタイマアプリか何かを使えばいいのだが、ターミナルに棲むいきものとしては、住処から離れたくないわけだ。</p>
<p>しばらく便利に使っていたのだが、ひとつ不満点が出てきた。それは、再開する時刻がいつだったかを覚えておかなければならないということだ。
どこかにメモしておいてもいいが、せっかくなら現在時刻とともに表示させておきたい。</p>
<p>そんなわけで、「任意の文字列をターミナルに表示する」プログラムを書く運びとなった。
まあ、作らなくても探せばあると思うが、作りたいものは作りたいので知ったことではない。</p>
<h1 id="プログラム">プログラム</h1>
<p>全体の流れは次のようになっている。</p>
<ol>
<li>フォントファイルを読み込む</li>
<li>コマンドライン引数を Shift-JIS に変換する (フォントが Shift-JIS 基準で並んでいるため)</li>
<li>1文字ずつレンダリングしていく</li>
</ol>
<p><code>big-clock-mode</code> が Go 製なので、今回も Go で書いた。
PNG が標準ライブラリにあったり、Shift-JIS のエンコーディングが準標準ライブラリにあったりしたのは助かった。</p>
<p>フォントファイルは <code>go:embed</code> で実行ファイルに埋め込んでいるので、ビルド後はワンバイナリで動く。
仕事ではスクリプト言語ばかり書いているが、やはりコンパイル言語はいい。</p>
<h1 id="フォント">フォント</h1>
<p>フリーの 8x8 ビットマップフォントである、<a href="https://littlelimit.net/misaki.htm">美咲フォント 2021-05-05a 版</a> を使わせていただいた。</p>
<p>はじめは自分でポチポチ打っていたのだが、「き」くらいまでやって挫折した。
同じく 8x8 で作っていたのだが、平仮名でさえも、この小さなキャンバスにはとても収められない。</p>
<p>美咲フォントは、平仮名・片仮名に留まらず、JIS 第一・第二水準の漢字までサポートしている。
第二水準ともなると一生お目にかかることのない字の方が多いくらいだが、これをこの大きさで書くというのは、もはや芸術の域である。</p>
<p>さらに言うと、実のところ美咲フォントは実サイズ 7x7 で作られており、余白が設けられている。
これは、単純にそのまま並べても字間・行間を確保できるようにという配慮である。
おかげでコーディングまで楽になった。</p>
<p>ゴシック体と明朝体があったが、私の好みで明朝体の方にした。
ただ、ゴシック体の方が見やすい気がするので、フォントを選べるように後ほど拡張するかもしれない。</p>
<p>2022-04-27 追記: <code>-f</code> オプションで選べるようにした。</p>
<h1 id="おわりに">おわりに</h1>
<p>あなたもターミナルに住んでみませんか?</p>
]]></description>
    </item>
    
    <item>
      <title>PHPerKaigi 2022 トークン問題の解説</title>
      <link>https://blog.nsfisis.dev/posts/2022-04-09/phperkaigi-2022-tokens/</link>
      <pubDate>Sat, 09 Apr 2022 21:50:19 +0900</pubDate>
      
      <guid>https://blog.nsfisis.dev/posts/2022-04-09/phperkaigi-2022-tokens/</guid>
      <description><![CDATA[ <h1 id="はじめに">はじめに</h1>
<p>本日開始された <a href="https://phperkaigi.jp/2022/">PHPerKaigi 2022</a> の PHPer チャレンジにおいて、弊社 <a href="https://www.dgcircus.com/">デジタルサーカス株式会社</a> の問題を 3問作成した。この記事では、これらの問題の解説をおこなう。</p>
<p>リポジトリはこちら: <a href="https://github.com/nsfisis/PHPerKaigi2022-tokens">https://github.com/nsfisis/PHPerKaigi2022-tokens</a></p>
<h1 id="第1問-brainf_ckphp">第1問 brainf_ck.php</h1>
<p>ソースコードはこちら。実行には PHP 8.1 以上が必要なので注意。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php"><span style="color:#f92672">&lt;?</span><span style="color:#a6e22e">php</span>

<span style="color:#66d9ef">declare</span>(<span style="color:#a6e22e">strict_types</span><span style="color:#f92672">=</span><span style="color:#ae81ff">0</span><span style="color:#a6e22e">O1</span>);

<span style="color:#66d9ef">namespace</span> <span style="color:#a6e22e">Dgcircus\PHPerKaigi\Y2022</span>;

<span style="color:#e6db74">/**
</span><span style="color:#e6db74"> * @todo
</span><span style="color:#e6db74"> * Run this program to acquire a PHPer token.
</span><span style="color:#e6db74"> */</span>

<span style="color:#a6e22e">https</span><span style="color:#f92672">://</span><span style="color:#a6e22e">creativecommons</span><span style="color:#f92672">.</span><span style="color:#a6e22e">org</span><span style="color:#f92672">/</span><span style="color:#a6e22e">publicdomain</span><span style="color:#f92672">/</span><span style="color:#a6e22e">zero</span><span style="color:#f92672">/</span><span style="color:#ae81ff">1.0</span><span style="color:#f92672">/</span>

<span style="color:#a6e22e">\error_reporting</span>(<span style="color:#f92672">~+!</span><span style="color:#e6db74">&#39;We are hiring!&#39;</span>);

$z <span style="color:#f92672">=</span> <span style="color:#a6e22e">fn</span>($f) <span style="color:#f92672">=&gt;</span> (<span style="color:#a6e22e">fn</span>($x) <span style="color:#f92672">=&gt;</span> $f(<span style="color:#a6e22e">fn</span>(<span style="color:#f92672">...</span>$xs) <span style="color:#f92672">=&gt;</span> $x($x)(<span style="color:#f92672">...</span>$xs)))(<span style="color:#a6e22e">fn</span>($x) <span style="color:#f92672">=&gt;</span> $f(<span style="color:#a6e22e">fn</span>(<span style="color:#f92672">...</span>$xs) <span style="color:#f92672">=&gt;</span> $x($x)(<span style="color:#f92672">...</span>$xs)));
$id <span style="color:#f92672">=</span> <span style="color:#a6e22e">\spl_object_id</span>(<span style="color:#f92672">...</span>);
$put <span style="color:#f92672">=</span> <span style="color:#a6e22e">fn</span>($c) <span style="color:#f92672">=&gt;</span> <span style="color:#a6e22e">\printf</span>(<span style="color:#e6db74">&#39;%c&#39;</span>, $c);
$mm <span style="color:#f92672">=</span> <span style="color:#a6e22e">fn</span>($p, $n) <span style="color:#f92672">=&gt;</span> <span style="color:#66d9ef">new</span> <span style="color:#a6e22e">\ArrayObject</span>(<span style="color:#a6e22e">\array_fill</span>(<span style="color:#f92672">+!!</span>[], $n, $p));

$👉 <span style="color:#f92672">=</span> <span style="color:#a6e22e">fn</span>($m, $p, $b, $e, $mp, $pc) <span style="color:#f92672">=&gt;</span> [<span style="color:#f92672">++</span>$mp, <span style="color:#f92672">++</span>$pc];
$👈 <span style="color:#f92672">=</span> <span style="color:#a6e22e">fn</span>($m, $p, $b, $e, $mp, $pc) <span style="color:#f92672">=&gt;</span> [<span style="color:#f92672">--</span>$mp, <span style="color:#f92672">++</span>$pc];
$👍 <span style="color:#f92672">=</span> <span style="color:#a6e22e">fn</span>($m, $p, $b, $e, $mp, $pc) <span style="color:#f92672">=&gt;</span> [$mp, <span style="color:#f92672">++</span>$pc, <span style="color:#f92672">++</span>$m[$mp]];
$👎 <span style="color:#f92672">=</span> <span style="color:#a6e22e">fn</span>($m, $p, $b, $e, $mp, $pc) <span style="color:#f92672">=&gt;</span> [$mp, <span style="color:#f92672">++</span>$pc, <span style="color:#f92672">--</span>$m[$mp]];
$📝 <span style="color:#f92672">=</span> <span style="color:#a6e22e">fn</span>($m, $p, $b, $e, $mp, $pc) <span style="color:#f92672">=&gt;</span> [$mp, <span style="color:#f92672">++</span>$pc, $put($m[$mp])];
$🤡 <span style="color:#f92672">=</span> <span style="color:#a6e22e">fn</span>($m, $p, $b, $e, $mp, $pc) <span style="color:#f92672">=&gt;</span> <span style="color:#a6e22e">match</span> ($m[$mp]) {
    <span style="color:#f92672">+!!</span>[] <span style="color:#f92672">=&gt;</span> [$mp, $z(<span style="color:#a6e22e">fn</span>($loop) <span style="color:#f92672">=&gt;</span> <span style="color:#a6e22e">fn</span>($pc, $n) <span style="color:#f92672">=&gt;</span> <span style="color:#a6e22e">match</span> ($id($p[$pc])) {
      $b <span style="color:#f92672">=&gt;</span> $loop(<span style="color:#f92672">++</span>$pc, <span style="color:#f92672">++</span>$n),
      $e <span style="color:#f92672">=&gt;</span> $n <span style="color:#f92672">===</span> <span style="color:#f92672">+!!</span>[] <span style="color:#f92672">?</span> <span style="color:#f92672">++</span>$pc <span style="color:#f92672">:</span> $loop(<span style="color:#f92672">++</span>$pc, <span style="color:#f92672">--</span>$n),
      <span style="color:#66d9ef">default</span> <span style="color:#f92672">=&gt;</span> $loop(<span style="color:#f92672">++</span>$pc, $n),
    })($pc, <span style="color:#f92672">-!</span>[])],
    <span style="color:#66d9ef">default</span> <span style="color:#f92672">=&gt;</span> [$mp, <span style="color:#f92672">++</span>$pc],
};
$🎪 <span style="color:#f92672">=</span> <span style="color:#a6e22e">fn</span>($m, $p, $b, $e, $mp, $pc) <span style="color:#f92672">=&gt;</span> <span style="color:#a6e22e">match</span> ($m[$mp]) {
    <span style="color:#f92672">+!!</span>[] <span style="color:#f92672">=&gt;</span> [$mp, <span style="color:#f92672">++</span>$pc],
    <span style="color:#66d9ef">default</span> <span style="color:#f92672">=&gt;</span> [$mp, $z(<span style="color:#a6e22e">fn</span>($loop) <span style="color:#f92672">=&gt;</span> <span style="color:#a6e22e">fn</span>($pc, $n) <span style="color:#f92672">=&gt;</span> <span style="color:#a6e22e">match</span> ($id($p[$pc])) {
      $e <span style="color:#f92672">=&gt;</span> $loop(<span style="color:#f92672">--</span>$pc, <span style="color:#f92672">++</span>$n),
      $b <span style="color:#f92672">=&gt;</span> $n <span style="color:#f92672">===</span> <span style="color:#f92672">+!!</span>[] <span style="color:#f92672">?</span> $pc<span style="color:#f92672">+!</span>[] <span style="color:#f92672">:</span> $loop(<span style="color:#f92672">--</span>$pc, <span style="color:#f92672">--</span>$n),
      <span style="color:#66d9ef">default</span> <span style="color:#f92672">=&gt;</span> $loop(<span style="color:#f92672">--</span>$pc, $n),
    })($pc, <span style="color:#f92672">-!</span>[])],
};
$🐘 <span style="color:#f92672">=</span> <span style="color:#a6e22e">fn</span>($p) <span style="color:#f92672">=&gt;</span> $z(<span style="color:#a6e22e">fn</span>($loop) <span style="color:#f92672">=&gt;</span> <span style="color:#a6e22e">fn</span>($m, $p, $b, $e, $mp, $pc) <span style="color:#f92672">=&gt;</span>
  <span style="color:#a6e22e">isset</span>($p[$pc]) <span style="color:#f92672">&amp;&amp;</span> $loop($m, $p, $b, $e, <span style="color:#f92672">...</span>($p[$pc]($m, $p, $b, $e, $mp, $pc)))
)($mm(<span style="color:#f92672">+!!</span>[], <span style="color:#f92672">+</span>(<span style="color:#f92672">!</span>[]<span style="color:#f92672">.!</span>[])), $p, $id($🤡), $id($🎪), <span style="color:#f92672">+!!</span>[], <span style="color:#f92672">+!!</span>[]);

$🐘([
  $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍,
  $🤡,
    $👉, $👍, $👍, $👍,
    $👉, $👍, $👍, $👍, $👍, $👍,
    $👉, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍,
    $👉, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍, $👍,
    $👈, $👈, $👈, $👈, $👎,
  $🎪,
  $👉, $👍, $👍, $👍, $👍, $👍, $📝,
  $👎, $👎, $📝,
  $👉, $👎, $👎, $👎, $📝,
  $👉, $👎, $👎, $👎, $📝,
  $👎, $👎, $📝,
  $👎, $📝,
  $👈, $📝,
  $👉, $👉, $👎, $👎, $📝,
  $👍, $👍, $👍, $👍, $👍, $👍, $👍, $📝,
  $👈, $👎, $👎, $👎, $👎, $📝,
  $👈, $📝,
  $👉, $👍, $👍, $📝,
  $👉, $👎, $📝,
  $👈, $📝,
]);
</code></pre></div><p>この問題は、単に適切なバージョンの PHP で動かせばトークンが得られる。</p>
<h2 id="解説">解説</h2>
<h3 id="絵文字">絵文字</h3>
<p>まず目につくのは大量の絵文字だろう。
PHP は識別子に使用できる文字の範囲が広く、絵文字も使うことができる。</p>
<h3 id="プログラム全体">プログラム全体</h3>
<p>Brainf*ck のインタプリタとプログラムになっている。
Brainf*ck とは、難解プログラミング言語のひとつであり、ここで説明するよりも Wikipedia の該当ページを読んだ方がよい。</p>
<p><a href="https://ja.wikipedia.org/wiki/Brainfuck">https://ja.wikipedia.org/wiki/Brainfuck</a></p>
<p>なお、brainf*ck プログラムを普通の書き方で書くと、次のようになる。</p>
<pre tabindex="0"><code>+ + + + + + + + + +
[
  &gt; + + +
  &gt; + + + + +
  &gt; + + + + + + + + + + + +
  &gt; + + + + + + + + + +
  &lt; &lt; &lt; &lt; -
]
&gt; + + + + + .
- - .
&gt; - - - .
&gt; - - - .
- - .
- .
&lt; .
&gt; &gt; - - .
+ + + + + + + .
&lt; - - - - .
&lt; .
&gt; + + .
&gt; - .
&lt; .
</code></pre><p>実行結果はこちら: <a href="https://ideone.com/22VWmb">https://ideone.com/22VWmb</a></p>
<p>それぞれの絵文字で表された関数が、各命令に対応している。</p>
<ul>
<li><code>$👉</code>: <code>&gt;</code></li>
<li><code>$👈</code>: <code>&lt;</code></li>
<li><code>$👍</code>: <code>+</code></li>
<li><code>$👎</code>: <code>-</code></li>
<li><code>$📝</code>: <code>.</code></li>
<li><code>$🤡</code>: <code>[</code></li>
<li><code>$🎪</code>: <code>]</code></li>
</ul>
<p><code>,</code> (入力) に対応する関数はない (このプログラムでは使わないので用意していない)。</p>
<p>なお、<code>$🐘</code> はいわゆる main 関数であり、プログラムの実行部分である。</p>
<h3 id="絵文字の選択">絵文字の選択</h3>
<p>おおよそ意味に合致するよう選んでいるが、<code>$🤡</code> と <code>$🎪</code> は弊社デジタルサーカスにちなんでいる。
また、<code>$🐘</code> は PHP のマスコットの象に由来する。</p>
<h3 id="strict_types">strict_types</h3>
<p><code>declare</code> 文の <code>strict_types</code> に指定できるのは、<code>0</code> か <code>1</code> の数値リテラルだが、
<code>0x0</code> や <code>0b1</code> のような値も受け付ける。
今回は、PHP 8.1 から追加された、<code>0O</code> または <code>0o</code> から始まる八進数リテラルを使った。</p>
<h3 id="url">URL</h3>
<p>ソースコードのライセンスを示したこの部分だが、</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php"><span style="color:#a6e22e">https</span><span style="color:#f92672">://</span><span style="color:#a6e22e">creativecommons</span><span style="color:#f92672">.</span><span style="color:#a6e22e">org</span><span style="color:#f92672">/</span><span style="color:#a6e22e">publicdomain</span><span style="color:#f92672">/</span><span style="color:#a6e22e">zero</span><span style="color:#f92672">/</span><span style="color:#ae81ff">1.0</span><span style="color:#f92672">/</span>
</code></pre></div><p>完全に合法な PHP のコードである。
<code>https:</code> 部分はラベル、<code>//</code> 以降は行コメントになっている。</p>
<h3 id="リテラルなしで数値を生成する">リテラルなしで数値を生成する</h3>
<p>ソースコード中に、ほとんど数値リテラルが書かれていないことにお気づきだろうか。
PHP では、型変換を利用することで任意の整数を作り出すことができる。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php"><span style="color:#a6e22e">assert</span>(<span style="color:#ae81ff">0</span> <span style="color:#f92672">===</span> <span style="color:#f92672">+!!</span>[]);
<span style="color:#a6e22e">assert</span>(<span style="color:#ae81ff">1</span> <span style="color:#f92672">===</span> <span style="color:#f92672">+!</span>[]);
<span style="color:#a6e22e">assert</span>(<span style="color:#ae81ff">2</span> <span style="color:#f92672">===</span> <span style="color:#f92672">!</span>[]<span style="color:#f92672">+!</span>[]);
<span style="color:#a6e22e">assert</span>(<span style="color:#ae81ff">3</span> <span style="color:#f92672">===</span> <span style="color:#f92672">!</span>[]<span style="color:#f92672">+!</span>[]<span style="color:#f92672">+!</span>[]);
<span style="color:#a6e22e">assert</span>(<span style="color:#ae81ff">10</span> <span style="color:#f92672">===</span> <span style="color:#f92672">+</span>(<span style="color:#f92672">!</span>[]<span style="color:#f92672">.+!!</span>[]));
</code></pre></div><p><code>[]</code> に <code>!</code> を適用すると <code>true</code> が返ってくる。それに <code>+</code>
を適用すると、<code>bool</code> から <code>int</code> ヘの型変換が走り、<code>1</code> が生成される。<code>10</code>
はさらにトリッキーだ。まず <code>1</code> と <code>0</code> を作り、<code>.</code> で文字列として結合する
(<code>'10'</code>)。これに <code>+</code> を適用すると、<code>string</code> から <code>int</code>
への型変換が走り、<code>10</code> が生まれる (コード量に頓着しないなら、<code>1</code> を 10
個足し合わせてももちろん 10 が作れる)。</p>
<p>また、<code>error_reporting</code> に指定しているのは <code>-1</code> である。
これは、<code>!</code> によって文字列を <code>false</code> にし、<code>+</code> によって <code>false</code> を <code>0</code> にし、さらにビット反転して <code>-1</code> にしている。</p>
<h3 id="if-文なしで条件分岐"><code>if</code> 文なしで条件分岐</h3>
<p>三項演算子ないし <code>match</code> 式を使うことで、<code>if</code> を一切書かずに条件分岐ができる。
また、<code>&amp;&amp;</code> / <code>||</code> も使えることがある。
遅延評価が不要なケースでは、<code>[$t, $f][$cond]</code> のような形で分岐することもできる。</p>
<h3 id="whilefor-文なしでループ"><code>while</code>、<code>for</code> 文なしでループ</h3>
<p>不動点コンビネータを使って無名再帰する (詳しい説明は省略する。これらの単語で検索してほしい)。
ここでは、一般に Z コンビネータとして知られるものを使った (<code>$z</code>)。</p>
<p>実際のところ、<code>$🤡</code> や <code>$🎪</code>、<code>$🐘</code> は、一度 Scheme (Lisp の一種) で書いてから PHP に翻訳する形で記述した。</p>
<p>なお、PHP は末尾再帰の最適化をおこなわない (少なくとも今のところは) ので、
あまりに長い brainf*ck プログラムを書くとスタックオーバーフローする。</p>
<h1 id="第2問-riddlephp">第2問 riddle.php</h1>
<p>ソースコードはこちら。実行には PHP 8.0 以上が必要なので注意。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php"><span style="color:#f92672">&lt;?</span><span style="color:#a6e22e">php</span>

<span style="color:#e6db74">/*********************************************************
</span><span style="color:#e6db74"> * This program displays a PHPer token.                  *
</span><span style="color:#e6db74"> * Guess &#39;N&#39;.                                            *
</span><span style="color:#e6db74"> *                                                       *
</span><span style="color:#e6db74"> * Hints:                                                *
</span><span style="color:#e6db74"> * - N itself has no special meaning, e.g., 42, 8128,    *
</span><span style="color:#e6db74"> *   it is selected at random.                           *
</span><span style="color:#e6db74"> * - Each element of $token represents a single letter.  *
</span><span style="color:#e6db74"> * - One letter consists of 5x5 cells.                   *
</span><span style="color:#e6db74"> * - Remember, the output is a complete PHPer token.     *
</span><span style="color:#e6db74"> *                                                       *
</span><span style="color:#e6db74"> * License:                                              *
</span><span style="color:#e6db74"> *   https://creativecommons.org/publicdomain/zero/1.0/  *
</span><span style="color:#e6db74"> *********************************************************/</span>
<span style="color:#66d9ef">const</span> <span style="color:#66d9ef">N</span> <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span> <span style="color:#75715e">/* Change it to your answer. */</span>;
<span style="color:#a6e22e">assert</span>(<span style="color:#ae81ff">0</span> <span style="color:#f92672">&lt;=</span> <span style="color:#a6e22e">N</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#a6e22e">N</span> <span style="color:#f92672">&lt;=</span> <span style="color:#ae81ff">0</span><span style="color:#a6e22e">b11111_11111_11111_11111_11111</span>);

$token <span style="color:#f92672">=</span> [
  <span style="color:#ae81ff">0x14B499C</span>,
  <span style="color:#ae81ff">0x0BE34CC</span>, <span style="color:#ae81ff">0x01C9C69</span>,
  <span style="color:#ae81ff">0x0ECA069</span>, <span style="color:#ae81ff">0x01C2449</span>, <span style="color:#ae81ff">0x0FDB166</span>, <span style="color:#ae81ff">0x01C9C69</span>,
  <span style="color:#ae81ff">0x01C1C66</span>, <span style="color:#ae81ff">0x0FC1C47</span>, <span style="color:#ae81ff">0x01C1C66</span>,
  <span style="color:#ae81ff">0x10C5858</span>, <span style="color:#ae81ff">0x1E4E3B8</span>, <span style="color:#ae81ff">0x1A2F2F8</span>,
];
<span style="color:#66d9ef">foreach</span> ($token <span style="color:#66d9ef">as</span> $x) {
  $x <span style="color:#f92672">=</span> $x <span style="color:#f92672">^</span> <span style="color:#a6e22e">N</span>;

  $x <span style="color:#f92672">=</span> <span style="color:#a6e22e">sprintf</span>(<span style="color:#e6db74">&#39;%025b&#39;</span>, $x);
  $x <span style="color:#f92672">=</span> <span style="color:#a6e22e">str_replace</span>(<span style="color:#a6e22e">search</span><span style="color:#f92672">:</span> [<span style="color:#e6db74">&#39;0&#39;</span>, <span style="color:#e6db74">&#39;1&#39;</span>], <span style="color:#a6e22e">replace</span><span style="color:#f92672">:</span> [<span style="color:#e6db74">&#39; &#39;</span>, <span style="color:#e6db74">&#39;#&#39;</span>], <span style="color:#a6e22e">subject</span><span style="color:#f92672">:</span> $x);
  $x <span style="color:#f92672">=</span> <span style="color:#a6e22e">implode</span>(<span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, <span style="color:#a6e22e">str_split</span>($x, <span style="color:#a6e22e">length</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">5</span>));
  <span style="color:#66d9ef">echo</span> <span style="color:#e6db74">&#34;</span><span style="color:#e6db74">{</span>$x<span style="color:#e6db74">}</span><span style="color:#ae81ff">\n\n</span><span style="color:#e6db74">&#34;</span>;
}
</code></pre></div><p>さて、この問題はさきほどのように単純に実行しただけでは、謎のブロックが表示されるだけでトークンは得られない。
トークンを得るためには、ソースコードを読み、定数 <code>N</code> を特定する必要がある。</p>
<p>ここでは、私の想定解を解説する。</p>
<h2 id="読解">読解</h2>
<p>まずはソースコードを読んでいく。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php">$token <span style="color:#f92672">=</span> [
  <span style="color:#75715e">// 略
</span><span style="color:#75715e"></span>];
</code></pre></div><p>数値からなる <code>$token</code> があり、各要素をループしている。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php">  $x <span style="color:#f92672">=</span> $x <span style="color:#f92672">^</span> <span style="color:#a6e22e">N</span>;
</code></pre></div><p>まずは排他的論理和 (xor) を取り、</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php">  $x <span style="color:#f92672">=</span> <span style="color:#a6e22e">sprintf</span>(<span style="color:#e6db74">&#39;%025b&#39;</span>, $x);
</code></pre></div><p>二進数に変換して、</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php">  $x <span style="color:#f92672">=</span> <span style="color:#a6e22e">str_replace</span>(<span style="color:#a6e22e">search</span><span style="color:#f92672">:</span> [<span style="color:#e6db74">&#39;0&#39;</span>, <span style="color:#e6db74">&#39;1&#39;</span>], <span style="color:#a6e22e">replace</span><span style="color:#f92672">:</span> [<span style="color:#e6db74">&#39; &#39;</span>, <span style="color:#e6db74">&#39;#&#39;</span>], <span style="color:#a6e22e">subject</span><span style="color:#f92672">:</span> $x);
</code></pre></div><p>0 を空白に、1 を <code>#</code> にし、</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php">  $x <span style="color:#f92672">=</span> <span style="color:#a6e22e">implode</span>(<span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, <span style="color:#a6e22e">str_split</span>($x, <span style="color:#a6e22e">length</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">5</span>));
</code></pre></div><p>5文字ごとに区切ったあと、改行で結合している。</p>
<h2 id="ヒント">ヒント</h2>
<p>次に、ソースコードに書いてあるヒントを読んでいく。</p>
<ul>
<li><code>N</code> それ自体は、42 や 8128 といったような特別な意味を持たず、ランダムに決められている</li>
<li><code>$token</code> の各要素は、1文字を表す</li>
<li>1文字は 5x5 のセルからなる</li>
<li>出力されるのは、完全な PHPer トークンである</li>
</ul>
<p>ここで、PHPer トークンは必ず <code>#</code> 記号から始まることを思いだすと、
<code>$token</code> の最初の数字 <code>0x14B499C</code> は、変換の結果 <code>#</code> になるのではないかと予想される (なお、このことは、リポジトリの README ファイルに追加ヒントとして書かれている)。</p>
<h2 id="解く">解く</h2>
<p>ここまでわかれば、あと一歩で解ける。すなわち、<code>0x14B499C</code> が <code>#</code> に変換されるような <code>N</code> を見つければよい。</p>
<p><code>N</code> は高々</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php"><span style="color:#a6e22e">assert</span>(<span style="color:#ae81ff">0</span> <span style="color:#f92672">&lt;=</span> <span style="color:#a6e22e">N</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#a6e22e">N</span> <span style="color:#f92672">&lt;=</span> <span style="color:#ae81ff">0</span><span style="color:#a6e22e">b11111_11111_11111_11111_11111</span>);
</code></pre></div><p>なのでブルートフォースしてもよいが、ここではブルートフォースしない方法を紹介する。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php"><span style="color:#f92672">&lt;?</span><span style="color:#a6e22e">php</span>

$x <span style="color:#f92672">=</span> <span style="color:#ae81ff">0x14B499C</span>;

$x <span style="color:#f92672">=</span> $x <span style="color:#f92672">^</span> <span style="color:#a6e22e">N</span>;

$x <span style="color:#f92672">=</span> <span style="color:#a6e22e">sprintf</span>(<span style="color:#e6db74">&#39;%025b&#39;</span>, $x);
$x <span style="color:#f92672">=</span> <span style="color:#a6e22e">str_replace</span>(<span style="color:#a6e22e">search</span><span style="color:#f92672">:</span> [<span style="color:#e6db74">&#39;0&#39;</span>, <span style="color:#e6db74">&#39;1&#39;</span>], <span style="color:#a6e22e">replace</span><span style="color:#f92672">:</span> [<span style="color:#e6db74">&#39; &#39;</span>, <span style="color:#e6db74">&#39;#&#39;</span>], <span style="color:#a6e22e">subject</span><span style="color:#f92672">:</span> $x);
$x <span style="color:#f92672">=</span> <span style="color:#a6e22e">implode</span>(<span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, <span style="color:#a6e22e">str_split</span>($x, <span style="color:#a6e22e">length</span><span style="color:#f92672">:</span> <span style="color:#ae81ff">5</span>));

<span style="color:#a6e22e">assert</span>($x <span style="color:#f92672">===</span>
  <span style="color:#e6db74">&#34; # # </span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span> <span style="color:#f92672">.</span>
  <span style="color:#e6db74">&#34;#####</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span> <span style="color:#f92672">.</span>
  <span style="color:#e6db74">&#34; # # </span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span> <span style="color:#f92672">.</span>
  <span style="color:#e6db74">&#34;#####</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span> <span style="color:#f92672">.</span>
  <span style="color:#e6db74">&#34; # # &#34;</span>);
</code></pre></div><p>この一連の変換に対する逆変換を考えると、次のようになる。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php"><span style="color:#f92672">&lt;?</span><span style="color:#a6e22e">php</span>

$x <span style="color:#f92672">=</span>
  <span style="color:#e6db74">&#34; # # </span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span> <span style="color:#f92672">.</span>
  <span style="color:#e6db74">&#34;#####</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span> <span style="color:#f92672">.</span>
  <span style="color:#e6db74">&#34; # # </span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span> <span style="color:#f92672">.</span>
  <span style="color:#e6db74">&#34;#####</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span> <span style="color:#f92672">.</span>
  <span style="color:#e6db74">&#34; # # &#34;</span>;

$x <span style="color:#f92672">=</span> <span style="color:#a6e22e">implode</span>(<span style="color:#e6db74">&#39;&#39;</span>, <span style="color:#a6e22e">explode</span>(<span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, $x));
$x <span style="color:#f92672">=</span> <span style="color:#a6e22e">str_replace</span>(<span style="color:#a6e22e">search</span><span style="color:#f92672">:</span> [<span style="color:#e6db74">&#39; &#39;</span>, <span style="color:#e6db74">&#39;#&#39;</span>], <span style="color:#a6e22e">replace</span><span style="color:#f92672">:</span> [<span style="color:#e6db74">&#39;0&#39;</span>, <span style="color:#e6db74">&#39;1&#39;</span>], <span style="color:#a6e22e">subject</span><span style="color:#f92672">:</span> $x);
$x <span style="color:#f92672">=</span> <span style="color:#a6e22e">bindec</span>($x);

$n <span style="color:#f92672">=</span> $x <span style="color:#f92672">^</span> <span style="color:#ae81ff">0x14B499C</span>;

<span style="color:#66d9ef">echo</span> <span style="color:#e6db74">&#34;N = </span><span style="color:#e6db74">$n\n</span><span style="color:#e6db74">&#34;</span>;
</code></pre></div><p>これを実行すると、<code>N</code> が得られる。</p>
<h1 id="第3問-toquinephp">第3問 toquine.php</h1>
<p>ソースコードはこちら。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php"><span style="color:#f92672">&lt;?</span><span style="color:#a6e22e">php</span>

<span style="color:#75715e">// License: https://creativecommons.org/publicdomain/zero/1.0/
</span><span style="color:#75715e">// This is a quine-like program to generate a PHPer token.
</span><span style="color:#75715e">// Execute it like this: php toquine.php | php | php | php | ...
</span><span style="color:#75715e"></span>
$s <span style="color:#f92672">=</span> <span style="color:#e6db74">&lt;&lt;&lt;&#39;</span><span style="color:#e6db74">Q</span><span style="color:#e6db74">&#39;
</span><span style="color:#e6db74">&lt;?cuc
</span><span style="color:#e6db74">// Yvprafr: uggcf://perngvirpbzzbaf.bet/choyvpqbznva/mreb/1.0/
</span><span style="color:#e6db74">// Guvf vf n dhvar-yvxr cebtenz gb trarengr n CUCre gbxra.
</span><span style="color:#e6db74">// Rkrphgr vg yvxr guvf: cuc gbdhvar.cuc | cuc | cuc | cuc | ...
</span><span style="color:#e6db74">%f$f = %f;
</span><span style="color:#e6db74">$f = fge_ebg13($f); $kf = [
</span><span style="color:#e6db74">%f,
</span><span style="color:#e6db74">];
</span><span style="color:#e6db74">$g = ahyy.snyfr; sbe ($v = 0; $v &lt;= vagqvi(__YVAR__-035,6); ++$v) vs (!vffrg($kf[$v])) oernx; ryfr
</span><span style="color:#e6db74">$g .= vzcybqr(&#34;\a&#34;, fge_fcyvg(fge_ercynpr([&#39;0&#39;,&#39;1&#39;], [&#39;  &#39;,&#39;##&#39;], fcevags(pue(37) . &#39;025o&#39;, $kf[$v])), 012)) . &#34;\a\a&#34;;
</span><span style="color:#e6db74">$jf = neenl_znc(sa($j) =&gt; vzcybqr(&#39;, &#39;, $j), neenl_puhax(neenl_znc(sa($k) =&gt; fcevags(&#39;0k&#39; . pue(37) . &#39;07K&#39;, $k), $kf), 10));
</span><span style="color:#e6db74">cevags($f, $g, fge_ebg13(&#34;&lt;&lt;&lt;&#39;Q&#39;\a{$f}\aQ&#34;), vzcybqr(&#34;,\a&#34;, $jf));
</span><span style="color:#e6db74"></span><span style="color:#e6db74">Q</span>;
$s <span style="color:#f92672">=</span> <span style="color:#a6e22e">str_rot13</span>($s); $xs <span style="color:#f92672">=</span> [
<span style="color:#ae81ff">0x0AFABEA</span>, <span style="color:#ae81ff">0x1F294A7</span>, <span style="color:#ae81ff">0x1F2109F</span>, <span style="color:#ae81ff">0x1F294A7</span>, <span style="color:#ae81ff">0x0002800</span>, <span style="color:#ae81ff">0x1F2109F</span>, <span style="color:#ae81ff">0x0117041</span>, <span style="color:#ae81ff">0x1F294A7</span>, <span style="color:#ae81ff">0x1FAD6B5</span>, <span style="color:#ae81ff">0x1F295B7</span>,
<span style="color:#ae81ff">0x010FC21</span>, <span style="color:#ae81ff">0x1FAD6B5</span>, <span style="color:#ae81ff">0x1151151</span>, <span style="color:#ae81ff">0x010FC21</span>, <span style="color:#ae81ff">0x1F294A7</span>, <span style="color:#ae81ff">0x1F295B7</span>, <span style="color:#ae81ff">0x1FAD6B5</span>, <span style="color:#ae81ff">0x1F294A7</span>, <span style="color:#ae81ff">0x1F295B7</span>, <span style="color:#ae81ff">0x1F8C63F</span>,
<span style="color:#ae81ff">0x1F8C631</span>, <span style="color:#ae81ff">0x1FAD6B5</span>, <span style="color:#ae81ff">0x17AD6BD</span>, <span style="color:#ae81ff">0x17AD6BD</span>, <span style="color:#ae81ff">0x1F8C63F</span>, <span style="color:#ae81ff">0x1F295B7</span>,
];
$t <span style="color:#f92672">=</span> <span style="color:#66d9ef">null</span><span style="color:#f92672">.</span><span style="color:#66d9ef">false</span>; <span style="color:#66d9ef">for</span> ($i <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>; $i <span style="color:#f92672">&lt;=</span> <span style="color:#a6e22e">intdiv</span>(<span style="color:#66d9ef">__LINE__</span><span style="color:#f92672">-</span><span style="color:#ae81ff">035</span>,<span style="color:#ae81ff">6</span>); <span style="color:#f92672">++</span>$i) <span style="color:#66d9ef">if</span> (<span style="color:#f92672">!</span><span style="color:#a6e22e">isset</span>($xs[$i])) <span style="color:#66d9ef">break</span>; <span style="color:#66d9ef">else</span>
$t <span style="color:#f92672">.=</span> <span style="color:#a6e22e">implode</span>(<span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, <span style="color:#a6e22e">str_split</span>(<span style="color:#a6e22e">str_replace</span>([<span style="color:#e6db74">&#39;0&#39;</span>,<span style="color:#e6db74">&#39;1&#39;</span>], [<span style="color:#e6db74">&#39;  &#39;</span>,<span style="color:#e6db74">&#39;##&#39;</span>], <span style="color:#a6e22e">sprintf</span>(<span style="color:#a6e22e">chr</span>(<span style="color:#ae81ff">37</span>) <span style="color:#f92672">.</span> <span style="color:#e6db74">&#39;025b&#39;</span>, $xs[$i])), <span style="color:#ae81ff">012</span>)) <span style="color:#f92672">.</span> <span style="color:#e6db74">&#34;</span><span style="color:#ae81ff">\n\n</span><span style="color:#e6db74">&#34;</span>;
$ws <span style="color:#f92672">=</span> <span style="color:#a6e22e">array_map</span>(<span style="color:#a6e22e">fn</span>($w) <span style="color:#f92672">=&gt;</span> <span style="color:#a6e22e">implode</span>(<span style="color:#e6db74">&#39;, &#39;</span>, $w), <span style="color:#a6e22e">array_chunk</span>(<span style="color:#a6e22e">array_map</span>(<span style="color:#a6e22e">fn</span>($x) <span style="color:#f92672">=&gt;</span> <span style="color:#a6e22e">sprintf</span>(<span style="color:#e6db74">&#39;0x&#39;</span> <span style="color:#f92672">.</span> <span style="color:#a6e22e">chr</span>(<span style="color:#ae81ff">37</span>) <span style="color:#f92672">.</span> <span style="color:#e6db74">&#39;07X&#39;</span>, $x), $xs), <span style="color:#ae81ff">10</span>));
<span style="color:#a6e22e">printf</span>($s, $t, <span style="color:#a6e22e">str_rot13</span>(<span style="color:#e6db74">&#34;&lt;&lt;&lt;&#39;D&#39;</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">{</span>$s<span style="color:#e6db74">}</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">D&#34;</span>), <span style="color:#a6e22e">implode</span>(<span style="color:#e6db74">&#34;,</span><span style="color:#ae81ff">\n</span><span style="color:#e6db74">&#34;</span>, $ws));
</code></pre></div><p>コメントにもあるとおり、次のようにして実行すれば答えがでてくる。</p>
<pre tabindex="0"><code class="language-shell-session" data-lang="shell-session">$ php toquine.php | php | php | php | ...
</code></pre><p>実際にはもう少しパイプで繋げなければならない。</p>
<h2 id="解説-1">解説</h2>
<h3 id="プログラム全体-1">プログラム全体</h3>
<p>コメントにもあるとおり、これは quine (風) のプログラムになっている。
Quine とは、自分のソースコードをそっくりそのまま出力するようなプログラムのことである。</p>
<p>このプログラムは、実行すると自身とほとんど同じプログラムを出力する。
異なるのはトークンになっている部分のみである。</p>
<h3 id="トークン">トークン</h3>
<p><code>$xs</code> がトークンに対応している。変換のロジックは <code>riddle.php</code> とほぼ同じなので省略する。</p>
<h3 id="状態保持">状態保持</h3>
<p>トークンの何文字目まで出力したかを、ソースコードを変えずに (quine なので) 覚えておく必要がある。
このプログラムでは、トークンが出力されるとソースコードがだんだんと長くなっていくのを利用して、<code>__LINE__</code> から情報を取得している。</p>
<h3 id="rot-13">ROT 13</h3>
<p>Quine は、素朴に書くとプログラムの一部が 2回記述されてしまう。
これがあまり美しくないので、<code>toquine.php</code> では、ROT 13 変換を使って難読化した。</p>
<p>それにしてもなぜこんなものが標準ライブラリに……。</p>
<h1 id="おわりに">おわりに</h1>
<p>解いていただいたみなさん、また、難易度調整につきあっていただいた社内のみなさん、ありがとうございました。</p>
<p>今回は直前に作りはじめたのもあり、3問だけかつ使い古されたネタばかりになってしまいましたが、
来年は 5問、より面白い問題を持っていきます。</p>
<p>実はもう作りはじめているので、どうか来年もありますように……。</p>
]]></description>
    </item>
    
    <item>
      <title>Rust のプリミティブ型はどこからやって来るか</title>
      <link>https://blog.nsfisis.dev/posts/2021-10-02/rust-where-are-primitive-types-from/</link>
      <pubDate>Sat, 02 Oct 2021 09:39:27 +0900</pubDate>
      
      <guid>https://blog.nsfisis.dev/posts/2021-10-02/rust-where-are-primitive-types-from/</guid>
      <description><![CDATA[ <p>この記事は Qiita から移植してきたものです。
元 URL: <a href="https://qiita.com/nsfisis/items/9a429432258bbcd6c565">https://qiita.com/nsfisis/items/9a429432258bbcd6c565</a></p>
<hr>
<h1 id="前置き">前置き</h1>
<p>Rust において、プリミティブ型の名前は予約語でない。したがって、次のコードは合法である。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-rust" data-lang="rust"><span style="color:#75715e">#![allow(non_camel_case_types)]</span>
<span style="color:#75715e">#![allow(dead_code)]</span>

<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">bool</span>;
<span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">char</span>;
<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">i8</span>;
<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">i16</span>;
<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">i32</span>;
<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">i64</span>;
<span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">i128</span>;
<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">isize</span>;
<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">u8</span>;
<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">u16</span>;
<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">u32</span>;
<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">u64</span>;
<span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">u128</span>;
<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">usize</span>;
<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">f32</span>;
<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">f64</span>;
<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">str</span>;
</code></pre></div><p>では、普段単に <code>bool</code> と書いたとき、この <code>bool</code> は一体どこから来ているのか。rustc のソースを追ってみた。</p>
<blockquote>
<p>前提知識: 一般的なコンパイラの構造、用語。<code>rustc</code> そのものの知識は不要 (というよりも筆者自身がよく知らない)</p>
</blockquote>
<h1 id="調査">調査</h1>
<p>調査に使用したソース (調査時点での最新 master)</p>
<p><a href="https://github.com/rust-lang/rust/tree/511ed9f2356af365ad8affe046b3dd33f7ac3c98">https://github.com/rust-lang/rust/tree/511ed9f2356af365ad8affe046b3dd33f7ac3c98</a></p>
<p>どのようにして調べるか。rustc の構造には詳しくないため、すぐに当たりをつけるのは難しい。</p>
<p>大雑把な構造としては、<code>compiler</code> フォルダ以下に <code>rustc_*</code> という名前のクレートが数十個入っている。これがどうやら <code>rustc</code> コマンドの実装部のようだ。</p>
<p><code>rustc</code> はセルフホストされている (= <code>rustc</code> 自身が Rust で書かれている) ので、<code>bool</code> や <code>char</code> などで適当に検索をかけてもノイズが多すぎて話にならない。
しかし、お誂え向きなことに <code>i128</code>/<code>u128</code> というコンパイラ自身が使うことがなさそうな型が存在するのでこれを使って <code>git grep</code> してみる。</p>
<pre tabindex="0"><code>$ git grep &quot;\bi128\b&quot; | wc      # i128
     165    1069   15790

$ git grep &quot;\bu128\b&quot; | wc      # u128
     293    2127   26667

$ git grep &quot;\bbool\b&quot; | wc      # cf. bool の結果
    3563   23577  294659
</code></pre><p>165 程度であれば探すことができそうだ。今回は、クレート名を見ておおよその当たりをつけた。</p>
<pre tabindex="0"><code>$ git grep &quot;\bi128\b&quot;
...
rustc_resolve/src/lib.rs:        table.insert(sym::i128, Int(IntTy::I128));
...
</code></pre><p><code>rustc_resolve</code> というのはいかにも名前解決を担いそうなクレート名である。該当箇所を見てみる。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-rust" data-lang="rust"><span style="color:#e6db74">/// Interns the names of the primitive types.
</span><span style="color:#e6db74">///
</span><span style="color:#e6db74">/// All other types are defined somewhere and possibly imported, but the primitive ones need
</span><span style="color:#e6db74">/// special handling, since they have no place of origin.
</span><span style="color:#e6db74"></span><span style="color:#66d9ef">struct</span> <span style="color:#a6e22e">PrimitiveTypeTable</span> {
    primitive_types: <span style="color:#a6e22e">FxHashMap</span><span style="color:#f92672">&lt;</span>Symbol, PrimTy<span style="color:#f92672">&gt;</span>,
}

<span style="color:#66d9ef">impl</span> PrimitiveTypeTable {
    <span style="color:#66d9ef">fn</span> <span style="color:#a6e22e">new</span>() -&gt; <span style="color:#a6e22e">PrimitiveTypeTable</span> {
        <span style="color:#66d9ef">let</span> <span style="color:#66d9ef">mut</span> table <span style="color:#f92672">=</span> FxHashMap::default();

        table.insert(sym::<span style="color:#66d9ef">bool</span>, Bool);
        table.insert(sym::char, Char);
        table.insert(sym::<span style="color:#66d9ef">f32</span>, Float(FloatTy::F32));
        table.insert(sym::<span style="color:#66d9ef">f64</span>, Float(FloatTy::F64));
        table.insert(sym::<span style="color:#66d9ef">isize</span>, Int(IntTy::Isize));
        table.insert(sym::<span style="color:#66d9ef">i8</span>, Int(IntTy::I8));
        table.insert(sym::<span style="color:#66d9ef">i16</span>, Int(IntTy::I16));
        table.insert(sym::<span style="color:#66d9ef">i32</span>, Int(IntTy::I32));
        table.insert(sym::<span style="color:#66d9ef">i64</span>, Int(IntTy::I64));
        table.insert(sym::<span style="color:#66d9ef">i128</span>, Int(IntTy::I128));
        table.insert(sym::<span style="color:#66d9ef">str</span>, Str);
        table.insert(sym::<span style="color:#66d9ef">usize</span>, Uint(UintTy::Usize));
        table.insert(sym::<span style="color:#66d9ef">u8</span>, Uint(UintTy::U8));
        table.insert(sym::<span style="color:#66d9ef">u16</span>, Uint(UintTy::U16));
        table.insert(sym::<span style="color:#66d9ef">u32</span>, Uint(UintTy::U32));
        table.insert(sym::<span style="color:#66d9ef">u64</span>, Uint(UintTy::U64));
        table.insert(sym::<span style="color:#66d9ef">u128</span>, Uint(UintTy::U128));
        Self { primitive_types: <span style="color:#a6e22e">table</span> }
    }
}
</code></pre></div><p>これは初めに列挙したプリミティブ型の一覧と一致している。doc comment にも、</p>
<blockquote>
<p>All other types are defined somewhere and possibly imported, but the primitive ones need special handling, since they have no place of origin.</p>
</blockquote>
<p>とある。次はこの struct の使用箇所を追う。追うと言っても使われている箇所は次の一箇所しかない。なお説明に不要な箇所は大きく削っている。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-rust" data-lang="rust">    <span style="color:#e6db74">/// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope.
</span><span style="color:#e6db74"></span>    <span style="color:#e6db74">/// (略)
</span><span style="color:#e6db74"></span>    <span style="color:#66d9ef">fn</span> <span style="color:#a6e22e">resolve_ident_in_lexical_scope</span>(
        <span style="color:#f92672">&amp;</span><span style="color:#66d9ef">mut</span> self,
        <span style="color:#66d9ef">mut</span> ident: <span style="color:#a6e22e">Ident</span>,
        ns: <span style="color:#a6e22e">Namespace</span>,
        <span style="color:#75715e">// (略)
</span><span style="color:#75715e"></span>    ) -&gt; Option<span style="color:#f92672">&lt;</span>LexicalScopeBinding<span style="color:#f92672">&lt;</span><span style="color:#a6e22e">&#39;a</span><span style="color:#f92672">&gt;&gt;</span> {
        <span style="color:#75715e">// (略)
</span><span style="color:#75715e"></span>
        <span style="color:#66d9ef">if</span> ns <span style="color:#f92672">==</span> TypeNS {
            <span style="color:#66d9ef">if</span> <span style="color:#66d9ef">let</span> Some(prim_ty) <span style="color:#f92672">=</span> self.primitive_type_table.primitive_types.get(<span style="color:#f92672">&amp;</span>ident.name) {
                <span style="color:#66d9ef">let</span> binding <span style="color:#f92672">=</span>
                    (Res::PrimTy(<span style="color:#f92672">*</span>prim_ty), ty::Visibility::Public, DUMMY_SP, ExpnId::root())
                        .to_name_binding(self.arenas);
                <span style="color:#66d9ef">return</span> Some(LexicalScopeBinding::Item(binding));
            }
        }

        None
    }
</code></pre></div><p>関数名や doc comment が示している通り、この関数は識別子 (identifier, ident) を現在のレキシカルスコープ内で解決 (resolve) する。
<code>if ns == TypeNS</code> のブロック内では、<code>primitive_type_table</code> (上記の <code>PrimitiveTypeTable::new()</code> で作られた変数) に含まれている識別子 (<code>bool</code>、<code>i32</code> など) かどうか判定し、そうであればそれに紐づけられたプリミティブ型を返している。</p>
<p>なお、<code>ns</code> は「名前空間」を示す変数である。Rust における名前空間はC言語におけるそれとほとんど同じで、今探している名前が関数名/変数名なのか型なのかマクロなのかを区別している。この <code>if</code> は、プリミティブ型に解決されるのは型を探しているときだけだ、と言っている。</p>
<p>重要なのは、これが <code>resolve_ident_in_lexical_scope()</code> の最後に書かれている点である。つまり、最初に挙げたプリミティブ型の識別子は、「名前解決の最終段階で」、「他に同名の型が見つかっていなければ」プリミティブ型として解決される。</p>
<p>動作がわかったところで、例として次のコードを考える。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-rust" data-lang="rust"><span style="color:#75715e">#![allow(non_camel_case_types)]</span>

<span style="color:#66d9ef">struct</span> <span style="color:#66d9ef">bool</span>;

<span style="color:#66d9ef">fn</span> <span style="color:#a6e22e">main</span>() {
    <span style="color:#66d9ef">let</span> _: <span style="color:#66d9ef">bool</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">bool</span>;
}
</code></pre></div><p>ここで <code>main()</code> の <code>bool</code> は <code>struct bool</code> として解決される。なぜなら、プリミティブ型の判定をする前に <code>bool</code> という名前の別の型が見つかるからだ。</p>
<h1 id="まとめ">まとめ</h1>
<p>Rust のプリミティブ型は予約語ではない。名前解決の最終段階で特別扱いされ、他に同名の型が見つかっていなければ対応するプリミティブ型に解決される。</p>
]]></description>
    </item>
    
    <item>
      <title>[Ruby] then キーワードと case in</title>
      <link>https://blog.nsfisis.dev/posts/2021-10-02/ruby-then-keyword-and-case-in/</link>
      <pubDate>Sat, 02 Oct 2021 09:38:50 +0900</pubDate>
      
      <guid>https://blog.nsfisis.dev/posts/2021-10-02/ruby-then-keyword-and-case-in/</guid>
      <description><![CDATA[ <p>この記事は Qiita から移植してきたものです。
元 URL: <a href="https://qiita.com/nsfisis/items/787a8cf888a304497223">https://qiita.com/nsfisis/items/787a8cf888a304497223</a></p>
<hr>
<h1 id="tl-dr">TL; DR</h1>
<p><code>case</code> - <code>in</code> によるパターンマッチング構文でも、<code>case</code> - <code>when</code> と同じように <code>then</code> が使える (場合によっては使う必要がある)。</p>
<h1 id="then-とは"><code>then</code> とは</h1>
<p>使われることは稀だが、Ruby では <code>then</code> がキーワードになっている。次のように使う:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ruby" data-lang="ruby"><span style="color:#66d9ef">if</span> cond <span style="color:#66d9ef">then</span>
  puts <span style="color:#e6db74">&#34;Y&#34;</span>
<span style="color:#66d9ef">else</span>
  puts <span style="color:#e6db74">&#34;N&#34;</span>
<span style="color:#66d9ef">end</span>
</code></pre></div><p>このキーワードが現れうる場所はいくつかあり、<code>if</code>、<code>unless</code>、<code>rescue</code>、<code>case</code> 構文がそれに当たる。
上記のように、何か条件を書いた後 <code>then</code> を置き、式がそこで終了していることを示すマーカーとして機能する。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ruby" data-lang="ruby"><span style="color:#75715e"># Example:</span>

<span style="color:#66d9ef">if</span> x <span style="color:#66d9ef">then</span>
  a
<span style="color:#66d9ef">end</span>

<span style="color:#66d9ef">unless</span> x <span style="color:#66d9ef">then</span>
  a
<span style="color:#66d9ef">end</span>

<span style="color:#66d9ef">begin</span>
  a
<span style="color:#66d9ef">rescue</span> <span style="color:#66d9ef">then</span>
  b
<span style="color:#66d9ef">end</span>

<span style="color:#66d9ef">case</span> x
<span style="color:#66d9ef">when</span> p <span style="color:#66d9ef">then</span>
  a
<span style="color:#66d9ef">end</span>
</code></pre></div><h1 id="なぜ普段は書かなくてもよいのか">なぜ普段は書かなくてもよいのか</h1>
<p>普通 Ruby のコードで <code>then</code> を書くことはない。なぜか。次のコードを実行してみるとわかる。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ruby" data-lang="ruby"><span style="color:#66d9ef">if</span> <span style="color:#66d9ef">true</span> puts <span style="color:#e6db74">&#39;Hello, World!&#39;</span> <span style="color:#66d9ef">end</span>
</code></pre></div><p>次のような構文エラーが出力される。</p>
<pre tabindex="0"><code>20:1: syntax error, unexpected local variable or method, expecting `then' or ';' or '\n'
if true puts 'Hello, World!' end
        ^~~~
20:1: syntax error, unexpected `end', expecting end-of-input
...f true puts 'Hello, World!' end
</code></pre><p>二つ目のメッセージは無視して一つ目を読むと、<code>then</code> か <code>;</code> か改行が来るはずのところ変数だかメソッドだかが現れたことによりエラーとなっているようだ。</p>
<p>ポイントは改行が <code>then</code> (や <code>;</code>) の代わりとなることである。<code>true</code> の後に改行を入れてみる。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ruby" data-lang="ruby"><span style="color:#66d9ef">if</span> <span style="color:#66d9ef">true</span>
puts <span style="color:#e6db74">&#39;Hello, World!&#39;</span> <span style="color:#66d9ef">end</span>
</code></pre></div><p>無事 Hello, World! と出力されるようになった。</p>
<h1 id="なぜ-then-や--や改行が必要か">なぜ <code>then</code> や <code>;</code> や改行が必要か</h1>
<p>なぜ <code>then</code> や <code>;</code> や改行 (以下 「<code>then</code> 等」) が必要なのだろうか。次の例を見てほしい:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ruby" data-lang="ruby"><span style="color:#66d9ef">if</span> a b <span style="color:#66d9ef">end</span>
</code></pre></div><p><code>then</code> も <code>;</code> も改行もないのでエラーになるが、これは条件式がどこまで続いているのかわからないためだ。
この例は二通りに解釈できる。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ruby" data-lang="ruby"><span style="color:#75715e"># a という変数かメソッドの評価結果が truthy なら b という変数かメソッドを評価</span>
<span style="color:#66d9ef">if</span> a <span style="color:#66d9ef">then</span>
  b
<span style="color:#66d9ef">end</span>
</code></pre></div><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ruby" data-lang="ruby"><span style="color:#75715e"># a というメソッドに b という変数かメソッドの評価結果を渡して呼び出し、</span>
<span style="color:#75715e"># その結果が truthy なら何もしない</span>
<span style="color:#66d9ef">if</span> a(b) <span style="color:#66d9ef">then</span>
<span style="color:#66d9ef">end</span>
</code></pre></div><p><code>then</code> 等はこの曖昧性を排除するためにあり、条件式は <code>if</code> から <code>then</code> 等までの間にある、ということを明確にする。
C系の <code>if</code> 後に来る <code>(</code>/<code>)</code> や、Python の <code>:</code>、Rust/Go/Swift などの <code>{</code> も同じ役割を持つ。</p>
<p>Ruby の場合、プログラマーが書きやすいよう改行でもって <code>then</code> が代用できるので、ほとんどの場合 <code>then</code> は必要ない。</p>
<h1 id="case---in-における-then"><code>case</code> - <code>in</code> における <code>then</code></h1>
<p>ようやく本題にたどり着いた。来る Ruby 3.0 では <code>case</code> と <code>in</code> キーワードを使ったパターンマッチングの構文が入る予定である。この構文でもパターン部との区切りとして <code>then</code> 等が必要になる。
(現在の) Ruby には formal な形式での文法仕様は存在しないので、yacc の定義ファイルを参照した (yacc の説明は省略)。</p>
<p><a href="https://github.com/ruby/ruby/blob/221ca0f8281d39f0dfdfe13b2448875384bbf735/parse.y#L3961-L3986">https://github.com/ruby/ruby/blob/221ca0f8281d39f0dfdfe13b2448875384bbf735/parse.y#L3961-L3986</a></p>
<pre tabindex="0"><code class="language-yacc" data-lang="yacc">p_case_body	: keyword_in
		    {
			SET_LEX_STATE(EXPR_BEG|EXPR_LABEL);
			p-&gt;command_start = FALSE;
			$&lt;ctxt&gt;1 = p-&gt;ctxt;
			p-&gt;ctxt.in_kwarg = 1;
			$&lt;tbl&gt;$ = push_pvtbl(p);
		    }
		    {
			$&lt;tbl&gt;$ = push_pktbl(p);
		    }
		  p_top_expr then
		    {
			pop_pktbl(p, $&lt;tbl&gt;3);
			pop_pvtbl(p, $&lt;tbl&gt;2);
			p-&gt;ctxt.in_kwarg = $&lt;ctxt&gt;1.in_kwarg;
		    }
		  compstmt
		  p_cases
		    {
		    /*%%%*/
			$$ = NEW_IN($4, $7, $8, &amp;@$);
		    /*% %*/
		    /*% ripper: in!($4, $7, escape_Qundef($8)) %*/
		    }
		;
</code></pre><p>簡略版:</p>
<pre tabindex="0"><code class="language-yacc" data-lang="yacc">p_case_body	: keyword_in p_top_expr then compstmt p_cases
		;
</code></pre><p>ここで、<code>keyword_in</code> は文字通り <code>in</code>、<code>p_top_expr</code> はいわゆるパターン、<code>then</code> は <code>then</code> キーワードのことではなく、この記事で <code>then</code> 等と呼んでいるもの、つまり <code>then</code> キーワード、<code>;</code>、改行のいずれかである。</p>
<p>これにより、<code>case</code> - <code>when</code> による従来の構文と同じように、<code>then</code> 等をパターンの後ろに挿入すればよいことがわかった。つまり次の3通りのいずれかになる:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ruby" data-lang="ruby"><span style="color:#66d9ef">case</span> x
<span style="color:#66d9ef">in</span> <span style="color:#ae81ff">1</span> <span style="color:#66d9ef">then</span> a
<span style="color:#66d9ef">in</span> <span style="color:#ae81ff">2</span> <span style="color:#66d9ef">then</span> b
<span style="color:#66d9ef">in</span> <span style="color:#ae81ff">3</span> <span style="color:#66d9ef">then</span> c
<span style="color:#66d9ef">end</span>

<span style="color:#66d9ef">case</span> x
<span style="color:#66d9ef">in</span> <span style="color:#ae81ff">1</span>
  a
<span style="color:#66d9ef">in</span> <span style="color:#ae81ff">2</span>
  b
<span style="color:#66d9ef">in</span> <span style="color:#ae81ff">3</span>
  c
<span style="color:#66d9ef">end</span>

<span style="color:#66d9ef">case</span> x
<span style="color:#66d9ef">in</span> <span style="color:#ae81ff">1</span>; a
<span style="color:#66d9ef">in</span> <span style="color:#ae81ff">2</span>; b
<span style="color:#66d9ef">in</span> <span style="color:#ae81ff">3</span>; c
<span style="color:#66d9ef">end</span>
</code></pre></div><p>ところで、<code>p_top_expr</code> には <code>if</code> による guard clause が書けるので、その場合は <code>if</code> - <code>then</code> と似たような見た目になる。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ruby" data-lang="ruby"><span style="color:#66d9ef">case</span> x
<span style="color:#66d9ef">in</span> <span style="color:#ae81ff">0</span> <span style="color:#66d9ef">then</span> a
<span style="color:#66d9ef">in</span> n <span style="color:#66d9ef">if</span> n <span style="color:#f92672">&lt;</span> <span style="color:#ae81ff">0</span> <span style="color:#66d9ef">then</span> b
<span style="color:#66d9ef">in</span> n <span style="color:#66d9ef">then</span> c
<span style="color:#66d9ef">end</span>
</code></pre></div><h1 id="まとめ">まとめ</h1>
<ul>
<li><code>if</code> や <code>case</code> の条件の後ろには <code>then</code>、<code>;</code>、改行のいずれかが必要
<ul>
<li>通常は改行しておけばよい</li>
</ul>
</li>
<li>3.0 で入る予定の <code>case</code> - <code>in</code> でも <code>then</code> 等が必要になる</li>
<li>Ruby の構文を正確に知るには (現状) <code>parse.y</code> を直接読めばよい</li>
</ul>
]]></description>
    </item>
    
    <item>
      <title>[C&#43;&#43;] 属性構文の属性名にはキーワードが使える [[void]] [[for]]</title>
      <link>https://blog.nsfisis.dev/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes/</link>
      <pubDate>Sat, 02 Oct 2021 09:38:30 +0900</pubDate>
      
      <guid>https://blog.nsfisis.dev/posts/2021-10-02/cpp-you-can-use-keywords-in-attributes/</guid>
      <description><![CDATA[ <p>この記事は Qiita から移植してきたものです。
元 URL: <a href="https://qiita.com/nsfisis/items/94090937bcf860cfa93b">https://qiita.com/nsfisis/items/94090937bcf860cfa93b</a></p>
<hr>
<p>タイトル落ち。まずはこのコードを見て欲しい。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-cpp" data-lang="cpp"><span style="color:#75715e">#include</span> <span style="color:#75715e">&lt;iostream&gt;</span><span style="color:#75715e">
</span><span style="color:#75715e"></span>
<span style="color:#a6e22e">[[alignas]] [[alignof]] [[and]] [[and_eq]] [[asm]] [[auto]] [[bitand]]</span>
<span style="color:#a6e22e">[[bitor]] [[bool]] [[break]] [[case]] [[catch]] [[char]] [[char16_t]]</span>
<span style="color:#a6e22e">[[char32_t]] [[class]] [[compl]] [[const]] [[const_cast]] [[constexpr]]</span>
<span style="color:#a6e22e">[[continue]] [[decltype]] [[default]] [[delete]] [[do]] [[double]]</span>
<span style="color:#a6e22e">[[dynamic_cast]] [[else]] [[enum]] [[explicit]] [[export]] [[extern]] [[false]]</span>
<span style="color:#a6e22e">[[final]] [[float]] [[for]] [[friend]] [[goto]] [[if]] [[inline]] [[int]]</span>
<span style="color:#a6e22e">[[long]] [[mutable]] [[namespace]] [[new]] [[noexcept]] [[not]] [[not_eq]]</span>
<span style="color:#a6e22e">[[nullptr]] [[operator]] [[or]] [[or_eq]] [[override]] [[private]]</span>
<span style="color:#a6e22e">[[protected]] [[public]] [[register]] [[reinterpret_cast]] [[return]] [[short]]</span>
<span style="color:#a6e22e">[[signed]] [[sizeof]] [[static]] [[static_assert]] [[static_cast]] [[struct]]</span>
<span style="color:#a6e22e">[[switch]] [[template]] [[this]] [[thread_local]] [[throw]] [[true]] [[try]]</span>
<span style="color:#a6e22e">[[typedef]] [[typeid]] [[typename]] [[union]] [[unsigned]]</span>
<span style="color:#a6e22e">[[virtual]] [[void]] [[volatile]] [[wchar_t]] [[while]] [[xor]] [[xor_eq]]</span>
<span style="color:#75715e">// [[using]]
</span><span style="color:#75715e"></span><span style="color:#66d9ef">int</span> main() {
    std<span style="color:#f92672">::</span>cout <span style="color:#f92672">&lt;&lt;</span> <span style="color:#e6db74">&#34;Hello, World!&#34;</span> <span style="color:#f92672">&lt;&lt;</span> std<span style="color:#f92672">::</span>endl;
}
</code></pre></div><blockquote>
<p>コンパイラのバージョン
$ clang++ &ndash;version
Apple clang version 11.0.0 (clang-1100.0.33.8)
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin</p>
<p>コンパイルコマンド (C++17指定)
$ clang++ &ndash;std=c++17 hoge.cpp</p>
</blockquote>
<p>この記事から得られるものはこれ以上ないので以下は蛇足になる。</p>
<p>別件で cppreference.com の <a href="https://en.cppreference.com/w/cpp/language/identifiers">identifier のページ</a> を読んでいた時、次の文が目に止まった。</p>
<blockquote>
<ul>
<li>the identifiers that are keywords cannot be used for other purposes;
<ul>
<li>The only place they can be used as non-keywords is in an attribute-token. (e.g. [[private]] is a valid attribute) (since C++11)</li>
</ul>
</li>
</ul>
</blockquote>
<p>キーワードでも属性として指定する場合は非キーワードとして使えるらしい。
実際にやってみる。</p>
<p>同サイトの [keywords のページ] (<a href="https://en.cppreference.com/w/cpp/keyword">https://en.cppreference.com/w/cpp/keyword</a>) から一覧を拝借し、上のコードが出来上がった (C++17 においてキーワードでないものなど、一部省いている)。
大量の警告 (unknown attribute &lsquo;〇〇&rsquo; ignored) がコンパイラから出力されるが、コンパイルできる。</p>
<p>上のコードでは <code>[[using]]</code> をコメントアウトしているが、これは <code>using</code> キーワードのみ属性構文の中で意味を持つからであり、このコメントアウトを外すとコンパイルに失敗する。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-cpp" data-lang="cpp"><span style="color:#75715e">// using の例
</span><span style="color:#75715e"></span><span style="color:#a6e22e">[[using foo: attr1, attr2]] int x; // [[foo::attr1, foo::attr2]]</span> <span style="color:#960050;background-color:#1e0010">の糖衣構文</span>
</code></pre></div><p>C++17 の仕様も見てみる (正確には標準化前のドラフト)。</p>
<p>引用元: <a href="https://timsong-cpp.github.io/cppwp/n4659/dcl.attr#grammar-4">https://timsong-cpp.github.io/cppwp/n4659/dcl.attr#grammar-4</a></p>
<blockquote>
<p>If a keyword or an alternative token that satisfies the syntactic requirements of an identifier is contained in an attribute-token, it is considered an identifier.</p>
</blockquote>
<p>「<code>identifier</code> の構文上の要件を満たすキーワードまたは代替トークンが <code>attribute-token</code> に含まれている場合、<code>identifier</code> とみなされる」とある。どうやら間違いないようだ。</p>
<p>ところで、代替トークン (alternative token) とは <code>and</code> (<code>&amp;</code>) や <code>bitor</code> (<code>|</code>) などのことだが、<code>identifier</code> の構文上の要件を満たさないような代替トークンなどあるのか?
疑問に思って調べたところ、代替トークンという語にはダイグラフも含まれるらしい (参考: <a href="https://timsong-cpp.github.io/cppwp/n4659/lex.digraph">同ドラフト</a>)</p>
<ul>
<li><code>&lt;%</code> → <code>{</code></li>
<li><code>%&gt;</code> → <code>}</code></li>
<li><code>&lt;:</code> → <code>[</code></li>
<li><code>:&gt;</code> → <code>]</code></li>
<li><code>%:</code> → <code>#</code></li>
<li><code>%:%:</code> → <code>##</code></li>
</ul>
<p>「<code>identifier</code> の構文上の要件を満たさないような代替トークン」はこれらが当てはまると思われる。</p>
<p>調べた感想: 字句解析器か構文解析器が辛そう</p>
]]></description>
    </item>
    
    <item>
      <title>[Ruby] 自身を実行している処理系の種類を判定する</title>
      <link>https://blog.nsfisis.dev/posts/2021-10-02/ruby-detect-running-implementation/</link>
      <pubDate>Sat, 02 Oct 2021 09:37:50 +0900</pubDate>
      
      <guid>https://blog.nsfisis.dev/posts/2021-10-02/ruby-detect-running-implementation/</guid>
      <description><![CDATA[ <p>この記事は Qiita から移植してきたものです。
元 URL: <a href="https://qiita.com/nsfisis/items/74d7ffeeebc51b20d791">https://qiita.com/nsfisis/items/74d7ffeeebc51b20d791</a></p>
<hr>
<p>Ruby という言語には複数の実装があるが、それらをスクリプト上からどのようにして programmatically に見分ければよいだろうか。</p>
<p><code>Object</code> クラスに定義されている <code>RUBY_ENGINE</code> という定数がこの用途に使える。</p>
<p>参考: <a href="https://docs.ruby-lang.org/ja/latest/method/Object/c/RUBY_ENGINE.html">Object::RUBY_ENGINE</a></p>
<p>上記ページの例から引用する:</p>
<pre tabindex="0"><code class="language-shell-session" data-lang="shell-session">$ ruby-1.9.1 -ve 'p RUBY_ENGINE'
ruby 1.9.1p0 (2009-03-04 revision 22762) [x86_64-linux]
&quot;ruby&quot;
$ jruby -ve 'p RUBY_ENGINE'
jruby 1.2.0 (ruby 1.8.6 patchlevel 287) (2009-03-16 rev 9419) [i386-java]
&quot;jruby&quot;
</code></pre><p>それぞれの処理系がどのような値を返すかだが、stack overflow に良い質問と回答があった。</p>
<p><a href="https://stackoverflow.com/a/9894232">What values for RUBY_ENGINE correspond to which Ruby implementations?</a> より引用:</p>
<blockquote>
<table>
<thead>
<tr>
<th style="text-align:center">RUBY_ENGINE</th>
<th style="text-align:left">Implementation</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">&lt;undefined&gt;</td>
<td style="text-align:left">MRI &lt; 1.9</td>
</tr>
<tr>
<td style="text-align:center">&lsquo;ruby&rsquo;</td>
<td style="text-align:left">MRI &gt;= 1.9 or REE</td>
</tr>
<tr>
<td style="text-align:center">&lsquo;jruby&rsquo;</td>
<td style="text-align:left">JRuby</td>
</tr>
<tr>
<td style="text-align:center">&lsquo;macruby&rsquo;</td>
<td style="text-align:left">MacRuby</td>
</tr>
<tr>
<td style="text-align:center">&lsquo;rbx&rsquo;</td>
<td style="text-align:left">Rubinius</td>
</tr>
<tr>
<td style="text-align:center">&lsquo;maglev&rsquo;</td>
<td style="text-align:left">MagLev</td>
</tr>
<tr>
<td style="text-align:center">&lsquo;ironruby&rsquo;</td>
<td style="text-align:left">IronRuby</td>
</tr>
<tr>
<td style="text-align:center">&lsquo;cardinal&rsquo;</td>
<td style="text-align:left">Cardinal</td>
</tr>
</tbody>
</table>
</blockquote>
<p>なお、この質問・回答は 2014年になされたものであり、値は変わっている可能性がある。MRI (aka CRuby) については執筆時現在 (2020/12/8) も <code>'ruby'</code> が返ってくることを確認済み。</p>
<p>この表にない主要な処理系として、<a href="https://mruby.org">mruby</a> は <code>'mruby'</code> を返す。</p>
<p><a href="https://github.com/mruby/mruby/blob/ed29d74bfd95362eaeb946fcf7e865d80346b62b/include/mruby/version.h#L32-L35">mruby 該当部分のソース</a> より引用:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c"><span style="color:#75715e">/*
</span><span style="color:#75715e"> * Ruby engine.
</span><span style="color:#75715e"> */</span>
<span style="color:#75715e">#define MRUBY_RUBY_ENGINE  &#34;mruby&#34;
</span></code></pre></div>]]></description>
    </item>
    
    <item>
      <title>Vimで選択した行の順番を入れ替える</title>
      <link>https://blog.nsfisis.dev/posts/2021-10-02/vim-swap-order-of-selected-lines/</link>
      <pubDate>Sat, 02 Oct 2021 09:37:25 +0900</pubDate>
      
      <guid>https://blog.nsfisis.dev/posts/2021-10-02/vim-swap-order-of-selected-lines/</guid>
      <description><![CDATA[ <p>この記事は Qiita から移植してきたものです。
元 URL: <a href="https://qiita.com/nsfisis/items/4fefb361d9a693803520">https://qiita.com/nsfisis/items/4fefb361d9a693803520</a></p>
<hr>
<h1 id="バージョン情報">バージョン情報</h1>
<p><code>:version</code> の一部</p>
<blockquote>
<p>VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Jan 26 2020 11:30:30)
macOS version
Included patches: 1-148
Huge version without GUI.</p>
</blockquote>
<h1 id="よく紹介されている手法">よく紹介されている手法</h1>
<h2 id="tac--tail"><code>tac</code> / <code>tail</code></h2>
<p><code>tac</code> や <code>tail -r</code> などの外部コマンドを <code>!</code> を使って呼び出し、置き換える。</p>
<blockquote>
<p>:h v_!</p>
</blockquote>
<p><code>tac</code> コマンドや <code>tail</code> の <code>-r</code> オプションは環境によって利用できないことがあり、複数の環境を行き来する場合に採用しづらい</p>
<h2 id="gm0"><code>:g/^/m0</code></h2>
<p>こちらは外部コマンドに頼らず、Vim の機能のみを使う。<code>g</code> は <code>:global</code> コマンドの、<code>m</code> は <code>:move</code> コマンドの略</p>
<p><code>:global</code> コマンドは <code>:[range]global/{pattern}/[command]</code> のように使い、<code>[range]</code> で指定された範囲の行のうち、<code>{pattern}</code> で指定された検索パターンにマッチする行に対して、順番に <code>[command]</code> で指定された Ex コマンドを呼び出す。</p>
<blockquote>
<p>:h :global</p>
</blockquote>
<p><code>:move</code> コマンドは <code>[range]:move {address}</code> のように使い、<code>[range]</code> で指定された範囲の行を <code>{address}</code> で指定された位置に移動させる。</p>
<blockquote>
<p>:h :move</p>
</blockquote>
<p><code>:g/^/m0</code> のように組み合わせると、「すべての行を1行ずつ 0行目(1行目の上)に動かす」という動きをする。これは確かに行の入れ替えになっている。</p>
<p>なお、<code>:g/^/m0</code> は全ての行を入れ替えるが、<code>:N,Mg/^/mN-1</code> とすることで N行目から M行目を処理範囲とするよう拡張できる。手でこれを入力するわけにはいかないので、次のようなコマンドを用意する。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-vim" data-lang="vim"><span style="color:#a6e22e">command</span>! -<span style="color:#a6e22e">bar</span> -<span style="color:#a6e22e">range</span>=%<span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010"></span>    \ <span style="color:#a6e22e">Reverse</span><span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010"></span>    \ &lt;<span style="color:#a6e22e">line1</span>&gt;,&lt;<span style="color:#a6e22e">line2</span>&gt;<span style="color:#a6e22e">g</span><span style="color:#e6db74">/^/</span><span style="color:#a6e22e">m</span>&lt;<span style="color:#a6e22e">line1</span>&gt;<span style="color:#ae81ff">-1</span><span style="color:#960050;background-color:#1e0010">
</span></code></pre></div><p>これは望みの動作をするが、実際に実行してみると全行がハイライトされてしまう。次節で詳細を述べる。</p>
<h1 id="gm0-の問題点"><code>:g/^/m0</code> の問題点</h1>
<p><code>:global</code> コマンドは各行に対してマッチングを行う際、現在の検索パターンを上書きしてしまう。<code>^</code> は行の先頭にマッチするため、結果として全ての行がハイライトされてしまう。<code>'hlsearch'</code> オプションを無効にしている場合その限りではないが、その場合でも直前の検索パターンが失われてしまうと <code>n</code> コマンドなどの際に不便である。</p>
<blockquote>
<p>:h @/</p>
</blockquote>
<h1 id="解決策">解決策</h1>
<blockquote>
<p>[2020/9/28追記]
より簡潔な方法を見つけたので次節に追記した</p>
</blockquote>
<p>前述した <code>:Reverse</code> コマンドの定義を少し変えて、次のようにする:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-vim" data-lang="vim"><span style="color:#66d9ef">function</span>! <span style="color:#a6e22e">s</span>:<span style="color:#a6e22e">reverse_lines</span>(<span style="color:#a6e22e">from</span>, <span style="color:#a6e22e">to</span>) <span style="color:#a6e22e">abort</span><span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010"></span>    <span style="color:#a6e22e">execute</span> <span style="color:#a6e22e">printf</span>(<span style="color:#e6db74">&#34;%d,%dg/^/m%d&#34;</span>, <span style="color:#a6e22e">a</span>:<span style="color:#a6e22e">from</span>, <span style="color:#a6e22e">a</span>:<span style="color:#a6e22e">to</span>, <span style="color:#a6e22e">a</span>:<span style="color:#a6e22e">from</span> - <span style="color:#ae81ff">1</span>)<span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">endfunction</span><span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#a6e22e">command</span>! -<span style="color:#a6e22e">bar</span> -<span style="color:#a6e22e">range</span>=%<span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010"></span>    \ <span style="color:#a6e22e">Reverse</span><span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010"></span>    \ <span style="color:#a6e22e">call</span> &lt;<span style="color:#a6e22e">SID</span>&gt;<span style="color:#a6e22e">reverse_lines</span>(&lt;<span style="color:#a6e22e">line1</span>&gt;, &lt;<span style="color:#a6e22e">line2</span>&gt;)<span style="color:#960050;background-color:#1e0010">
</span></code></pre></div><p>実行しているコマンドが変わったわけではないが、関数呼び出しを経由するようにした。これだけで前述の問題が解決する。</p>
<p>この理由は、ユーザー定義関数を実行する際は検索パターンが一度保存され、実行が終了したあと復元されるため。結果として検索パターンが <code>^</code> で上書きされることがなくなる。</p>
<p>Vim のヘルプから該当箇所を引用する (強調は筆者による)。</p>
<blockquote>
<p>:h autocmd-searchpat</p>
<p><strong>Autocommands do not change the current search patterns.</strong>  Vim saves the current
search patterns before executing autocommands then restores them after the
autocommands finish.  This means that autocommands do not affect the strings
highlighted with the &lsquo;hlsearch&rsquo; option.</p>
</blockquote>
<p>これは autocommand の実行に関しての記述だが、これと同じことがユーザー定義関数の実行時にも適用される。このことは <code>:nohlsearch</code> のヘルプにある。同じく該当箇所を引用する (強調は筆者による)。</p>
<blockquote>
<p>:h :nohlsearch</p>
<p>(略) This command doesn&rsquo;t work in an autocommand, because
the highlighting state is saved and restored when
executing autocommands |autocmd-searchpat|.
<strong>Same thing for when invoking a user function.</strong></p>
</blockquote>
<p>この仕様により、<code>:g/^/m0</code> の呼び出しをユーザー定義関数に切り出すことで上述の問題を解決できる。</p>
<h1 id="解決策-改訂版">解決策 (改訂版)</h1>
<blockquote>
<p>[2020/9/28追記]
より簡潔な方法を見つけたため追記する</p>
</blockquote>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-vim" data-lang="vim"><span style="color:#a6e22e">command</span>! -<span style="color:#a6e22e">bar</span> -<span style="color:#a6e22e">range</span>=%<span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010"></span>    \ <span style="color:#a6e22e">Reverse</span><span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010"></span>    \ <span style="color:#a6e22e">keeppatterns</span> &lt;<span style="color:#a6e22e">line1</span>&gt;,&lt;<span style="color:#a6e22e">line2</span>&gt;<span style="color:#a6e22e">g</span><span style="color:#e6db74">/^/</span><span style="color:#a6e22e">m</span>&lt;<span style="color:#a6e22e">line1</span>&gt;<span style="color:#ae81ff">-1</span><span style="color:#960050;background-color:#1e0010">
</span></code></pre></div><p>まさにこのための Exコマンド、<code>:keeppatterns</code> が存在する。<code>:keeppatterns {command}</code> のように使い、読んで字の如く、後ろに続く Exコマンドを「現在の検索パターンを保ったまま」実行する。はるかに分かりやすく意図を表現できる。</p>
<blockquote>
<p>:h :keeppatterns</p>
</blockquote>
<h1 id="コピペ用再掲">コピペ用再掲</h1>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-vim" data-lang="vim"><span style="color:#75715e">&#34; License: Public Domain</span><span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#a6e22e">command</span>! -<span style="color:#a6e22e">bar</span> -<span style="color:#a6e22e">range</span>=%<span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010"></span>    \ <span style="color:#a6e22e">Reverse</span><span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010"></span>    \ <span style="color:#a6e22e">keeppatterns</span> &lt;<span style="color:#a6e22e">line1</span>&gt;,&lt;<span style="color:#a6e22e">line2</span>&gt;<span style="color:#a6e22e">g</span><span style="color:#e6db74">/^/</span><span style="color:#a6e22e">m</span>&lt;<span style="color:#a6e22e">line1</span>&gt;<span style="color:#ae81ff">-1</span><span style="color:#960050;background-color:#1e0010">
</span></code></pre></div>]]></description>
    </item>
    
    <item>
      <title>[Vim] autocmd events の BufWrite/BufWritePre の違い</title>
      <link>https://blog.nsfisis.dev/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/</link>
      <pubDate>Sat, 02 Oct 2021 09:37:12 +0900</pubDate>
      
      <guid>https://blog.nsfisis.dev/posts/2021-10-02/vim-difference-between-autocmd-bufwrite-and-bufwritepre/</guid>
      <description><![CDATA[ <p>この記事は Qiita から移植してきたものです。
元 URL: <a href="https://qiita.com/nsfisis/items/79ab4db8564032de0b25">https://qiita.com/nsfisis/items/79ab4db8564032de0b25</a></p>
<hr>
<h1 id="tl-dr">TL; DR</h1>
<p>違いはない。ただのエイリアス。</p>
<h1 id="調査記録">調査記録</h1>
<p>Vim の autocmd events には似通った名前のものがいくつかある。大抵は <code>:help</code> に説明があるが、この記事のタイトルにある2つを含めた以下のイベントには、その違いについて説明がない。</p>
<ul>
<li><code>BufRead</code>/<code>BufReadPost</code></li>
<li><code>BufWrite</code>/<code>BufWritePre</code></li>
<li><code>BufAdd</code>/<code>BufCreate</code></li>
</ul>
<p>このうち、<code>BufAdd</code>/<code>BufCreate</code> に関しては、<code>:help BufCreate</code> に</p>
<blockquote>
<p>The BufCreate event is for historic reasons.</p>
</blockquote>
<p>とあり、おそらくは <code>BufAdd</code> のエイリアスであろうということがわかる。他の2組も同様ではないかと予想されるが、確認のため vim と neovim のソースコードを調査した。</p>
<blockquote>
<p>ソースコードへのリンク
<a href="https://github.com/vim/vim/tree/8e6be34338f13a6a625f19bcef82019c9adc65f2">vim (調査時点での master branch)</a>
<a href="https://github.com/neovim/neovim/tree/71d4f5851f068eeb432af34850dddda8cc1c71e3">neovim (上に同じ)</a></p>
</blockquote>
<h2 id="vim-のソースコード">vim のソースコード</h2>
<p>以下は、autocmd events の名前と内部で使われている整数値とのマッピングを定義している箇所である。見ての通り、上でエイリアスではないかと述べた3組には、それぞれ同じ内部値が使われている。</p>
<p><a href="https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L85-L86">https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L85-L86</a></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c">    {<span style="color:#e6db74">&#34;BufAdd&#34;</span>,		EVENT_BUFADD},
    {<span style="color:#e6db74">&#34;BufCreate&#34;</span>,	EVENT_BUFADD},
</code></pre></div><p><a href="https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L95-L97">https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L95-L97</a></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c">    {<span style="color:#e6db74">&#34;BufRead&#34;</span>,		EVENT_BUFREADPOST},
    {<span style="color:#e6db74">&#34;BufReadCmd&#34;</span>,	EVENT_BUFREADCMD},
    {<span style="color:#e6db74">&#34;BufReadPost&#34;</span>,	EVENT_BUFREADPOST},
</code></pre></div><p><a href="https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L103-L105">https://github.com/vim/vim/blob/8e6be34338f13a6a625f19bcef82019c9adc65f2/src/autocmd.c#L103-L105</a></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-c" data-lang="c">    {<span style="color:#e6db74">&#34;BufWrite&#34;</span>,	EVENT_BUFWRITEPRE},
    {<span style="color:#e6db74">&#34;BufWritePost&#34;</span>,	EVENT_BUFWRITEPOST},
    {<span style="color:#e6db74">&#34;BufWritePre&#34;</span>,	EVENT_BUFWRITEPRE},
</code></pre></div><h2 id="neovim-のソースコード">neovim のソースコード</h2>
<p>neovim の場合でも同様のマッピングが定義されているが、こちらの場合は Lua で書かれている。以下にある通り、はっきり <code>aliases</code> と書かれている。</p>
<p><a href="https://github.com/neovim/neovim/blob/71d4f5851f068eeb432af34850dddda8cc1c71e3/src/nvim/auevents.lua#L119-L124">https://github.com/neovim/neovim/blob/71d4f5851f068eeb432af34850dddda8cc1c71e3/src/nvim/auevents.lua#L119-L124</a></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-lua" data-lang="lua">  aliases <span style="color:#f92672">=</span> {
    BufCreate <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;BufAdd&#39;</span>,
    BufRead <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;BufReadPost&#39;</span>,
    BufWrite <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;BufWritePre&#39;</span>,
    FileEncoding <span style="color:#f92672">=</span> <span style="color:#e6db74">&#39;EncodingChanged&#39;</span>,
  },
</code></pre></div><p>ところで、上では取り上げなかった <code>FileEncoding</code> だが、これは <code>:help FileEncoding</code> にしっかりと書いてある。</p>
<pre tabindex="0"><code>                                                           *FileEncoding*
FileEncoding                    Obsolete.  It still works and is equivalent
                                to |EncodingChanged|.
</code></pre><h2 id="まとめ">まとめ</h2>
<p>記事タイトルについて言えば、どちらも変わらないので好きな方を使えばよい。あえて言えば、次のようになるだろう。</p>
<ul>
<li><code>BufAdd</code>/<code>BufCreate</code>
<ul>
<li>→ <code>BufCreate</code> は歴史的な理由により (&ldquo;for historic reasons&rdquo;) 存在しているため、新しい方 (<code>BufAdd</code>) を使う</li>
</ul>
</li>
<li><code>BufRead</code>/<code>BufReadPost</code>
<ul>
<li>→ <code>BufReadPre</code> との対称性のため、あるいは <code>BufWritePost</code> との対称性のため <code>BufReadPost</code> を使う</li>
</ul>
</li>
<li><code>BufWrite</code>/<code>BufWritePre</code>
<ul>
<li>→ <code>BufWritePost</code> との対称性のため、あるいは <code>BufReadPre</code> との対称性のため <code>BufWritePre</code> を使う</li>
</ul>
</li>
<li><code>FileEncoding</code>/<code>EncodingChanged</code>
<ul>
<li>→ <code>FileEncoding</code> は &ldquo;Obsolete&rdquo; と明言されているので、<code>EncodingChanged</code> を使う</li>
</ul>
</li>
</ul>
<p>ところでこの調査で知ったのだが、<code>BufRead</code> と <code>BufWrite</code> は上にある通り発火するタイミングが「後」と「前」で対称性がない。可能なら <code>Pre</code>/<code>Post</code> 付きのものを使った方が分かりやすいだろう。</p>
]]></description>
    </item>
    
    <item>
      <title>[Python] クロージャとUnboundLocalError: local variable &#39;x&#39; referenced before assignment</title>
      <link>https://blog.nsfisis.dev/posts/2021-10-02/python-unbound-local-error/</link>
      <pubDate>Sat, 02 Oct 2021 09:32:37 +0900</pubDate>
      
      <guid>https://blog.nsfisis.dev/posts/2021-10-02/python-unbound-local-error/</guid>
      <description><![CDATA[ <p>この記事は Qiita から移植してきたものです。
元 URL: <a href="https://qiita.com/nsfisis/items/5d733703afcb35bbf399">https://qiita.com/nsfisis/items/5d733703afcb35bbf399</a></p>
<hr>
<p>本記事は Python 3.7.6 の動作結果を元にして書かれている。</p>
<p>Python でクロージャを作ろうと、次のようなコードを書いた。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">f</span>():
    x <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>
    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">g</span>():
        x <span style="color:#f92672">+=</span> <span style="color:#ae81ff">1</span>
    g()

f()
</code></pre></div><p>関数 <code>g</code> から 関数 <code>f</code> のスコープ内で定義された変数 <code>x</code> を参照し、それに 1 を足そうとしている。
これを実行すると <code>x += 1</code> の箇所でエラーが発生する。</p>
<blockquote>
<p>UnboundLocalError: local variable &lsquo;x&rsquo; referenced before assignment</p>
</blockquote>
<p>local変数 <code>x</code> が代入前に参照された、とある。これは、<code>f</code> の <code>x</code> を参照するのではなく、新しく別の変数を <code>g</code> 内に作ってしまっているため。
前述のコードを宣言と代入を便宜上分けて書き直すと次のようになる。<code>var</code> を変数宣言のための構文として擬似的に利用している。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#75715e"># 注: var は正しい Python の文法ではない。上記参照のこと</span>
<span style="color:#66d9ef">def</span> <span style="color:#a6e22e">f</span>():
    var x           <span style="color:#75715e">#  f の local変数 &#39;x&#39; を宣言</span>
    x <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>           <span style="color:#75715e">#  x に 0 を代入</span>
    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">g</span>():        <span style="color:#75715e">#  f の内部関数 g を定義</span>
        var x       <span style="color:#75715e">#  g の local変数 &#39;x&#39; を宣言</span>
                    <span style="color:#75715e">#  たまたま f にも同じ名前の変数があるが、それとは別の変数</span>
        x <span style="color:#f92672">+=</span> <span style="color:#ae81ff">1</span>      <span style="color:#75715e">#  x に 1 を加算 (x = x + 1 の糖衣構文)</span>
                    <span style="color:#75715e">#  加算する前の値を参照しようとするが、まだ代入されていないためエラー</span>
    g()
</code></pre></div><p>当初の意図を表現するには、次のように書けばよい。</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-python" data-lang="python"><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">f</span>():
    x <span style="color:#f92672">=</span> <span style="color:#ae81ff">0</span>
    <span style="color:#66d9ef">def</span> <span style="color:#a6e22e">g</span>():
        <span style="color:#66d9ef">nonlocal</span> x   <span style="color:#75715e">## (*)</span>
        x <span style="color:#f92672">+=</span> <span style="color:#ae81ff">1</span>
    g()
</code></pre></div><p><code>(*)</code> のように、<code>nonlocal</code> を追加する。これにより一つ外側のスコープ (<code>g</code> の一つ外側 = <code>f</code>) で定義されている <code>x</code> を探しに行くようになる。</p>
]]></description>
    </item>
    
    <item>
      <title>PHPerKaigi 2021</title>
      <link>https://blog.nsfisis.dev/posts/2021-03-30/phperkaigi-2021/</link>
      <pubDate>Tue, 30 Mar 2021 23:22:40 +0900</pubDate>
      
      <guid>https://blog.nsfisis.dev/posts/2021-03-30/phperkaigi-2021/</guid>
      <description><![CDATA[ <h1 id="phperkaigi-2021-参加レポ">PHPerKaigi 2021 参加レポ</h1>
<p>2021-03-26 から 2021-03-28 にかけて開催された、<a href="https://phperkaigi.jp/2021/">PHPerKaigi 2021</a> に一般参加者として参加した。
弊社<a href="https://www.dgcircus.com/">デジタルサーカス株式会社</a> (今年1月から勤務) はダイヤモンドスポンサーとなっており、スポンサー枠のチケットを使わせていただいた。</p>
<p>このようなカンファレンスには初めて参加するのでかねてより心待ちにしていたのだが、生憎2日目から体調を崩してしまい、この記事も途中までとなっている。まだ見ていないセッションも多いが、ひとまず現時点での参加レポを書いておく。</p>
<p>発表はトラック A、B に分かれていたのだが、今回はすべて A トラックを視聴している (切り替えるのが面倒だっただけ)。</p>
<h2 id="凡例">凡例</h2>
<blockquote>
<p>発表・スライドのメモ (引用ではない)</p>
</blockquote>
<p>感想など</p>
<h2 id="day-0-前夜祭-20210327">Day 0 前夜祭 (2021/03/27)</h2>
<h3 id="1730-a">17:30 [A]</h3>
<p>PHP で AWS Lambda</p>
<blockquote>
<p>Rails のプロジェクトを PHPer のメンバのみでメンテ
→他のメンバもわかる PHP にリプレースを検討</p>
<p>サーバレス</p>
<ul>
<li>サーバ・インフラの管理が不要</li>
<li>アプリケーションコードの知識だけで保守可能</li>
</ul>
<p>ゼロベースで作れる案件が (Railsの件とは別に) あるため、そちらで試験的に導入?</p>
<p>AWSの学習
AWS のドキュメント
DevelopersIO</p>
<p>AWS Lambda のカスタムランタイムで PHP を動かす</p>
<p>サーバのセットアップや維持管理を気にしなくて良い
サーバーレスで PHP を動かすツールがすでにある
サーバーレス構築はすんなり</p>
<p>今は Laravel がルーティングしている
Laravel Livewire を Lambda に載せられないか?
デプロイ方法は?
バッチ処理は? (Lambda は 15分の制限)</p>
<p>Lambda でコンテナイメージがサポートされるように</p>
<p>抽象化されたもの「だけ」しか知らないよりも具象の理解は助けになる</p>
</blockquote>
<p>AWS Lambda のような Function as a Service はマイクロサービス化における一つの到達点に思えるのだが、これを使って実際に web サービスを作る具体的なイメージがまだ見えない (注: すべて for me として書いている)。</p>
<p>PHP on AWS Lambda があれだけ簡単に動かせるのには驚いた。</p>
<p>勝手に AWS Lambda だとフットプリントの軽さが求められそう (= PHP + Laravel などでは動かなさそう) だという先入観を持っていたのだが、この発表のデモによればそうでもないらしい。</p>
<h3 id="1810-a">18:10 [A]</h3>
<p>大規模サイトの SEO</p>
<blockquote>
<p>大規模サイト (100万ページ以上)
Google の基準</p>
<p>クロールバジェットを意識したSEO</p>
<p>大規模サイトでコンテンツが中頻度 (1回/週) で更新 OR 中規模サイト (10,000以上) でコンテンツが目まぐるしく変更される
これを満たさないなら、クロールバジェットを考えなくてもいい</p>
<p>サーチコンソール
「カバレッジ」の「除外」
多すぎるのは問題→クロールバジェットを浪費している</p>
<ul>
<li>クエリの順番を決める</li>
<li>空の値のルールを決めておく</li>
<li>リダイレクトすればインデックスはうまくいく</li>
<li>リンクが存在する限りクロールはされる</li>
</ul>
<p>リニューアル前のURL</p>
<p>インデックスは移行される
リンクのURLが存在する限り、別のURLとしてクロールされる
リダイレクトされるとはいえ、リニューアル前のURLは移行した方が良い
リニューアルで無視されるようになったパラメータも注意</p>
<p>robotes.txt で拒否しているのにクロールされる
一時的に拒否を外して 404 や 301 を読ませる
内部リンクを確認する
JS でのリンクに書き換え</p>
<p>クエリパラメータからURLのパスに
<code>/tokyo?area=HOGE</code> → <code>/tokyo/HOGE</code></p>
<p>URL 設計だいじ</p>
</blockquote>
<p>SEO (Search Engine Optimization) は大して知らないので新鮮な話が多かった。その分語れることも少ない……。</p>
<h3 id="1850-a">18:50 [A]</h3>
<blockquote>
<p>知覚可能
操作可能
理解可能
堅牢 ちゃんとしたHTMLを書く (閉じタグ・入れ子構造など)</p>
<ul>
<li>
<p>標準の HTML を適切に使う</p>
</li>
<li>
<p>WAI-ARIA</p>
</li>
<li>
<p>キーボードフレンドリー</p>
</li>
<li>
<p>マシンフレンドリー</p>
</li>
<li>
<p>SEOフレンドリー</p>
</li>
</ul>
<p>button タグ
→キーボード
h1 タグ
→スクリーンリーダー・クローラ
a タグ</p>
<p>WAI-ARIA
HTML では表現できないセマンティクスを追加する</p>
<ul>
<li>ロール
<ul>
<li>何をするのか?</li>
<li>ユーザーアクションによって変化しない</li>
</ul>
</li>
<li>プロパティ
<ul>
<li>関連づけられたデータ</li>
</ul>
</li>
<li>ステート
<ul>
<li>現在の状態</li>
</ul>
</li>
</ul>
<p>まずは標準の HTML 要素で解決する
何でもかんでも WAI-ARIA を使えばいいというものではない</p>
<p>マウスホバーでツールチップが出てくるが、キーボード操作では出てこない</p>
<p>VoiceOver</p>
<p>全ての属性を使う必要はない
あくまでアクセシビリティを上げるための方法の一つにすぎない</p>
</blockquote>
<p>つい最近 WAI-ARIA についての記事を読んだばかりだったので個人的にタイムリーな話題だった。(あまりこの言葉を使いたくないのだが) いわゆる「健常者」にとって、こうした問題を普段の生活の中で意識するのは難しい。だからこそ情報へのアンテナは張っておくようにしたい。</p>
<h3 id="1930-a">19:30 [A]</h3>
<p>PHP で FUSE</p>
<p>個人的に楽しみだった発表。</p>
<blockquote>
<p>VFS (virtual filesystem) vs 具体的なファイルシステム</p>
<p>最適な実装方法は状況により異なる</p>
<p>アプリケーションに見せるAPIは変えずに実装を隠蔽する→VFS</p>
<p>カーネルのプログラムを作るのは難しい</p>
<ul>
<li>権限がデカすぎる</li>
<li>システム全体がクラッシュ</li>
<li>セキュリティリスク</li>
<li>開発サイクルを回しづらい</li>
<li>ネイティブコードにコンパイルされる言語である必要がある</li>
</ul>
<p>Filesystem in USEr space (FUSE)</p>
<ul>
<li>特定の C の関数を呼ぶことで filesystem が作れる</li>
<li>FFI を持つ言語なら FUSE が使える</li>
</ul>
<p>SSHFS / s3fs / Docker Desktop</p>
<p>Linux 以外でも使える</p>
<ul>
<li>dokany (on Windows)</li>
<li>osxfuse</li>
</ul>
<p>VFS: システムコールが呼ばれると、ファイルシステムによってコール
FUSE: カーネル空間からユーザ空間へ通信</p>
<p>高レベルなラッパで型をつける</p>
<p>PHP 以外では Wordpress を FUSE にマウントする実装がある (C, Python など)</p>
<ul>
<li>grep できる</li>
<li>sed できる</li>
<li>編集できる</li>
</ul>
</blockquote>
<p>期待通りの興味深い発表だった。FUSE 自体も今回の発表で知ったのだが、これ本体の実装を見るのも面白そうだ。
この発表を聞きながらファイルシステムにマウントできそうなものを考えていたのだが、およそ木構造をしているものすべてと言えそうだ (ハンマーしか持っていないと云々)。何かできそうだがなかなか思いつかない。</p>
<h2 id="day-1-20210327">Day 1 (2021/03/27)</h2>
<h3 id="1050-a">10:50 [A]</h3>
<p>ATDD</p>
<blockquote>
<ul>
<li>ユーザーストーリー</li>
<li>ユニットテスト</li>
<li>CI/CD</li>
</ul>
<p>ユーザストーリーの受け入れ条件が曖昧になりがち
デグレチェックがユニットレベルでは収まらない場合、手動で同じシナリオをテストしている</p>
<p>Q2の強化
アジャイルテストの4象限</p>
<p>技術面/ビジネス面
開発チーム支援(コーディング前・コーディング中)/製品批評(コーディング後)</p>
<ul>
<li>Q1: 技術面 &amp; チーム支援
<ul>
<li>TDD</li>
<li>ユニットテストなど</li>
</ul>
</li>
<li>Q2: ビジネス面 &amp; チーム支援
<ul>
<li>ATDD</li>
<li>ビジネス面の受け入れテストで駆動する</li>
</ul>
</li>
</ul>
<p>Agile Alliance
ユーザストーリーのスキルレベルを高める</p>
<p>テストピラミッド</p>
<ul>
<li>
<p>UI Tests</p>
</li>
<li>
<p>Service Tests</p>
</li>
<li>
<p>Unit Tests</p>
</li>
<li>
<p>異なる粒度のテストを書く</p>
</li>
<li>
<p>高レベルになるほど、持つべきテストは少なくなる</p>
<ul>
<li>ピラミッド型になる</li>
</ul>
</li>
</ul>
<p>高レベルテストが多すぎる→アイスクリームコーン アンチパターン</p>
<p>ATDD (Acceptance TDD)
API経由・UI経由での高レベルテスト E2E test</p>
<p>ストーリ受け入れテスト</p>
<p>入れ子のフィードバックループ
ATDD(外側) と TDD(内側)</p>
<p>外部品質・内部品質</p>
<p>バーティカルスライスのデリバリー</p>
<ul>
<li>cucumber</li>
<li>gauge</li>
<li>behat</li>
</ul>
<p>ユビキタス言語
手動テストもspecに書く
自動化は可能だがコスパが悪い
失敗することがわかっているテスト(レッドテスト)はCIから外す
失敗時の原因究明が難しい
饒舌なエラーメッセージ
状況のスナップショット</p>
<p>Continuous Testing</p>
</blockquote>
<p>User Acceptance Test (UAT) くらいの規模になると個人開発・趣味開発では触れない領域なので、大いに勉強になった。スライドに添付されている資料が相当に充実していたので、これを読むのが本番といった様相すら感じる。
高レベルテストの自動化は現在のプロジェクトでも感じており、自動化のチャンスは伺っている。とはいえセッションでも指摘されているように自動化することにコストがかかりすぎる領域があるのも事実で、そのバランスが難しい。</p>
<h3 id="1150-a">11:50 [A]</h3>
<p>型解析を用いたリファクタリング</p>
<p>型のある世界で生きてきた身として大いに楽しみにしていた発表。</p>
<blockquote>
<ul>
<li>PHPStan</li>
<li>Phan</li>
<li>Psalm</li>
</ul>
<p>autoload も認識できる
bootstrapFiles</p>
<p>編集箇所と利用箇所を CI でチェック
ルールレベルを徐々に引き上げていく
警告が多すぎると見落としてしまう・無視されやすくなる</p>
<p>型がついていないことによるエラーが多い</p>
<p>型よりも詳細な検査 <code>Util_Assert::min</code></p>
<p>SQL を静的解析
placeholder の型付け</p>
<p>警告レベルを低いレベルから導入
タイプヒントを積極的に書いていく
PHPStan の拡張を追加する</p>
</blockquote>
<p>昨今、動的型付き言語での型宣言・型アノテーション・型ヒントの導入が相次いでいる。長らく静的型付き言語を書いてきた私からすると、ようやく気づいたかといったところだが、ともかく型を導入する言語が増えてきた。
今のプロジェクトでも新しく追加するコードには型をつけるよう努めているが、どうしても古いコードには型がついていない。個人的には型のないコードに対してどう型を自動的に付けるかという点に興味があり、その点で Ruby の typeprof には注目している。</p>
<h3 id="1230-a">12:30 [A]</h3>
<p>昼食をとっていた。事前に何か食料を買っておくべきだった。</p>
<h3 id="1310-a">13:10 [A]</h3>
<p>Documentation as Code</p>
<p>この発表も以前から非常に楽しみにしていた。</p>
<blockquote>
<p>開発開始までのオーバーヘッド
新規にチームにジョイン
担当範囲外の機能を理解
オンボーディングのコスト</p>
<p>PHPerKaigi 2020 で発表あり</p>
<p>継続的にシステムの理解を助けるドキュメント</p>
<p>継続的ドキュメンテーション
システムとドキュメントの乖離</p>
<p>書いてあることが間違っている・足りない</p>
<ul>
<li>徐々にずれていく</li>
<li>システムの更新タイミングとドキュメントの更新タイミングに差がある</li>
</ul>
<p>システムとドキュメントは対応関係がある</p>
<ul>
<li>間違ったドキュメント</li>
<li>存在しないドキュメント</li>
</ul>
<p>システムとドキュメントの乖離を定量化する
継続的に
システムの更新に近いタイミングで ドキュメントを更新し続ける</p>
<p>Documentation as Code</p>
<p>コードと同じツールでドキュメントを書く</p>
<ul>
<li>issue tracker</li>
<li>vcs</li>
<li>plain text markup</li>
<li>automation</li>
</ul>
<p>開発者
システム
ドキュメント
構造化データ
ソフトウェア</p>
<p>システムから構造化データを抽出する
PHPDoc
OpenAPI</p>
<p>ビュー 関心ごとに合わせてアーキテクチャを一つ以上の側面(断面)で説明する</p>
<p>ビューの単位でドキュメントに</p>
<p>スタックトレースからのドキュメント生成</p>
</blockquote>
<p>ドキュメントの管理は現プロジェクトでも課題と感じている。作られた当初は正しくても、実態と乖離していくのを止めるのは困難を極める。全体的に興味深い発表だったが、特にスタックトレースからのドキュメント生成というアイデアに惹かれるものを感じた。スタックトレースという実態と不可分な (乖離しない) 情報を起点にするのは理にかなっている。問題はトレースをいつ、どう取るかだろうか。それを自動化しなければ、実態との乖離が避けられないだろう。</p>
<h3 id="1410-a">14:10 [A]</h3>
<p>cookie による session 管理</p>
<p>全体的に基本的な話だったので特に触れない。Cookie やセッションの話としては非常に分かりやすくまとめられていたので、知らない人が学ぶにはいい教材だろう。</p>
<h3 id="1450-a">14:50 [A]</h3>
<p>PHP のエラーと例外</p>
<blockquote>
<p>エラー PHPエンジンがエラーを通知する
例外 プログラムが投げる</p>
<p>PHP7-8とエラー</p>
<p>PHPエンジンのエラーの一部が \Error に変換されるようになった
→ try-catch で捕捉できる</p>
<p>\Error は例外とは異なる</p>
<p>PHP8 でエラーレベルの引き上げ</p>
<ul>
<li>捕捉すべきもの
<ul>
<li>recoverable</li>
</ul>
</li>
<li>捕捉すべきでないもの
<ul>
<li>unrecoverable</li>
<li>開発時に対処できるもの</li>
</ul>
</li>
</ul>
<p>例外</p>
<ul>
<li>捕捉して事後処理</li>
<li>捕捉せず(or 捕捉した上で)さらに上に是非を問う</li>
</ul>
<p>開発段階で例外を把握し、ハンドリングを考えておく</p>
<p>\Throwable  \Exception と \Error</p>
<p>\Error はキャッチすべきでない</p>
<ul>
<li>
<p>\Error</p>
<ul>
<li>本番で起きてはいけない</li>
</ul>
</li>
<li>
<p>\LogicException</p>
<ul>
<li>本番で起きてはいけない
→生じないのだから捕捉もしない</li>
</ul>
</li>
<li>
<p>\RuntimeException</p>
<ul>
<li>起こるかもしれないので本番環境でも考慮する</li>
</ul>
</li>
</ul>
<p>捕捉して対応するのではなく、未然に防ぐ</p>
<p>独自例外を使う
\Exception を投げてしまうと、
catch (\Exception)せざるを得ない
→catch 範囲が広すぎる</p>
<p>SPL の例外を使う</p>
<p>例外翻訳
上位のレイヤが下位のレイヤの例外を捕捉し、上位レイヤのAPIに「翻訳」する
下位レイヤの知識に依存させない</p>
<p>@throws
捕捉してほしい例外を書き連ねておく</p>
<p>呼び出しもとに負わせたい責任</p>
</blockquote>
<p>PHP を学んでいる途中の私としては、今まさに聞きたい発表だった (現時点で PHP を書き始めてから 4ヶ月ほどになる)。</p>
<p>個人的に例外やエラーを最もうまく扱っているのは Go、Swift、Rust、Haskell などのエラーを「値として」扱う言語だと思っている。try-catch は通常の処理フローを完全に壊してしまう上、構文としても重すぎる。値としてのエラー通知は C言語時代への回帰ともいえるが、その頃と異なるのはエラーを暗黙のうちに握り潰すことがないということだ。これらの言語は型を持っており、静的に検証ができる (C のそれはまともな型付けではない。念のため)。</p>
<p>PHP のように、すでに例外が言語システムに根ざしている言語ではどうすればよいか。この場合も同じく静的検証の力を借りることになるだろう。</p>
<h3 id="1530-a">15:30 [A]</h3>
<p>Laravel のメール認証</p>
<p>Laravel の知識がない私にはまったくついていけなかった。また、個人的にタイトルがややミスリーディングに感じた。</p>
<h3 id="1610-a">16:10 [A]</h3>
<p>gRPC</p>
<blockquote>
<p>Unary RPCs
Server streaming RPCs
Client streaming RPCs
Bidirectional streaming RPCs</p>
<p>Protobuf</p>
<p>実装とAPIが乖離しにくい
自動生成
複数言語でも相互に使える</p>
<p>マイクロサービスのサービス通信
スマホアプリ
ゲームサーバ</p>
<p>PHP では?</p>
<p>PHP ではストリーミングが難しい
リクエストごとにプロセスが使い捨て</p>
<p>PHP ではgRPCのクライアントしか対応していない</p>
<p>gRPC-Web
ブラウザで扱うためのJSライブラリ+プロトコル</p>
<p>HTTP/1.1 でも使える
Unary RPC と Server streaming RPC のみ</p>
<p>Envoy
Nginx などで相互に gRPC と gRPC-Web で変換</p>
<p>Amp
イベント駆動な並行処理のフレームワーク</p>
<p>HTTP/2 対応</p>
<p>C#のgRPC-Webが楽</p>
</blockquote>
<p>(発表の中でもまさに同じことをおっしゃっていたが) PHP 以外の方が向いているだろう、というのが第一の感想である。gRPC はそれ自体というよりも Protobuf というエコシステムに乗れることのメリットが大きいと感じる。そのエコシステムにうまく乗れない時点で、うーんという感じ。</p>
<h3 id="1650-a">16:50 [A]</h3>
<p>アーキテクチャテスト</p>
<blockquote>
<p>Independent Core Layer Pattern</p>
<p>開発初期のアーキテクチャが崩れる
アーキテクチャ観点のコードレビューができない</p>
<p>どこにクラスを置けばよいか?
ドキュメントがない</p>
<p>アーキテクチャ設計に関する知識が属人化・暗黙知化</p>
<p>ガイドライン</p>
<ul>
<li>最初にルールを決めるのは簡単</li>
<li>ルール通り作り始めるのも簡単
<ul>
<li>→維持するのが難しい、人が決めたものゆえ壊れやすい</li>
</ul>
</li>
</ul>
<p>PHP の特性</p>
<ul>
<li>クラスは public</li>
<li>可視性の制御が public / protected / private のみ</li>
<li>依存関係の制御が困難</li>
</ul>
<p>アーキテクチャテスト
クラスの依存関係や実装ルールをコードとして表現し、自動テスト化する</p>
<ul>
<li>deptrac</li>
<li>phpat</li>
</ul>
<p>Independent Core Layer Pattern</p>
<p>アーキテクチャテストの失敗</p>
<ul>
<li>実装誤り</li>
<li>or アーキテクチャが適切でない
<ul>
<li>開発の過程でフィードバックしていく</li>
</ul>
</li>
</ul>
<p>モジュラーモノリス→マイクロサービスへ</p>
</blockquote>
<h2 id="day-2-20210328">Day 2 (2021/03/28)</h2>
<p>冒頭に書いた通り、2日目から体調が悪くまともに聴けていない。途中までは頭痛を我慢しつつ見ていたのだが、まともに入ってこなかった。</p>
<p>残念ではあるが、いずれにせよ見られていない発表は他にもあるので、今週末にでもまとめて見ようと思う。</p>
<h2 id="全体の感想">全体の感想</h2>
<p>Day 2 にほとんど参加できなかったのは残念だが、イベント自体は大変楽しく、また興味深いものであった。自分がまったく知らない領域の話を聞けるのはこうしたイベントならではだと感じる。オンライン開催ゆえ現地に行く必要がなく、気軽に参加できたのも (特に初参加者として) 嬉しいポイントだった。</p>
<p>今回、雑談/登壇者への質問等向けに Discord サーバもあったのだが、こちらは参加こそしたものの ROM のままになってしまった。発表に1ウィンドウ、メモを書くのに1ウィンドウ、Discord 表示に 1ウィンドウで私にはもう脳のリソースとディスプレイのスペースが追いつかなかった (さらにいうと Zoom でアンカンファレンスもやっていたようだ。こちらはまったく参加していない)。</p>
<p>1つ個人的な反省点としては、一つ一つのセッションを真剣に聞き過ぎたというものがある。もっと適当に聞いておけばよかった。これだけだと大変語弊があるのだが、言い方を変えると、Discord しかりアンカンファレンスしかり「このイベントのこの瞬間にしかないコンテンツ」に触れずに、後から見返せる発表やスライドに注力してしまった、ということだ。発表の詳細な見直しはあとからできるのだから、今しかできないことを考えるべきだった。
まあ初カンファレンスだし、とお茶を濁しておこう。</p>
<p>さて、カンファレンスで一つ気になったことがある。それは、Discord という書き込み場所が増えたことでニコ生のコメントの流量が吸い取られてしまったのではないか、という点だ。ニコニコだけ見ていると過疎っているかのように見えた発表も、Discord の方では盛り上がっている、というのを何度か見かけた。ニコニコのコメント方式は盛り上がりを如実に反映するが、逆もまたしかり。Discord があったこと自体はプラスだったと思うが、この点はマイナスだったのではないかと感じる。</p>
<hr>
<p>最後になりましたが、毎年の PHPerKaigi 開催にご尽力されている皆様、スピーカーの皆様、楽しい3日間でした。ありがとうございました!
(ずっと常体で書いてしまったのでいきなり仏頂面から笑顔になったようで気持ち悪い)</p>
<p>ではまた来年。</p>
]]></description>
    </item>
    
    <item>
      <title>My First Post</title>
      <link>https://blog.nsfisis.dev/posts/2021-03-05/my-first-post/</link>
      <pubDate>Fri, 05 Mar 2021 23:38:21 +0900</pubDate>
      
      <guid>https://blog.nsfisis.dev/posts/2021-03-05/my-first-post/</guid>
      <description><![CDATA[ <h1 id="test">Test</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
]]></description>
    </item>
    
  </channel>
</rss>