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

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

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

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

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

Avatar for orekyuu

orekyuu

May 21, 2021
Tweet

More Decks by orekyuu

Other Decks in Programming

Transcript

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

    Java の5言語から4択クイズを出題 ◦ バージョンが明記されてなければ最新の実装で動くものと思ってください • 最も正答率の高かった人が複数のプログラミング言語を極めし 王者! • 最強のマルチリンガルには、王者にふさわしい豪華景品を用意しています
  2. 14 自己紹介 • sue445 • 2018年7月入社 ◦ もうすぐ4年目 • インフラ部所属

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

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

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

    "1" (ダブルクオーテーション)や '1' (シングルクォーテーション)のように囲んでください
  6. 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']}"
  7. 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']}"
  8. 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"=>"フレッシュプリキュア!"}
  9. 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"]
  10. 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"]
  11. 23 なぜ? • & (アンカー)と * (エイリアス)で定義済みの値をいい感じに共通化できる のはYAMLのよくあるリファクタリング手法ですが、 <<: (マージ)はdeep

    merge(要素内に別の要素があった時に再帰的にマージされる)で はなく第1要素だけを上書きするマージ(代入に近い)なので、 今回の場合 default の内容が打ち消されます。
  12. 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"]
  13. 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"]
  14. 26 なぜ? • クオーテーションで囲んでいないので小数として解釈されるため 1.10 は 1.1 として解釈されます • 厳密に

    1.10 として評価するには "1.10" のように囲む必要があります。 • 余談ですがGo 1.10が出た時に .travis.yml に 1.10 を追加したらGo 1.1で CIが実行されてビルドが失敗したことがあります。
  15. 29 なぜ? • *_test.rb の * が前述のエイリアスとして評価されるのですが、 対応する _test.rb という名前のエイリアスが存在しないため

    シンタックスエラーになります。 • シンタックスエラーにしないためには "*_test.rb" のように囲む必要があります。
  16. 31 自己紹介 • /たっ?どさん/ • 2012年11月入社 ◦ 入社前はRubyをやってました ◦ PHPは入社してからの付き合いです

    • pixiv運営本部開発支援チーム • Emacs PHP Mode 現行メンテナー ◦ シンタックス色付け係 ◦ 連休中も正規表現書いてました tadsan
  17. 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;
  18. 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;
  19. 34 なぜ? • PHPの ::class マジック定数はクラス名のFQCN(名前空間付きクラス名)を 文字列として返します • しかし、そのクラスが定義済みか、ロード可能かなどは 一切問いません

    • 未定義だとしても ::class の左側に記述したクラス名を名前空間付きにした 文字列をそのまま返します • このようなミスの検出にはPHPStanのような静的解析が有効です
  20. 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'];
  21. 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'];
  22. 37 なぜ? • PHP用語で関数として呼び出し可能な値を callable擬似型と呼びます • callableとして型宣言できる値は「関数名の文字列」「クラス名 ::メソッド名の文字列」 「Closureオブジェクト」そして「2要素の配列」などです ◦

    2要素の配列とは [$obj, 'method'] または ['Klass', 'staticmethod'] ◦ 未定義のメソッド名が渡された場合はきちんと弾けます • 言語機能としてClosureが実装されるPHP 5.3より前はcreate_function()という 関数で引数に文字列を渡すと、擬似的な無名関数が作れました
  23. 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()は定義済み定数の値を得る関数
  24. 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');
  25. 40 なぜ? • const文に書けるのは定数式と呼ばれるもので、定数およびリテラル (配列含む)および、 それらを組み合わせた演算子式です。引数のデフォルト値と同じ。 • 1.はひっかけです。PHPの予約語はケースインセンシティブなので、大文字 小文字問わずconstという定数・関数は定義できません。 (変数とメソッドは可)

    ◦ define()で定義される定数をconstから参照するのは可能です • 2.はリテラル同士の演算子式なので合法です。 • 3., 4. は実行時に評価される関数なので const文には書けません。 PHPにはC++のconst exprのような概念はいまのところありません。
  26. 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);
  27. 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);
  28. 43 なぜ? • ここまで関数がそうだったように、 newにも変数が使えます • $class = 'B'; $obj

    = new $class; のように 文字列 'B' を渡すと、Bのインスタンスに初期化になります • newの右辺の変数が文字列ではなくインスタンスオブジェクトだった場合、 そのインスタンスのクラスとして初期化が実行されます ◦ この文脈では __toString() の有無は影響を及ぼさず、ひっかけです ◦ echoなどでは暗黙的に呼び出されますが、 newは呼び出しません
  29. 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"));
  30. 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"));
  31. 47 なぜ? • 通常、__FILE__マジック定数はファイル名の文字列として展開されます • eval 内で展開される二度目の__FILE__の文字列 "/path/eval.php(4) : eval()'d

    code" のような形式で、 ファイル名ではなくなります • このコードは初回起動と一回の evalでそれぞれ hi と出力され、 それ以上は再帰することなく終了します • エラー出力は ini_set("display_errors", 0); で抑制され、最終出力は hihi です
  32. 49 自己紹介 • usa (unak) • 2018年3月入社 • 配信技術部エンジニアマネージャー •

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

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

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

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

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

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

    すだけです。 • 結局、組み込みの p は呼ばれませんので、特になんの出力も行われません。
  39. 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
  40. 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
  41. 59 なぜ? • 全て1行パターンマッチング構文として正しく、 a に 42 が入ります。 • ただし、Cだけは現状は常時警告が出ます。

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

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

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

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

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

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

    # 次のコードに"pixiv!"と出力させるには、 # [] のあたりに選択肢のどれを書き込めばよ い? str = "p!xiv!" str. [] (/!/, 'i') puts str
  48. 70 自己紹介 • moriken (petamoriken) • 2017年5月入社(アルバイト) • プロダクト支援本部 課題解決部

    エンジニア ◦ 福岡オフィス • JavaScript が好きで TC39 会議を追っています ◦ 「moriken scrapbox」で検索! ◦ 2018年くらいから TC39 会議の流れが日本語 で読めます(最近サボリ気味) moriken
  49. 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}`;
  50. 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"
  51. 73 なぜ? • プリミティブ値に対してプロパティを設定することはできません。 • str1 はプリミティブで str2 はプリミティブラッパーオブジェクトなので、 str2

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

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

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

    10 と文字列の "10" のどっちが先に来るかわからない)が、これ については ES2019 から安定ソートが必須化されています。 ◦ 2, 3年くらい前の古い V8 エンジンの環境でない限り安定ソートだと考えて 問題ありません。
  55. 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問目
  56. // 最後の式の結果は? 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問目
  57. 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問目
  58. 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問目
  59. 82 なぜ? • この問題は for-of とジェネレーター函数について問われた問題です。 ◦ for-of の途中でループから抜ける場合、イテレーターに return

    メソッドが定義されて いる場合はそれを実行します。 ◦ ジェネレーター函数から作ったイテレーターにはプロトタイプに return メソッドが定義 されています。実行すると列挙が終わった扱いになります。 • 余談ですが ["PIXIV", "DEV", "MEETUP", "2021"].values() で ArrayIterator を作った場合 は、プロトタイプに return メソッドが定義されていないため結果が変わります。
  60. 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問目
  61. 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問目
  62. 86 なぜ? • これは Object.keys と Object.values がどんな配列を返すのかを問う問題です。 ◦ 両方ともオブジェクトのプロパティのキーが文字列なもののみを含みます(シンボルは

    含まれません)。 • 列挙順は以下の通りです。 ◦ まず配列のキーになり得る数値の文字列を小さい方から列挙します。 ◦ それ以外の文字列はオブジェクトのキーの定義順に返します。 • よって ["2021", "DEV", "MEETUP"] のうちの最後の要素が答えです。
  63. 88 自己紹介 • orekyuu • 2017年4月新卒入社 • BOOTH部所属 • Javaが好きなRailsエンジニア

    ◦ 業務のちょっとしたスクリプトでも Javaで書き始める書くおじさん ◦ 好きなIDEはIntelliJ orekyuu
  64. 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();
  65. 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();
  66. 91 なぜ? • 同じ文字列のリテラルはプールされるため、参照が等しくなります (1つ目) • literalJavaとつないだときは新しく文字列が作られるため違うインスタンスになります (2つ 目) •

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

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

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

    同じホストとは同じIPに解決される • 名前解決できない場合は大文字小文字に関係なくホスト名が等しいか • ホスト上のポート番号が同じでファイルとファイルのフラグメントが同じ場合 • ユーザー名の情報は 等価性に含まれない のでtrueになります
  70. 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); } }
  71. 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); } }
  72. 97 なぜ? • かなりマイナーな構文ですが、非 staticなメソッドではReceiver parameterと呼ばれるも のを定義できます • Receiver parameterを受け取ってなにかの情報を取ることはできないので無意味なよう

    に見える構文です • 嬉しさとしてはここにアノテーションを書くことができるので、コンパイル時に Receiverに対 して何かしらのチェックを走らせたいときに使うらしいです
  73. 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);
  74. 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);
  75. 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);
  76. 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);
  77. 104 なぜ? • ((Words) null).WORLD の部分については、NullPointerExceptionとなりません。static フィールドの呼び出しは、参照するインスタンスが nullかどうかに関わらず参照することが 出来ます(つまりこの式は"World"になります) •

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