Upgrade to Pro — share decks privately, control downloads, hide ads and more …

至極の難問言語仕様クイズ 〜最強のマルチリンガル決定戦〜

至極の難問言語仕様クイズ 〜最強のマルチリンガル決定戦〜

PIXIVDEVMEETUPの前夜祭的な企画で開催したエンジニアクイズ大会のスライドです

7c8a8c1fdd7ecbbd8ed01d2061f38a4c?s=128

orekyuu

May 21, 2021
Tweet

Transcript

  1. 至極の難問言語仕様クイズ 〜最強のマルチリンガル決定戦〜 2021.5.6

  2. 至極の難問言語仕様クイズとは • YAML / PHP / Ruby / JavaScript /

    Java の5言語から4択クイズを出題 ◦ バージョンが明記されてなければ最新の実装で動くものと思ってください • 最も正答率の高かった人が複数のプログラミング言語を極めし 王者! • 最強のマルチリンガルには、王者にふさわしい豪華景品を用意しています
  3. 景品1 最強のマルチリンガルRoleを付与 目立つこと間違いなし!!!

  4. 景品2 重箱の隅をつつく人をモチーフ にした「多言語王トロフィー」 ※複数名優勝の場合は抽選 1名

  5. ルール説明

  6. フォームでご回答ください

  7. 󰢄 禁止事項 • irbやdevconsoleなどで実行して動作確認しないでください • ぐぐらないでください • 答えが出てからフォームに回答しないでください • #エンジニアクイズ大会

    に正解に近づくヒント、もしくは解答を 書かないでください • 正々堂々最強のエンジニアになりましょう
  8. 󰢐 推奨事項 • #エンジニアクイズ大会 での実況・感想など • Twitterへの感想の投稿など ◦ #pixivdevmeetup をつけていただけると嬉しいです

  9. 練習問題 必ず解答ください

  10. 1. Hello Worldが出力される 2. Hello pixivが出力される 3. Hell pixivが出力される 4.

    何も出力されない Ruby puts 'Hello pixiv'
  11. 1. Hello Worldが出力される 2. Hello pixivが出力される 3. Hell pixivが出力される 4.

    何も出力されない Ruby puts 'Hello pixiv'
  12. 12 なぜ? • putsは標準出力をするためのメソッド • 渡された文字列を出力します

  13. YAML問題

  14. 14 自己紹介 • sue445 • 2018年7月入社 ◦ もうすぐ4年目 • インフラ部所属

    • 自称YAMLエンジニア ◦ Ansible, Docker Compose, CircleCI, Travis CI, Wercker, GitHub Actions, GitLab CI, Serverless Framework, AWS SAM, Kubernetes sue445
  15. 1. {"a"=>"1"} 2. {"a"=>1} 3. シンタックスエラー 4. その他 YAML 1問目

    # problem1.yml a: 1 # Rubyで実行 YAML.load_file("problem1.yml" )
  16. 1. {"a"=>"1"} 2. {"a"=>1} 3. シンタックスエラー 4. その他 YAML 1問目

    # problem1.yml a: 1 # Rubyで実行 YAML.load_file("problem1.yml" )
  17. 17 なぜ? • YAMLの数字っぽい文字列はその言語の数字の型( Rubyだと Integer ) として解釈されます。 • 文字列として解釈させたい場合は

    "1" (ダブルクオーテーション)や '1' (シングルクォーテーション)のように囲んでください
  18. 1. "ふたりはプリキュア Splash Star,Yes!プリキュア5,Yes!プリ キュア5GoGo,フレッシュプリキュ ア!" 2. "ふたりはプリキュア Splash Star,,Yes!プリキュア5GoGo,フレッ

    シュプリキュア!" 3. ",Yes!プリキュア5,Yes!プリキュア 5GoGo,フレッシュプリキュア!" 4. シンタックスエラー YAML 2問目 # problem2.yml splash: ふたりはプリキュア Splash Star yes: Yes!プリキュア5 yes_gogo: Yes!プリキュア5GoGo fresh: フレッシュプリキュア! # Rubyで実行 data = YAML.load_file("problem2.yml" ) "#{data['splash']}, #{data['yes']}, #{data['yes_gogo']} ,#{data['fresh']}"
  19. 1. "ふたりはプリキュア Splash Star,Yes!プリキュア5,Yes!プリ キュア5GoGo,フレッシュプリキュ ア!" 2. "ふたりはプリキュア Splash Star,,Yes!プリキュア5GoGo,フレッ

    シュプリキュア!" 3. ",Yes!プリキュア5,Yes!プリキュア 5GoGo,フレッシュプリキュア!" 4. シンタックスエラー YAML 2問目 # problem2.yml splash: ふたりはプリキュア Splash Star yes: Yes!プリキュア5 yes_gogo: Yes!プリキュア5GoGo fresh: フレッシュプリキュア! # Rubyで実行 data = YAML.load_file("problem2.yml" ) "#{data['splash']}, #{data['yes']}, #{data['yes_gogo']} ,#{data['fresh']}"
  20. 20 なぜ? • true, false, yes, no, on, off はダブルクオーテーションなどで囲まない限り

    YAMLでは全て 真偽値 として扱われます • Hashのvalueだけでなくkeyに対しても同様に適用されます data = YAML.load_file("problem2.yml") => {"splash"=>"ふたりはプリキュア Splash Star", true=>"Yes!プリキュア5GoGo!", "yes_gogo"=>"Yes!プリキュア5GoGo", "fresh"=>"フレッシュプリキュア!"}
  21. 1. {"slack"=>{"webhook_url"=> "https://example.com/", "channel"=>"random"}} 2. {"slack"=>{"webhook_url"=> "https://example.com/", "channel"=>"production_notify"}} 3. {"slack"=>{"channel"=>

    "production_notify"}} 4. シンタックスエラー YAML 3問目 # problem3.yml default: &default slack: webhook_url: "https://example.com/" channel: "random" production: <<: *default slack: channel: "production_notify" # Rubyで実行 data = YAML.load_file("problem3.yml" ) data["production"]
  22. 1. {"slack"=>{"webhook_url"=> "https://example.com/", "channel"=>"random"}} 2. {"slack"=>{"webhook_url"=> "https://example.com/", "channel"=>"production_notify"}} 3. {"slack"=>{"channel"=>

    "production_notify"}} 4. シンタックスエラー YAML 3問目 # problem3.yml default: &default slack: webhook_url: "https://example.com/" channel: "random" production: <<: *default slack: channel: "production_notify" # Rubyで実行 data = YAML.load_file("problem3.yml" ) data["production"]
  23. 23 なぜ? • & (アンカー)と * (エイリアス)で定義済みの値をいい感じに共通化できる のはYAMLのよくあるリファクタリング手法ですが、 <<: (マージ)はdeep

    merge(要素内に別の要素があった時に再帰的にマージされる)で はなく第1要素だけを上書きするマージ(代入に近い)なので、 今回の場合 default の内容が打ち消されます。
  24. 1. [1.9, 1.10, 1.11, 1.12] 2. [1.9, 1.1, 1.11, 1.12]

    3. [1.90, 1.10, 1.11, 1.12] 4. シンタックスエラー YAML 4問目 # problem4.yml go: - 1.9 - 1.10 - 1.11 - 1.12 # Rubyで実行 data = YAML.load_file("problem4.yml" ) data["go"]
  25. 1. [1.9, 1.10, 1.11, 1.12] 2. [1.9, 1.1, 1.11, 1.12]

    3. [1.90, 1.10, 1.11, 1.12] 4. シンタックスエラー YAML 4問目 # problem4.yml go: - 1.9 - 1.10 - 1.11 - 1.12 # Rubyで実行 data = YAML.load_file("problem4.yml" ) data["go"]
  26. 26 なぜ? • クオーテーションで囲んでいないので小数として解釈されるため 1.10 は 1.1 として解釈されます • 厳密に

    1.10 として評価するには "1.10" のように囲む必要があります。 • 余談ですがGo 1.10が出た時に .travis.yml に 1.10 を追加したらGo 1.1で CIが実行されてビルドが失敗したことがあります。
  27. 1. aのみシンタックスエラー 2. bのみシンタックスエラー 3. aとb両方シンタックスエラー 4. シンタックスエラーは無い YAML 5問目

    # この中でシンタックスエラーになるのは? # a excludes: - *_test.rb # b excludes: - test/**
  28. 1. aのみシンタックスエラー 2. bのみシンタックスエラー 3. aとb両方シンタックスエラー 4. シンタックスエラーは無い YAML 5問目

    # この中でシンタックスエラーになるのは? # a excludes: - *_test.rb # b excludes: - test/**
  29. 29 なぜ? • *_test.rb の * が前述のエイリアスとして評価されるのですが、 対応する _test.rb という名前のエイリアスが存在しないため

    シンタックスエラーになります。 • シンタックスエラーにしないためには "*_test.rb" のように囲む必要があります。
  30. PHP問題

  31. 31 自己紹介 • /たっ?どさん/ • 2012年11月入社 ◦ 入社前はRubyをやってました ◦ PHPは入社してからの付き合いです

    • pixiv運営本部開発支援チーム • Emacs PHP Mode 現行メンテナー ◦ シンタックス色付け係 ◦ 連休中も正規表現書いてました tadsan
  32. 1. Http\Referer が 出力される 2. Referer が出力される 3. object(Referer)#1 (0)

    {} が 出力される 4. 実行時に Class "Referer" not found エラーで落ちる PHP 1問目 <?php declare(strict_types=1); namespace Http; class Referrer { // impl } echo Referer::class;
  33. 1. Http\Referer が 出力される 2. Referer が出力される 3. object(Referer)#1 (0)

    {} が 出力される 4. 実行時に Class "Referer" not found エラーで落ちる PHP 1問目 <?php declare(strict_types=1); namespace Http; class Referrer { // impl } echo Referer::class;
  34. 34 なぜ? • PHPの ::class マジック定数はクラス名のFQCN(名前空間付きクラス名)を 文字列として返します • しかし、そのクラスが定義済みか、ロード可能かなどは 一切問いません

    • 未定義だとしても ::class の左側に記述したクラス名を名前空間付きにした 文字列をそのまま返します • このようなミスの検出にはPHPStanのような静的解析が有効です
  35. 1. $a 2. $b 3. $c 4. $d PHP 2問目

    <?php declare(strict_types=1); namespace pixiv; // これらの変数をPHP 8.0 で // $f(...$args) のように呼び出したとき、 // 関数として呼び出せない変数はどれ? // ($argsには適切な引数が格納されている ) $a = 'printf'; $b = 'function () { return 1; }'; $c = 'DateTime::createFromFormat'; $d = ['DateTime', 'createFromFormat'];
  36. 1. $a 2. $b 3. $c 4. $d PHP 2問目

    <?php declare(strict_types=1); namespace pixiv; // これらの変数をPHP 8.0 で // $f(...$args) のように呼び出したとき、 // 関数として呼び出せない変数はどれ? // ($argsには適切な引数が格納されている ) $a = 'printf'; $b = 'function () { return 1; }'; $c = 'DateTime::createFromFormat'; $d = ['DateTime', 'createFromFormat'];
  37. 37 なぜ? • PHP用語で関数として呼び出し可能な値を callable擬似型と呼びます • callableとして型宣言できる値は「関数名の文字列」「クラス名 ::メソッド名の文字列」 「Closureオブジェクト」そして「2要素の配列」などです ◦

    2要素の配列とは [$obj, 'method'] または ['Klass', 'staticmethod'] ◦ 未定義のメソッド名が渡された場合はきちんと弾けます • 言語機能としてClosureが実装されるPHP 5.3より前はcreate_function()という 関数で引数に文字列を渡すと、擬似的な無名関数が作れました
  38. 1. CONST 2. CONST_2 3. CONST_3 4. CONST_4 PHP 3問目

    <?php declare(strict_types=1); namespace pixiv; // 以下の const で定義する定数定義のうち、 // Syntax Errorにならず問題なく定義できる // 定義文の行はどれ? // (実際には不正な行を削除しないと実行不能 ) \define('DDD', 'Defined Constant'); const CONST = DDD; const CONST_2 = 'Con' . 'st'; const CONST_3 = \strtolower('CONST'); const CONST_4 = \constant('PHP_EOL'); ヒント: define()関数は実行時(関数呼び出し時)に、 const文はコンパイル時に定数を定義します。 . は文字列結合演算子 strtolower()は文字列を小文字にする関数 constant()は定義済み定数の値を得る関数
  39. 1. CONST 2. CONST_2 3. CONST_3 4. CONST_4 PHP 3問目

    ヒント: define()関数は実行時(関数呼び出し時)に、 const文はコンパイル時に定数を定義します。 . は文字列結合演算子 strtolower()は文字列を小文字にする関数 constant()は定義済み定数の値を得る関数 <?php declare(strict_types=1); namespace pixiv; // 以下の const で定義する定数定義のうち、 // Syntax Errorにならず問題なく定義できる // 定義文の行はどれ? // (実際には不正な行を削除しないと実行不能 ) \define('DDD', 'Defined Constant'); const CONST = DDD; const CONST_2 = 'Con' . 'st'; const CONST_3 = \strtolower('CONST'); const CONST_4 = \constant('PHP_EOL');
  40. 40 なぜ? • const文に書けるのは定数式と呼ばれるもので、定数およびリテラル (配列含む)および、 それらを組み合わせた演算子式です。引数のデフォルト値と同じ。 • 1.はひっかけです。PHPの予約語はケースインセンシティブなので、大文字 小文字問わずconstという定数・関数は定義できません。 (変数とメソッドは可)

    ◦ define()で定義される定数をconstから参照するのは可能です • 2.はリテラル同士の演算子式なので合法です。 • 3., 4. は実行時に評価される関数なので const文には書けません。 PHPにはC++のconst exprのような概念はいまのところありません。
  41. 1. Aが出力される 2. Bが出力される 3. 実行時エラーで落ちる 4. syntax errorで実行できない PHP

    4問目 <?php declare(strict_types=1); namespace pixiv; // 以下のコードを実行するとどうなるでしょうか class A { public function __toString() { return B::class; } } class B { } $a = new A; $obj = new $a; echo get_class($obj);
  42. 1. Aが出力される 2. Bが出力される 3. 実行時エラーで落ちる 4. syntax errorで実行できない PHP

    4問目 <?php declare(strict_types=1); namespace pixiv; // 以下のコードを実行するとどうなるでしょうか class A { public function __toString() { return B::class; } } class B { } $a = new A; $obj = new $a; echo get_class($obj);
  43. 43 なぜ? • ここまで関数がそうだったように、 newにも変数が使えます • $class = 'B'; $obj

    = new $class; のように 文字列 'B' を渡すと、Bのインスタンスに初期化になります • newの右辺の変数が文字列ではなくインスタンスオブジェクトだった場合、 そのインスタンスのクラスとして初期化が実行されます ◦ この文脈では __toString() の有無は影響を及ぼさず、ひっかけです ◦ echoなどでは暗黙的に呼び出されますが、 newは呼び出しません
  44. ゲスト問題 uzulla

  45. 1. hiと出力される 2. hihiと出力される 3. hihihihi…と無限ループする 4. レスポンスが返ってこない PHP 5問目

    <?php // $ php -S 127.0.0.1:8080 // でビルトインWebサーバを起動し、 // ブラウザから実行するとどうなるか? ini_set("display_errors", 0); echo "hi"; $code = file_get_contents(__FILE__); eval(ltrim($code, "<?ph"));
  46. 1. hiと出力される 2. hihiと出力される 3. hihihihi…と無限ループする 4. レスポンスが返ってこない PHP 5問目

    <?php // $ php -S 127.0.0.1:8080 // でビルトインWebサーバを起動し、 // ブラウザから実行するとどうなるか? ini_set("display_errors", 0); echo "hi"; $code = file_get_contents(__FILE__); eval(ltrim($code, "<?ph"));
  47. 47 なぜ? • 通常、__FILE__マジック定数はファイル名の文字列として展開されます • eval 内で展開される二度目の__FILE__の文字列 "/path/eval.php(4) : eval()'d

    code" のような形式で、 ファイル名ではなくなります • このコードは初回起動と一回の evalでそれぞれ hi と出力され、 それ以上は再帰することなく終了します • エラー出力は ini_set("display_errors", 0); で抑制され、最終出力は hihi です
  48. Ruby問題

  49. 49 自己紹介 • usa (unak) • 2018年3月入社 • 配信技術部エンジニアマネージャー •

    Rubyコミッタ ◦ 毎年Rubyの安定版を殺す係の人 ◦ https://www.ruby-lang.org/ で一番多くの記 事を書いてる人 ◦ x64版Windowsへの移植をした人 usa
  50. 1. nil と改行が出力される 2. nil だけ出て無改行 3. 改行のみが出力される 4. 改行も含めて一切何も出力さ

    れない Ruby 1問目 # 以下のスクリプトを実行すると何が # 起きますか? p
  51. 1. nil と改行が出力される 2. nil だけ出て無改行 3. 改行のみが出力される 4. 改行も含めて一切何も出力さ

    れない Ruby 1問目 # 以下のスクリプトを実行すると何が # 起きますか? p
  52. 52 なぜ? • 特に解説するほどでもないですが、 p は無引数の場合は何も出力しません。

  53. 1. 改行のみが出力される 2. 何も出力されない 3. 42 が出力される 4. SystemStackError 例外が発

    生する Ruby 2問目 # 以下のスクリプトを実行すると何が # 起きますか? def p(p=42) p end p p
  54. 1. 改行のみが出力される 2. 何も出力されない 3. 42 が出力される 4. SystemStackError 例外が発

    生する Ruby 2問目 # 以下のスクリプトを実行すると何が # 起きますか? def p(p=42) p end p p
  55. 55 なぜ? • スクリプト内で再定義された p メソッド内で使われている p は仮引数の p なので、このメ

    ソッドは無引数で呼ばれた場合には単に 42 を返すだけのメソッドとなります。 • 括弧があるか引数の指定があればここで自分を再帰呼び出しするんですが、この場合は メソッド呼び出しではなく変数参照が優先されるんですね。 • で、p p では、まず後ろの p の呼び出しが発生し、無引数なので 42 を返します。
  56. 56 なぜ? • つづいて、この 42 を引数として再び p が呼ばれますが、今度はこの引数である 42 を返

    すだけです。 • 結局、組み込みの p は呼ばれませんので、特になんの出力も行われません。
  57. 1. Bは a に 42 が入るが、AとCは syntax errorになる 2. AとBは

    a に 42 が入るが C は syntax errorになる 3. BとCは a に 42 が入るが A は syntax errorになる 4. 全部 a に 42 が入る Ruby 3問目 # Rubyには本当の意味での右代入はないですが、 # Ruby 3.0からは類似のことが 1行パターン # マッチング構文で実現可能となっています。 # では、Ruby 3.0において、以下のスクリプト の # A・B・Cについて、正しい答えを選んで # ください。 42 => a # A (42) => (a) # B [42] => [a] # C
  58. 1. Bは a に 42 が入るが、AとCは syntax errorになる 2. AとBは

    a に 42 が入るが C は syntax errorになる 3. BとCは a に 42 が入るが A は syntax errorになる 4. 全部 a に 42 が入る Ruby 3問目 # Rubyには本当の意味での右代入はないですが、 # Ruby 3.0からは類似のことが 1行パターン # マッチング構文で実現可能となっています。 # では、Ruby 3.0において、以下のスクリプト の # A・B・Cについて、正しい答えを選んで # ください。 42 => a # A (42) => (a) # B [42] => [a] # C
  59. 59 なぜ? • 全て1行パターンマッチング構文として正しく、 a に 42 が入ります。 • ただし、Cだけは現状は常時警告が出ます。

    • 来るRuby 3.1ではこの警告も消えるかもです。 • なお、これらは式の値自体は nil になりますのでご注意くださいませ。
  60. 1. {42 => 42} が出力される 2. syntax errorになる 3. nil

    が出力される 4. 何も出力されない Ruby 4問目 # Ruby 3.0で以下のスクリプトを実行すると # 何が起きるでしょう? a = b = 42 p { a => b }
  61. 1. {42 => 42} が出力される 2. syntax errorになる 3. nil

    が出力される 4. 何も出力されない Ruby 4問目 # Ruby 3.0で以下のスクリプトを実行すると # 何が起きるでしょう? a = b = 42 p { a => b }
  62. 62 なぜ? • { a => b } はハッシュロケット構文なのでHashオブジェクト {42

    => 42} になって、それを p するから答えは1……ではありません。ここでは { はハッシュ式ではなくブロック引数の始ま りとみなされますので、Hashオブジェクトにはなりません。Rubyを書き始めたばかりの人 がよく踏むやつです。 • というわけで、ハッシュ式の中以外ではハッシュロケット => は書けませんので、ここで syntax errorになるので答えは2……となりそうな気がしますし、実際、 Ruby 2.7までではそ の通りなのですが、Ruby 3.0では第3問で述べた1行パターンマッチング構文が導入され たので、a => b は文法的に正しい式です。
  63. 63 なぜ? • 従って、これは正しい文なので a => b が評価され、その結果は nil なので

    nil が出力され て答えは3…… となるわけではなくて、実はRubyではブロックを引数として受け取らないメ ソッドに敢えてブロックを渡した場合、単にそれを無視するという不思議な性質がありま す。構文解析だけはされるので、文法的に書けない式を書くと syntax errorにはなるんで すけどね。 • というわけで、{ a => b } は結局 p メソッドには無視されてしまい、引数がないという扱い になるので、第1問と同じように、何も出力されないのでした。
  64. ゲスト問題 mame

  65. 1. gsub! 2. sub 3. = 4. ! Ruby 5問目

    # 次のコードに"pixiv!"と出力させるには、 # [] のあたりに選択肢のどれを書き込めばよ い? str = "p!xiv!" str. [] (/!/, 'i') puts str
  66. 1. gsub! 2. sub 3. = 4. ! Ruby 5問目

    # 次のコードに"pixiv!"と出力させるには、 # [] のあたりに選択肢のどれを書き込めばよ い? str = "p!xiv!" str. [] (/!/, 'i') puts str
  67. 67 なぜ? • ! を両方置き換えたらまずいから gsub! はダメだというのはみなさんすぐにわかると思い ますが、sub では元の文字列は変更されないし、どういうことなの? ってなったと思いま

    す。 • 実は、「[] のあたりに」というのが罠で、[] 部分を置き換えるのではなくて [] の後ろに = を 入れるのが正解です。
  68. 68 なぜ? • String#[]= は、引数が整数であればそこで指定されたインデックスの文字を 置き換え、整数の範囲式であればその指定された範囲の部分文字列を置き換え ますが、引数が正規表現の場合は最初にマッチした部分文字列を置き換えます。 • このマイナーな挙動に加えて、それを代入式記法 (str[/!/]

    = 'i')ではなく メソッド式記法(str.[]=(/!/, 'i'))で使わせるという、普段書かないので 頭に浮かびにくいコードとなっており、罠が何重にもかけられているという 問題でした。
  69. JavaScript問題

  70. 70 自己紹介 • moriken (petamoriken) • 2017年5月入社(アルバイト) • プロダクト支援本部 課題解決部

    エンジニア ◦ 福岡オフィス • JavaScript が好きで TC39 会議を追っています ◦ 「moriken scrapbox」で検索! ◦ 2018年くらいから TC39 会議の流れが日本語 で読めます(最近サボリ気味) moriken
  71. 1. "PIXIV DEV MEETUP 2021" 2. "PIXIV undefined MEETUP 2021"

    3. "PIXIV DEV [object String] 2021" 4. "PIXIV undefined [object String] 2021" JavaScript 1問目 // 最後の式の結果は? const str1 = "PIXIV"; str1.word = "DEV"; const str2 = new String("MEETUP"); str2.word = "2021"; `${str1} ${str1.word} ${str2} ${str2.word}`;
  72. JavaScript 1問目 // 最後の式の結果は? const str1 = "PIXIV"; str1.word =

    "DEV"; const str2 = new String("MEETUP"); str2.word = "2021"; `${str1} ${str1.word} ${str2} ${str2.word}`; 1. "PIXIV DEV MEETUP 2021" 2. "PIXIV undefined MEETUP 2021" 3. "PIXIV DEV [object String] 2021" 4. "PIXIV undefined [object String] 2021"
  73. 73 なぜ? • プリミティブ値に対してプロパティを設定することはできません。 • str1 はプリミティブで str2 はプリミティブラッパーオブジェクトなので、 str2

    にのみプロパティを設定できます。 • また Object.prototype.toString.call(str2) は "[object String]" を返すのですが これはひっかけで、str2.toString() の結果と同じ "MEETUP" の文字列が含まれる 形になります。
  74. 1. [5, 10, 15, "10"] 2. [5, 10, "10", 15]

    3. [10, "10", 15, 5] 4. 実装依存 (一意に定まらない) JavaScript 2問目 // ソートの結果は? [10, 15, "10", 5].sort();
  75. 1. [5, 10, 15, "10"] 2. [5, 10, "10", 15]

    3. [10, "10", 15, 5] 4. 実装依存 (一意に定まらない) // ソートの結果は? [10, 15, "10", 5].sort(); JavaScript 2問目
  76. 76 なぜ? • Array.prototype.sort のデフォルトソートは何故か文字列の比較となっている ため、文字列化した際の辞書順に並びます。 • Array.prototype.sort は安定ソートとは限らないため実装依存と思った方もいらっしゃる かもしれません(数値の

    10 と文字列の "10" のどっちが先に来るかわからない)が、これ については ES2019 から安定ソートが必須化されています。 ◦ 2, 3年くらい前の古い V8 エンジンの環境でない限り安定ソートだと考えて 問題ありません。
  77. 1. PIXIV { DEV: "MEETUP" } (PIXIV オブジェクト) 2. "2021"

    3. String { "2021" } (プリミティブラッパーオブ ジェクト) 4. throws TypeError // 最後の式の結果は? class PIXIV { constructor() { this.DEV = "MEETUP"; return "2021"; } } new PIXIV(); JavaScript 3問目
  78. // 最後の式の結果は? class PIXIV { constructor() { this.DEV = "MEETUP";

    return "2021"; } } new PIXIV(); 1. PIXIV { DEV: "MEETUP" } (PIXIV オブジェクト) 2. "2021" 3. String { "2021" } (プリミティブラッパーオブ ジェクト) 4. throws TypeError JavaScript 3問目
  79. 79 なぜ? • コンストラクタの返り値がオブジェクトの場合はそれで上書きできますが、 プリミティブ値の場合は上書きできずにそのままスルーされて this が返ります。

  80. 1. { value: "PIXIV", done: false } 2. { value:

    "MEETUP", done: false } 3. { value: undefined, done: true } 4. throws TypeError // 最後の式の結果は? function* gen() { yield* ["PIXIV", "DEV", "MEETUP", "2021"]; } const iter = gen(); for (const word of iter) { if (word === "DEV") { break; } } iter.next(); JavaScript 4問目
  81. 1. { value: "PIXIV", done: false } 2. { value:

    "MEETUP", done: false } 3. { value: undefined, done: true } 4. throws TypeError // 最後の式の結果は? function* gen() { yield* ["PIXIV", "DEV", "MEETUP", "2021"]; } const iter = gen(); for (const word of iter) { if (word === "DEV") { break; } } iter.next(); JavaScript 4問目
  82. 82 なぜ? • この問題は for-of とジェネレーター函数について問われた問題です。 ◦ for-of の途中でループから抜ける場合、イテレーターに return

    メソッドが定義されて いる場合はそれを実行します。 ◦ ジェネレーター函数から作ったイテレーターにはプロトタイプに return メソッドが定義 されています。実行すると列挙が終わった扱いになります。 • 余談ですが ["PIXIV", "DEV", "MEETUP", "2021"].values() で ArrayIterator を作った場合 は、プロトタイプに return メソッドが定義されていないため結果が変わります。
  83. ゲスト問題 gaogao_9

  84. 1. "PIXIV" 2. "DEV" 3. "MEETUP" 4. "2021" // 最後の式の結果は?

    const obj = Object.create(null, { [Symbol("PIXIV")]: { value: "PIXIV", enumerable: true }, DEV: { value: "DEV", enumerable: true }, MEETUP: { value: "MEETUP", enumerable: true }, 2021: { value: "2021", enumerable: true }, }); Object.values(obj)[ Object.keys(obj).length-1 ]; JavaScript 5問目
  85. 1. "PIXIV" 2. "DEV" 3. "MEETUP" 4. "2021" // 最後の式の結果は?

    const obj = Object.create(null, { [Symbol("PIXIV")]: { value: "PIXIV", enumerable: true }, DEV: { value: "DEV", enumerable: true }, MEETUP: { value: "MEETUP", enumerable: true }, 2021: { value: "2021", enumerable: true }, }); Object.values(obj)[ Object.keys(obj).length-1 ]; JavaScript 5問目
  86. 86 なぜ? • これは Object.keys と Object.values がどんな配列を返すのかを問う問題です。 ◦ 両方ともオブジェクトのプロパティのキーが文字列なもののみを含みます(シンボルは

    含まれません)。 • 列挙順は以下の通りです。 ◦ まず配列のキーになり得る数値の文字列を小さい方から列挙します。 ◦ それ以外の文字列はオブジェクトのキーの定義順に返します。 • よって ["2021", "DEV", "MEETUP"] のうちの最後の要素が答えです。
  87. Java問題

  88. 88 自己紹介 • orekyuu • 2017年4月新卒入社 • BOOTH部所属 • Javaが好きなRailsエンジニア

    ◦ 業務のちょっとしたスクリプトでも Javaで書き始める書くおじさん ◦ 好きなIDEはIntelliJ orekyuu
  89. 1. false/false/false/false 2. true/false/true/true 3. true/true/true/false 4. true/false/true/false Java 1問目

    void hoge() { String literalJava = "Java"; final String finalJava = "Java"; final String newJava = new String("Java"); System.out.print("Hello, Java" == "Hello, Java"); System.out.print("/"); System.out.print(("Hello, " + literalJava) == "Hello, Java"); System.out.print("/"); System.out.print(("Hello, " + finalJava) == "Hello, Java"); System.out.print("/"); System.out.print(("Hello, " + newJava) == "Hello, Java"); } hoge();
  90. 1. false/false/false/false 2. true/false/true/true 3. true/true/true/false 4. true/false/true/false Java 1問目

    void hoge() { String literalJava = "Java"; final String finalJava = "Java"; final String newJava = new String("Java"); System.out.print("Hello, Java" == "Hello, Java"); System.out.print("/"); System.out.print(("Hello, " + literalJava) == "Hello, Java"); System.out.print("/"); System.out.print(("Hello, " + finalJava) == "Hello, Java"); System.out.print("/"); System.out.print(("Hello, " + newJava) == "Hello, Java"); } hoge();
  91. 91 なぜ? • 同じ文字列のリテラルはプールされるため、参照が等しくなります (1つ目) • literalJavaとつないだときは新しく文字列が作られるため違うインスタンスになります (2つ 目) •

    finalで宣言されたStringはコンパイル時にインライン化されるため、 "Hello, Java"と同等 になるので等しいです(3つ目) • newされた場合はプールされないため別のインスタンスになります (4つ目) • Javaの文字列は==で比較せずにequalsメソッドを使って比較しろってことです 😡
  92. 1. true 2. false 3. 環境によって異なる 4. 実行時エラー Java 2問目

    URL hoge = new URL("http://hoge:password@hoge.com" ); URL fuga = new URL("http://fuga:password@hoge.com" ); System.out.println(hoge.equals(fuga)) ;
  93. 1. true 2. false 3. 環境によって異なる 4. 実行時エラー Java 2問目

    URL hoge = new URL("http://hoge:password@hoge.com" ); URL fuga = new URL("http://fuga:password@hoge.com" ); System.out.println(hoge.equals(fuga)) ;
  94. 94 なぜ? • URLのequalsはオーバーライドされていて次の条件に一致する場合 trueを返します ◦ 同じプロトコルを持ち ◦ 同じホストを参照し ◦

    同じホストとは同じIPに解決される • 名前解決できない場合は大文字小文字に関係なくホスト名が等しいか • ホスト上のポート番号が同じでファイルとファイルのフラグメントが同じ場合 • ユーザー名の情報は 等価性に含まれない のでtrueになります
  95. 1. main.showText();の行で コンパイルエラー 2. void showText(Main Main.this)の行で コンパイルエラー 3. System.out.printlnの行で

    コンパイルエラー 4. pixivが出力される Java 3問目 public class Main { String text; public static void main(String[] args) { Main main = new Main(); main.text = "pixiv"; main.showText() ; } void showText(Main Main.this) { System. out.println(Main. this.text); } }
  96. 1. main.showText();の行で コンパイルエラー 2. void showText(Main Main.this)の行で コンパイルエラー 3. System.out.printlnの行で

    コンパイルエラー 4. pixivが出力される Java 3問目 public class Main { String text; public static void main(String[] args) { Main main = new Main(); main.text = "pixiv"; main.showText() ; } void showText(Main Main.this) { System. out.println(Main. this.text); } }
  97. 97 なぜ? • かなりマイナーな構文ですが、非 staticなメソッドではReceiver parameterと呼ばれるも のを定義できます • Receiver parameterを受け取ってなにかの情報を取ることはできないので無意味なよう

    に見える構文です • 嬉しさとしてはここにアノテーションを書くことができるので、コンパイル時に Receiverに対 して何かしらのチェックを走らせたいときに使うらしいです
  98. 1. 常にtrue 2. 常にfalse 3. 実行ごとに結果が変わる 4. 実行時エラー Java 4問目

    boolean prev = true; int matchCount = 0; for (int i = 0; i < 100; i++) { boolean other = new Random(System.currentTimeMillis()) .nextBoolean() ; if (prev == other) matchCount++ ; prev = other; } System.out.println(matchCount > 50);
  99. 1. 常にtrue 2. 常にfalse 3. 実行ごとに結果が変わる 4. 実行時エラー Java 4問目

    boolean prev = true; int matchCount = 0; for (int i = 0; i < 100; i++) { boolean other = new Random(System.currentTimeMillis()) .nextBoolean() ; if (prev == other) matchCount++ ; prev = other; } System.out.println(matchCount > 50);
  100. 100 なぜ? • よくよく見るとRandomのシード値がミリ秒になっています • 現代のマシンでは1ミリ秒の間にループがすべて回ってしまうため同じシード値になってし まう • Randomは使い回さない +

    デフォルトコンストラクタを使いましょう
  101. ゲスト問題 noko_k

  102. 1. 実行時例外 2. Hello null 3. 何も出力されない 4. それ以外 Java

    5問目 class Words { static String HELLO = "Hello"; static String WORLD = "World"; } Words words = new Words(); "%s %s".formatted(words. HELLO, ((Words) null).WORLD) .chars().forEach(System. out::print);
  103. 1. 実行時例外 2. Hello null 3. 何も出力されない 4. それ以外 72101108108111328711111

    4108100が出力されます Java 5問目 class Words { static String HELLO = "Hello"; static String WORLD = "World"; } Words words = new Words(); "%s %s".formatted(words. HELLO, ((Words) null).WORLD) .chars().forEach(System. out::print);
  104. 104 なぜ? • ((Words) null).WORLD の部分については、NullPointerExceptionとなりません。static フィールドの呼び出しは、参照するインスタンスが nullかどうかに関わらず参照することが 出来ます(つまりこの式は"World"になります) •

    chars() メソッドは文字列をIntStreamに変換します(CharStreamは存在しません) • IntStream#forEachはIntConsumerを受け取ります。それによりここで呼び出されるメ ソッドは引数がintのprintメソッドとなります。 • これにより、実行するとそれぞれの文字を整数表現にした数字がそれぞれ表示されてし まいます。
  105. 結果発表!