クフでダローバルな日記

タフでもグローバルもない

学科で Advent Calendar をするということ

この記事は、eeic2015 の自称イベンター(not イベ長)であるところの僕が、次世代のイベンターを募集するための啓蒙ポエムです。

eeic Advent Calendar 2016 その2 の最終日の記事でもあります。

qiita.com

eeic Advent Calendar 2016 総括

eeic Advent Calendar 2016 は今日で終了となります(この文は2016年12月25日に書かれました)。 参加してくださった皆さん、ご協力ありがとうございました & お疲れ様でした。

せっかくなので今年の Advent Calendar について少しだけ振り返ってみようと思います。

学年ごとの延べ参加者数

個人的に気になったので、把握できる範囲で参加者を年度ごとにまとめてみました。 合計が50にならないのは、上の方の世代の方で僕が世代を知らない人が多かったためです。 来年以降は自分の年代書くの必須にしたい。

学年 その1 その2 合計
eeic2010 0 1 1
eeic2011 0 0 0
eeic2012 4 0 4
eeic2013 6 1 7
eeic2014 0 0 0
eeic2015 12 5 17
eeic2016 1 2 3
eeic2017 1 13 14

僕の同期にあたる2015が多いのは納得ですが、2017が想像以上に多くて怖いです。 eeic2017 は技術的にも強そうな記事が多くて本当に怖いのですが一言老害として苦言を申し上げておくと、やや日本語が怪しい傾向にあるのでキレられたくない人は『日本語の作文技術』と『理科系の作文技術』くらいは読みましょう(より具体的に言うならば、この段落を読んで日本語が怪しいと思わなかった人、もしくは怪しいと思っても直し方がわからない人は必ず読んで下さい)。

お忙しい中記事を書いてくださった先輩方、ありがとうございました。eeic2014の方々は僕のこと嫌いなんでしょうか。

ジャンルごとの記事数

記事のジャンルを勝手に分類しました。

ジャンル その1 その2 合計
技術 13 13 26
生き方 5 4 9
eeic・東大関 3 4 7
オタク 2 2 4
その他 2 2 4

ジャンルのばらつきはその1・その2で意外と均等ですね。 今年はオタク枠が少なくてやや悲しい気もします。

話題になった記事

今年の Advent Calendar で一番人気を博した記事は、 id:aerith7 さんの apollo11号のソースコードを読みつつ - aerith7’s blog であることは誰もが認めるところでしょう。 2016年12月26日16時57分時点ではてなブックマーク数は1657記事にも上り、メディア掲載劣化版無断パクリ記事の登場魚拓はこちら) にまで至っています。しゅごい。

eeic Advent Calendar をはじめたワケ

eeic Advent Calendar も二年目を終え、来年以降も続いていくと良いなと思いつつ、定番化すると当初の目的意識が曖昧になることもよくある話なので、ここで僕が Advent Calendar という文化を eeic に輸入した理由を記述として遺しておこうと思います。
理由は大きく分けて3つあるので、以下ではそれらを順番に語っていきます。

学科民にパブリックな記事を書いてほしい

eeicの後期実験の一つである「大規模ソフトウェアを手探る」では、ブログ記事をレポートとして認めることで外部に知見を共有し、自分の苦労とスキルを公開できるという面白い特徴があります。 @Kriver1 の 「LibreOfficeCalcに関数候補表示機能を付けるまで 最終回 LibreOfficeにコミットしてみる - Qiita」 では、この記事を公開したことで LibreOffice のmini Conferenceに招待されています。
この経過を控室で見ていたことや僕自身もブログによって恩恵を得ていたことから、大学外部への発信を通して得られる利益を他の人にも得てほしいという思いがありました。

なので、少し話はそれますが、ブログを書くこと・それが"バズる"ことのメリットについて話したいと思います。

エンジニア向けの自己啓発書として最近話題の『SOFT SKILLS ソフトウェア開発者の人生マニュアル』の第1部「キャリアを築こう」第5章「面接をハッキングするコツ」に次のような一節があります。

次のようなシナリオを想像してみよう。あなたは面接会場に入っていく。面接官と握手すると、面接官があなたを見たあと、一瞬、間をおいてあなたを認識し、顔をほころばせる。「ああ、あなたのことは知っていますよ。ブログで写真を見てますからね。あなたのブログポストはずいぶん読んでいますよ」

面接中にそういうことが起きたら、合格の可能性はどうだろう。(中略)ポイントは、一般に考えられていることとは裏腹に、ほとんどの面接官は、技術以外のあらゆる要素に基づいて人を採用するということである(有名ブログを持つための具体的な方法については第2部で説明する)。

早い話が、ブログがバズると就活などで使えます。
何を意識の高いことを言っているんだと思われるかもしれませんが、多くの人に読んでもらう技術記事を書くために必要な能力は文章力・構成力・テーマの発見能力などなど実用的なスキルセットです。 そういったスキルを身につけられるだけでなく、面接官に自分の強みを履歴書以外の部分でアピールできるのがブログなどの自己発信メディアの強みでしょう。

実体験の話もしておきます。僕はB3の夏にはてなのサマーインターンに行くことを目標にeeic生活を過ごすことにしていたのですが、大量に課せられる課題の影響もありB3の春時点での僕の開発スキルはほとんど初心者レベルで、技術的に自信のある領域などは全くありませんでした。 そこで僕が取った戦略は、はてなapiを使ったWebサービスを作ってブログに公開することでした。 結果的に多くのはてなユーザーの方に使っていただけた上に記事もそこそこバズり、念願のはてなインターンに参加に至ることができました。
実際にこのブログが合格にどれほど作用したのかは聞けませんでしたが、はてな社員の方からこの作ったサービスと記事の話を振られること何度かあったので、「技術以外のあらゆる要素」の一部をアピールできたのではないかと思っています。 技術に自信がない人こそ、ブログなど技術以外の面で自己アピールしていくのは戦略としてアリだと思います。

今年は Advent Calendar に参加を断念した方も、こんなメリットがあることを念頭に置いて来年以降は参加していただけたら企画者冥利に尽きます。 ただしもちろん、そんな意識の高い記事ばかりになってしまうのも面白くないですし、eeicの実態を全く反映しないので、趣味と情熱が振り切れた記事やコンプレックスを露出する記事などもぜひぜひ書いてほしいところです。

外部に eeic を知ってほしい

東大では進学振り分けというシステムによって、学科の人気が如実に可視化されます。 近年の eeic の人気は概ね右肩上がりであり、「人気回復期」であるといえますが、過去の変遷を見る限り、今後もその傾向が続くとは限りません(参考: 東大電気系(eeic)の人気の変遷をたどる - nakachanのブログ)。

eeic の人気回復のために有効だったのは、先生方の尽力ももちろんですが、五月祭における学生主体の展示が大きいと僕は考えています。 だからこそ、今後の人気を維持していく、なおかつ進振り学生と学科のミスマッチを防ぐためにも、eeicがどんな学科なのかを学生主体で発信していくことが必要だと考えました。
今のB2に昨年のAdvent Calendar を読んでいた人がどれほどいるのかは存じ上げないので、結局どれほど効果があったのかはわかりません。 ただ、今年の Advent Calendar を見れば、どんな人が eeic にいるのかが進振り説明会などよりも如実に伝わるのではないでしょうか。

※もし、進振り前から eeic Advent Calendarを見たという人がいたら、聞きたいことがあるので教えてください。

たのしい

僕はよく「理学部情報科学科に行けば良かッた!!」などとたまに愚痴っていますが、結局eeicが好きです。 僕が思う eeic の一番良いところは「他者を楽しませようという気持ちがある」という点で、これは他の学科より明らかに勝っているのではないかと考えています。
これはG3実験やBDMのように講義で発揮されるだけでなく、今年MFAwards学術部門で5連覇を達成した近未来体験でも如実に発揮されています。

この他者を楽しませる・他者の役に立つという性質は、「媚びている」と称されることもあるものの、モノを作って現実社会に還元しようとする工学部の精神に呼応したものでしょう。
僕は今までに学科同期でハッカソン・LT大会・ラボ紹介などを企画していますが、同期が作ってくれるものが楽しみだからこそ企画するモチベーションになっています。 来年以降の Advent Calendar も、楽しい記事を読めることを楽しみにしています。

イベンター募集

上の項で学科でイベントを企画することの楽しさを述べましたが、オタクは場を与えれば参加してくれるものの実際に場を作ろうとする人はあまりいません。 なので誰かが場を設置する必要があるのですが、eeic2016以降の後輩にそういった企画者がいるのかは知りません。
というわけで、いろいろ場所をお膳立てする縁の下のイベンターをこの場で募集しておきます。 やることは大変ではないのですが、僕がこの2年いろいろやった結果オタクを動かすノウハウも少し蓄積されてきたので、今後何かしたいけどやり方がわからんというときはぜひ僕に声をかけてください。出来る限りの協力はします。

ちなみに僕が開催したイベントの振り返りがwikiの僕のページに書いてあるので、そちらも御覧ください。

『コーディングを支える技術』読書メモとか

大学四年生になって自分の勉強をする時間がようやく取れるようになったので、体系的な知識をつけるために技術書を読むことにしている。 ただ漫然と読んでいるとサラーッと読んでしまうので、人に説明できる程度には自分のものにしたかったので、自分用のwikiに読書メモをまとめている。 しかし、圧力がないと飽きてしまうのでとりあえずブログに公開してみることにした。

まとめ方は基本的に一つの節を一つの疑問文に直し、その答えを極力簡潔にその節の中からまとめる形。

以下自前wikiより転載。


コーディングを支える技術

読むことにしたわけ

  1. プログラミングについての知識を深める以前に、全体の俯瞰をしたかった

  2. 例外とかよく知らないなと思った

  3. 勉強法についても乗ってるっぽくて良さそうだった

読後の感想

☆5

もっと早く読むべきだったとも思うが、今読むことが出来て本当に良かった。 知ってはいるし使ってもいるが何となくも理解しきれていない技術がどのような歴史的経緯で発明されて、今後どこに向かっていきそうなのかがかなりよくまとまっていた。 オブジェクト指向の章は今まで読んだ中で一番納得感のある内容だった。

ただ、この本を読んだからと言って実装ができるようになるとは限らず、また細かいところも省略されているのであとは自分で調べる必要がありそう。

読書メモ

第1章 言語を深く効率的に学ぶには

タイトルの通り

  • 1.1 比較から学ぶ -why?

    • 言語ごとに共通な知識と違いを知ることが出来るから

    • RubyとCでtrueになるものの違い

  • 1.2 歴史から学ぶ -why?

    • なぜその機能が必要なのかを、言語設計者の視点から知ることが出来るから
  • 1.3 まとめ

第2章 プログラミング言語を俯瞰する

どうしてプログラミング言語が生まれたか?

  • 2.1 プログラミング言語誕生の歴史 -what?

    • ケーブルをつなぎ替える→テープでのプログラミング(機械語)→FORTRAN等で人間が読み書きしやすく、という歴史
  • 2.2 プログラミング言語の生まれた目的 -what?

    • 特定の目的を「楽」にするため

      • C++ならCと同等の速さのコードをきれいに書く

      • Schemeは言語仕様を最小限 仕様書全体で50ページ!

      • Pythonは読むのが楽

      • MLは言語処理が楽

      • etc

  • 2.3 まとめ

第3章 文法の誕生

なぜ文法が必要か?

  • 3.1 文法って何だろう?

    • 演算子の優先順位など、言語設計者が決めたルール

    • この章では演算子の様々な処理方法を比較する

  • 3.2 スタックマシンとFORTH -what

    • スタックに値を入れていって、演算子/関数が来たらスタックから値を取り出すもの

    • PythonとかJavaVMもスタックマシン型

  • 3.3 構文木LISP -what

    • 関数ノードの下に値が葉として生えてる木とその再帰的な組み合わせが構文木

    • 実は、LISPとFORTHは構文木を辿る順番が違うだけ

  • 3.4 中置記法 -what

    • 1+2 みたいな+の使い方

    • 同じ構文木を作るためにいろんな文法があるが、それぞれを実現するために適切な構文解析器(パーサ)が必要

  • 3.5 まとめ

第4章 処理の流れのコントロール

なぜ制御構造が必要か?

  • 4.1 構造化プログラミングの誕生 -what

    • ifとかwhileとかが生まれた → なぜ?
  • 4.2 ifが生まれる前 -what

    • アセンブリレベルではジャンプ(=Cでのgoto)を使っている。直感に反しており読みづらい。

    • elseも同様。楽で読みやすい方が良い!

  • 4.3 while ──繰り返しのifを読みやすく表現 -what

    • ifgotoだけで実現できるが、読みやすさ書きやすさが良い
  • 4.4 for ──数値を増やしながらのwhileを読みやすく表現 -what

    • forを使うとループの初期化と週条件とステップがまとまってるので意図が分かりやすい。foreachも同様の目的。
  • 4.5 まとめ

    • 使わなくても出来るけど、制御できるおかげで分かりやすい

第5章 関数

何故関数が必要か?

  • 5.1 関数の役割 - what?

    • 理解のため - いくつかの行を一塊にして名前をつけることで 組織 のようになる

    • 再利用のため - 部品としてコンパクトに再利用できる。

  • 5.2 戻る命令 - how?

    • 従来の goto 文だと戻ることができなかった。

    • 戻り先を書き換える方式だと上書きされたら戻れなくなる。

    • 戻り先をスタックに保存しておくことでネストした関数呼び出しにも対応できる。

  • 5.3 再帰呼び出し - why?

    • 入れ子構造のデータを扱うために必要。
  • 5.4 まとめ

第6章 エラー処理

なぜ例外処理が返り値を使う方法よりもよいのか?

  • 6.1 プログラムも失敗をする - what?

    • ファイルの書き込みの失敗などは起きうるが、それを伝える必要がある。
  • 6.2 失敗をどうやって伝える? - how?

    1. 返り値で失敗を伝える - 失敗を見落とす、エラー処理がifの中にあるのでコードが読みづらくなるなどの問題がある

    2. 失敗したらジャンプする - 失敗したときにジャンプする場所を決めておくことでコードの可読性は向上する。

  • 6.3 失敗しそうなコードを囲む構文 - why?

    • 例外の可能性を忘れる/不適切な例外処理を書くというもんだいを解決するためには、失敗しそうな処理を囲ってエラーをあとに書くという try ~ catch が必要。
  • 6.4 出口を1つにしたい - why?

    • try, catch だけでなく finally も生まれた。

    • 対になる処理(file の lock , unlock など)を絶対に行う必要があるから。

    • D言語では scope(exit) というスコープガードを発明。

  • 6.5 どういうときに例外を投げるか

    • 何が例外的状況なのかは一通りではない

    • 筆者としては、すぐ例外を投げてくれたほうが異常事態に気づきやすいので良い(フェイルファースト)

  • 6.6 例外の伝搬

    • 関数fの中で呼ばれた関数gで例外が発生したとき、gで処理されない例外はfで処理されるか、fの上の関数に伝搬していく。

      • ある関数が発生させうる例外を特定するためにはその関数が呼び出しているすべての関数をチェックする必要がある。
    • Javaの検査例外では、例外を投げる可能性のあるメソッドを呼ぶときにその例外を処理するか自分も投げるのかを明示する。

      • かなり良いが、Javaの実装だと苦しい。

      • 型システムでどうにかならないか?

  • 6.7 まとめ

第7章 名前とスコープ

なぜ名前の有効範囲を制限する必要があったのか?

  • 7.1 名前はなぜ必要だったか

    • メモリの番地よりも人にとってわかりやすい

    • 名前は衝突しうるので、長い変数名をつけることとスコープを利用することが対策としてうまれた。

  • 7.2 スコープの進化 - what?

    1. 動的スコープ - 入り口で元の値をとっておき、出口で戻す。呼び出された関数のスコープが呼び出し元と同じになってしまう。

    2. 静的スコープ - 関数ごとの名前と値の対応表を専用に持っているので、影響範囲を関数内だけに限定できる。←これが普通

  • 7.3 静的スコープは完成形?

    • ネストした関数でのスコープや、外の関数への束縛など問題は残っており、各言語が頑張って解決している
  • 7.4 まとめ

第8章 型

  • 8.1 型とは何か

    • ビット列をどのように解釈するのかを定めた追加の情報
  • 8.2 数値をオンとオフで表現する方法

    • 0~9をランプで表現するためには、位取りや7セグメント、そろばん形式など多くの形式がある
  • 8.3 1つの位に必要なランプはいくつか?

    • 4つで良いが、2新方で表せばもっと節約できる。
  • 8.4 実数はどうやって表現しよう

    • 固定小数点数ではどこまでを小数部に決めたかを覚えておく必要があり大変。

    • どこからか少数部かの情報自体を値に含めれば良い→浮動小数点数

  • 8.5 型は何のため?

    • コンピュータにとってはビット列が何を表しているかわからない→言語処理系で宣言しておけばどのように処理すればよいかわかる。
  • 8.6 型のいろいろな展開

    • 既存の型を組み合わせて作るユーザー定義型や、さらにデータの処理の仕方もまとめたクラスへと発展した。

    • 方があっているかはコンパイラがチェックできるので、型を仕様として用いることができるようになった。

    • 構成要素の型の一部が変わる型が生まれた。ex. Javaジェネリクス, Haskellの型コンストラクタ。

    • 動的型付け: 情報の種類と値をセットにした上でメモリに保存することで、言語処理系で宣言する必要がなくなった。

      • メモリ上で同じように扱えるように設計されている。

      • 柔軟な処理ができるものの、コンパイル時に型の整合性チェックができなくなった。

    • 型推論

      • 型チェックかつ型宣言なし

      • より強力な型推論によってバグがないことを証明しようとする研究もある

  • 8.7 まとめ

第9章 コンテナと文字列

「いくつものモノを入れるためのモノ」について、色々な種類がある理由とその長所と短所について。後半は特に文字列について。

  • 9.1 いろいろな種類のコンテナがある - what?

    • e.g. Cの配列、 Lispのリスト、 Pythonのタプル、Rubyのアレイ……

    • これらをまとめてコンテナと呼ぶ

  • 9.2 なぜいろいろな種類のコンテナがあるのか

    • それぞれのコンテナに長所と短所があるから。

    • ex. 配列と連結リストでは、操作によって効率の優劣が違う。

  • 9.3 辞書,ハッシュ,連想配列 - what?

    • 「キー: 値」という組み合わせ。

    • 万能のコンテナはない

  • 9.4 文字とは何か

    • これを文字と呼びましょうとし決めた記号の集合。「文字集合

    • 文字集合をデジタルに表現するための符号化の方法が文字符号化方式であり、結局UTF-8が標準になりそう。

      • 混じってると困る。
  • 9.5 文字列とは何か

  • 9.6 まとめ

    • 文字列の実現へのアプローチにはいくつかの方法があるが、実装で解決するだけでなく標準化での解決も進んでいる。

第10章 並行処理

同時に複数の処理が実行される時何が起こっているのか。どんな問題が起こりうるのか。

  • 10.1 並行処理とは何か

    • 複数の処理を時間軸上でオーバラップして実行すること。
  • 10.2 細かく区切って実行する -what

    • 実際には、 人間が気付かないくらい短い間隔で複数の処理を切り替えながら実行している
  • 10.3 処理を切り替える2通りの方法 -what

  • 10.4 競合状態を防ぐには -how

    • 競合状態が起こるには3つの条件がある。

      1. 2つの処理が変数を共有している。

      2. 少なくとも1つの処理がその変数を書き換える。

      3. 一方の処理が一段落付く前にもう一方の処理が割り込む可能性がある。

    • 3条件のどれかを解消すれば良い

      1. 共有しない: メモリを共有しない方法・メッセージを送り合う方法(アクターモデル)

      2. 書き換えない: Immutable パターン, const, val などなど

      3. 割り込まない: 協調的なスレッドを作る(RubyのFiberなど)、割り込まれたくないときは印をつける(ロック、mutex、セマフォ)

  • 10.5 ロックの問題点と解決策 -what

    • デッドロック・合成できない(アトミックに実行されて欲しい一連の処理を扱えない)

    • DBのトランザクション理論を転用して、トランザクショナルメモリというものができた。→これからどうなる?

  • 10.6 まとめ

第11章 オブジェクトとクラス

オブジェクト指向という言葉がさすものは言語によって異なります。」

  • 11.1 オブジェクト指向とは何か

  • 11.2 変数と関数を束ねて模型を作る方法

    • クラス以外の3つをまず以下で説明
  • 11.3 方法1 モジュール,パッケージ

    • 関連性の強い関数や変数のまとまりを表現するもの。

    • Perlでの例。最初はデータもモジュール(パッケージ)に含めていたが、データを外部のハッシュにし、blessでモジュールと紐付けて実現。

  • 11.4 方法2 関数もハッシュに入れる

    • JSでは関数もハッシュ(Object)に入れる。

    • ただObjectに入れるだけだと各Objectに関数があってメモリの無駄なので、prototypeに関数を入れておくことでオブジェクト指向を実現。

  • 11.5 方法3 クロージャ

  • 11.6 方法4 クラス

    • 言語によってクラスの主要な意味は異なるが、主に3つの意味がある。

      • まとまったものを作る生成器(上述の例)

      • どういう操作が可能かという仕様としてのユーザー定義型(C++での主目的)

      • 継承しコードを再利用する単位

  • 11.7 まとめ

第12章 継承によるコードの再利用

いろいろな継承の仕組みの長所と短所

  • 12.1 継承とは

    • 実装を自動で引き継ぐ考え方。主に3つの考え方がある。

      • 一般化/特殊化

      • 共通部分の抽出 - 複数のクラスの共通部分を親クラスとして抽出する

      • 差分実装 - 変更分だけ実装していく → コードの場所がわかりづらくなるという批判あり。

    • リスコフの置換原則(継承はis-aの関係でなければならない)

  • 12.2 多重継承 -what

    • 現実世界では、1つのモノが複数の分類に属することがほとんど。→多重継承
  • 12.3 多重継承の問題点──またしても衝突!

    • 多重継承した結果複数のクラスで同じメソッドを持っていたらどうするか?

      • 多重継承の禁止(Javaなど) - 委譲を用いてオブジェクトを持つにとどめる(依存性の注入)。インターフェースを用いる。

      • メソッド解決順序を工夫する(Pythonなど) - 深さ優先探索(Python2.3まで)、C3線形化(Python2.3以降)

      • 処理を混ぜ込む:Mix-in(Rubyなど) - 再利用したい機能だけを持った小さなクラスを混ぜ込む。(衝突は解決できない)

      • トレイト - 再利用の単位としての役割をインスタンス生成機としての役割から分離する。Rubyのmodule同様メソッドをまとめる束だが、mix-inでの衝突時に明示的にエラーにする。トレイトを利用するクラスに必要とするメソッドを明示しておく。

  • 12.4 まとめ

ほしいものを頂いた

誰ですか!院試前の僕に『オブジェクト指向入門』と『型システム入門』を買ってくださったのは!

段ボール届いたとき重すぎて絶対何かヤバいやつだと思いましたよ!

 

ありがとうございますこれからも誠意勉強してまいります本当にありがとうございます(院試ヤバいです)

 


f:id:SWIMATH2:20160806132432j:image