ねぎ嫌い

始業前に学んだことを小出しに。最近はHacker Newsの人気記事をまとめてみたり。

2017-10-23 Simple Ways to Be Better at Remembering

原文:www.nytimes.com

何かを思い出すための簡単な方法についてのお話。

平均的な1日では、人は47回もスマートフォンを確認している。
18歳から24歳に限って言えばその倍近くにも登る。
この状態は、何かを覚えておくのには難しい。
スマートフォンは歩行や会話、思考を変え、我々はほとんど追いついていない。

全てはGoogle検索によってほぼ瞬時に手に入れることが出来るのに、
何が役に立たない情報を保持しておく動機になるのだろうか。

このインスタントファクトはどの情報をフィルタリングして保持しておくかの判断を曇らせる。
もはや些細なデータを覚えておくことは重視されず、
大きい認知スペースを押し付けられている。
それではどのように覚えているものを選択しているのだろうか。

2種類の思い出があり、
1つは意識的な経験から作られる「明示的」なものと、
もう1つは過去に経験した恐ろしい体験や未知の出来事といった「暗黙的」なものである。

思い出は時の経過とともに変化する、あてにならないものである。
長期記憶を呼び出すことは、新しいコンテキストを加えた短期記憶として思い出す。
ゆえに、記憶は再構築であり、写真記録ではない。
合理的な目的のために、脳は永遠にその記憶を再録し、
多くのエラーを起こしやすくしてしまう。

多くの人は1つのタスクに継続的・持続的に取り組み、
より多くの成果を上げる可能性があることに気づいていない。
Facebook上で1つの会話から逃げ、別の会話に移ることは爽快かもしれないが、
人はこのプロセスで何を失ったのか気づいていない。
これは、頭の上で美味しいスープを注ぐようなものである。
タスク間の取り組みを最善の方法で共有できていると思っている人は、
実際には多くのものが欠落している。

脳は、処理や扱えることに制限がある。
とはいえ、それらを改善することは出来る。

Repeat After Me

思っているよりも簡単な方法の1つは、タスクを繰り返すこと。
何度も読んだり、単語を繰り返し言葉にしたり。
短期記憶を長期記憶に移動させるのに、最も適した方法である。
これをやるために、1度に1つのタスクに集中することを再教育しなければいけない。
悲しいことに、我々は既に生産的であると確信しているため、この方法を避けてしまう。

何かを学ぶとき、新しいコネクションが脳内で生成される。
学んだことを思い出すために、若いときはこういうことをやっていただろう。
単語を繰り返したり、正しい答えにたどり着くまで考えやアイディアを繰り返したり。

Take Your Time

詰め込み型の勉強のことは忘れる。
大学で上手く行かなかったように、現在も上手く行かない。
間隔反復が最も良い方法だろう。

脳に基本的な事実を詰め込むことは長期記憶において忘れさせてしまう。
知識や技能をなんども復習する時、それはとどまる。
なので、覚えようとしていることを日常生活に盛り込むことができれば、
記憶にとどめておくチャンスは劇的に向上する。

しかし、一度でも知識の復習を止めると、記憶力は大いに抜け落ちてしまう。
研究者はそれを忘却曲線と呼ぶ。

それを乗り越えるために、数日かけて繰り返すことと、効果を自身で確かめること。
ただし、多くのことを同時に繰り返すことはあまり効果が出ないので、
上手く効果の出せる健康的な方法を探すことに気をつける。
これは新しい言語に取り組み効果的な方法である。

Sit Down and Stay Put

記憶とフォーカスは密接に関連している。
フォーカスを改善するための一つの方法として、オフィスを組み替えることを提案している。
シリコンバレーでよくあるオープンオフィスは実際には生産性を大幅に低下させると考えられている。
同僚がドローンを操縦したり、スナックを食べたりしているそばで、
どのようにして一つのタスクに集中することが出来るだろうか。

オープンな職場の復活はこのようなシチュエーションを助けられない。
机もなく、物理的な遮蔽物もなく、プライバシーもなく、ただ遊具だけは多くある職場に言及している。
ヨガ用の部屋、ロッククライミングやガーデンは大きな特典になるが、
多数の挑発のなかで締め切りを守ることは難しくなる。

多数の研究で、先延ばしはストレスになり、完全にフォーカスを殺すことを発見されている。
ウェブサーフィンといった興味をそそるが無用なタスクをやめ、働くのに必要なことだけに取り組む。
そうするとフォーカスは高まり、記憶も改善する。
いわゆる「ライフハック」を追求し、お互いに不正行為を働いていない時、
フォーカスと記憶のパフォーマンスはより良くなる。

Incentivize Moments and Read Cues

精神は常にさまよっている。
学生に対して頻繁にテストを実施することで、
彼らは小テストが実施されることがわかるようになるため、 結果としてフォーカスを促すことになる。
ハーバードの調査ではこの手法は白昼夢を50%削減し、
結果を改善していると報告している。

このトリックはフォーカスにある。
ウェブサーフィンといった幾つかのタスクでは、分割された注意は無害に聞こえるが、
運転しているときはそのタスク以外何もない。
その忘却は人生全体の経過を変える可能性があり、最も深刻な脆弱性は記憶にある。

鍵のようなアイテムに視覚的あるいは言語的なきっかけを採用して、
場所やものを関連付ける方法を提案している。
我々の電子的なデバイスは想起することを助け、
例えば赤子を車のなかに置き去ったことを思い出させてくれる。
馬鹿げた話に聞こえるが、我々が失敗するときの悲劇でもある。

記憶は非常に”きっかけ”に依存している。
何かを参照することをぼんやりとした記憶障害(absent-minded memory failure)と呼ぶ。
多くの人は自分には決して起こらないことだと言うが、おおくのひとは既に起こしてしまっている。
このきっかけがなければ、ほとんどすべてのものを忘れる可能性がある。

ぼんやりとした記憶障害について本当にトリッキーなことは、
反応を起こす必要がある瞬間にきっかけが存在しなければ、
なににでも影響を与えられる可能性がある、ということである。

単純な方法は、リマインダーをセットすることである。
また、次のテクニックを組み合わせることも良い。

  • ポストイットにリマインダーを書いて、机の上に張っておくことで繰り返し目につくことを強制させる
  • 間隔反復の練習を実施する

これらのアプローチを組み合わせて、記憶を構築する。
近代の生活に保証はほとんどないが、これらのヒントを使うことできっと改善することができる。

多くの人々は注意散漫を扱うことが出来る、と自信過剰になっている。
1度に2つのことを行うことは常に影響している。
お金を払うときのように、注意を払うときは自身のおかれた状況を認識し、理解すること。 状況によっては問題にならないかもしれないが、その他の状況では全てを変えてしまうかもしれない。

2017-12-05 Introduction to logic programming with Prolog

原文:Introduction to logic programming with Prolog

Prologと言う論理型言語についてのお話。

筆者は大学時代に言語とパラダイムについて研究をしていて、
その中で多くの言語に触れ、良し悪しを把握してきた。
そのなかで、論理型言語であるPrologを計量言語学とAIに多く用いていた。

この記事ではPrologの軽い紹介と不可欠な機能について述べられている。

そもそも、なぜPrologやその他の言語を学ぶモチベーションがあるのかというと、
「達人プログラマー」でも以下に述べられているように、多くの言語を学ぶことで多くの解決策を仕入れることが出来るからである。

毎年少なくとも1つの言語を学ぶ。
異なる言語は同じ問題を異なる方法で解決している。
異なるアプローチを学ぶことは、考え方を広げ、同じ轍を踏まないように積み上げられる。
付け加えると、インターネット上で自由に使える豊富なソフトウェアのおかげで、現在では多くの言語を学ぶことははるかに簡単になっている。

例えば数独パズルをJavaやC、Prologで解くなど。

まず、論理型言語が何かについて述べる。

どのように完了するか、ではなく何がしたいかを述べる

論理型言語は数学の論理を基礎に持つプログラミングのパラダイムの1つである。
JavaやCと比べると、論理型言語で書かれたプログラムは連続した説明書のように構成されているわけではなく、公理の集合やオブジェクト間の関係の規則で成り立っている。
同様に命令型ではなく、宣言型のアプローチを採用している。

Prologはホーン節(第一階述語論理の部分集合)を基にしていて、多くの論理型言語と同様である。
Prologは1972年に初めて登場したが、現在では定理証明やエキスパートシステム自然言語処理あるいはAIにの領域で非常によく使われている。
また、Erlangの開発にも大きく影響を与えている。

他に、以下についても触れている

  • 言語構造
  • 基本的な「事実」とクエリ
  • ユニフィケーション
  • リスト表記
  • Prolog シェル
  • 回帰処理
  • 四色定理

2017-10-22 C++ Tips of the Week

原文:abseil.io

C++のtipsを週に一度書いていくウェブサイトのお話。

このウェブサイト自体はオープンソースC++の標準ライブラリ Abseilで、
このページはその中で議論されているC++のTipsを転記していく。

もともとはGoogleで行われてたTips of the Week(TotW)をAbseilのコミュニティでもやろうというもの。

2017-10-19 DevDocs API Documentation

原文:devdocs.io

複数のAPIドキュメントをまとめたDevDocsのお話。

各言語のリファレンスが一覧性高く、速く、検索しやすいインターフェースで提供されている。
めっちゃ便利そう。

2017-10-18 Why we switched from Python to Go

原文:getstream.io

PythonからGoを使い始めた経緯のお話。

既に経験のある言語から新しい言語に切り替えるのは大きなステップが必要になる。
streamでは主要なプログラミング言語PythonからGoに切り替えた。
本記事では、なぜPythonからGoに切り替えたのかの理由を述べている。

理由1. パフォーマンス

GoのパフォーマンスはJavaC++と同じくらい良い。
彼らのチームではGoのほうがPythonより30倍も早かった。

理由2. 言語のパフォーマンス

多くのアプリケーションにおいてプログラミング言語
ただアプリケーションとデータベースをつなぎ合わせるノリにすぎない。
言語自身のパフォーマンスはそんなに問題にならない。

彼らは500以上の会社と2億人以上のエンドユーザーにAPIを供給している。
Cassandra、PostgreSQL、Redisなどで最適化しているが、言語上の限界に達してしまった。

Pythonは素晴らしい言語であるが、serialization/deserialization、
ランキング、アグリゲーションといったユースケースでパフォーマンスが出なかった。
Cassandraは1msでデータを見つけるが、Pythonは10msでオブジェクトに詰めていた。

理由3. 開発者の生産性と創造性のなさ

Goのチュートリアルにあった以下のコードを見てほしい。

package main

type openWeatherMap struct{}

func (w openWeatherMap) temperature(city string) (float64, error) {
    resp, err := http.Get("http://api.openweathermap.org/data/2.5/weather?APPID=YOUR_API_KEY&q=" + city)
    if err != nil {
        return 0, err
    }

    defer resp.Body.Close()

    var d struct {
        Main struct {
            Kelvin float64 `json:"temp"`
        } `json:"main"`
    }

    if err := json.NewDecoder(resp.Body).Decode(&d); err != nil {
        return 0, err
    }

    log.Printf("openWeatherMap: %s: %.2f", city, d.Main.Kelvin)
    return d.Main.Kelvin, nil
}

このコード例には以下の要素が詰められている。

  • 複数割当(multiple assignments)
  • 構造体
  • ポインタ
  • フォーマッティング
  • ビルトインHTTPライブラリ

もしPythonで同じことをやろうとすると、

  • MetaClassesを使ってクラスの初期化をする
  • True/Falseをスワップアウトする
  • ビルトイン関数のリストに関数を追加する
  • 魔法のメソッド経由でオペレーターをオーバーロードする

これらの機能で遊ぶのは楽しいが、多くのプログラマが同意するように、
多くの場合これらのコードは理解するために読むのが難しくなる。

Goは基本に忠実にさせる。
誰が書いたコードであっても簡単に理解するために読めるようにしてくれている。

NOTE: どれだけ簡単か、はユースケースに因る。単純なCRUD APIであればDjangoDRFRailsを使うほうが良い。

理由4. 同期実行とチャネル

言語として、Goは物事を単純に保とうとする。
goroutineとchannelによって単純な言語を実現している。
goroutineは軽量のスレッド化手法で、
channelはgoroutine間のコミュニケーションを取る優れた方法である。

goroutineは非常に低コストで生成でき、メモリもわずかしか使用しない。
そのため、一度に何百、何千ものgoroutineを走らせることが出来る。

goroutine間の通信にはchannelを使う事ができる。
Goのランタイムが全ての複雑性をコントロールしてくれる。
goroutineとchannelベースの手法が同期実行を簡単に
使用可能な全てのCPUコアを使用させ、同期IOを扱う。
Python/Javaと比べ、Goは最低限の定型文のみが必要になるだけである。

理由5. 短いコンパイル時間

JavaC++に比べて非常に短い時間でコンパイルすることが出来る。

理由6. チームを構成する力がある

Goを書ける開発者はC++Javaといった古い言語の開発者よりも多くはない。
StackOverflowによると38%の開発者はJavaを書け、19%がC++を書けるが、
Goに関して言えば4.6%しかいない。
Githubのデータも似たような傾向を示している。

幸いにもGoは非常に簡単かつシンプルに学ぶことが出来る言語である。
基本的な機能を提供し、必要なものはそれ以外にない。
その簡潔さでPythonをかける開発者を1ヶ月以内に効率的に出来る。

そのため、他の言語に比べチームを構成するのに容易い。

理由7. 強力なエコシステムがある

20人以下の規模のチームにおいてエコシステムは問題になる。
小さな改革を起こさなければ、顧客に価値を提供することは出来ない。
Goは我々の使用しているツールに対してサポートをしている。
充実したライブラリは既に揃っていて、RedisやRabitMQ、PostgreSQL
テンプレートエンジンやタスクスケジューリング、文法解析などがある。

GoのエコシステムはRustやElixirといった他の新しい言語に概ね勝っている。
Javapython、Nodeなどには負けているが、
必要としている基本的なライブラリは既に使用可能である。

理由8. コードの強制フォーマッティング

Pythonにおけるautopop8のような強制フォーマッティングツールが備わっている。
タブ - スペース論争のようなものはもう必要ない。
Gofmtが全てを解決してくれる。

理由9. gRPCとプロトコルバッファ

GoはプロトコルバッファとgRPCを快適にサポートしている。
これらの2つのツールはRPC経由でのマイクロサービスを立てるのに適している。
マニフェストを書くだけで、RPC呼び出しを使える。
サーバーとクライアントのコードはマニフェストから自動生成される。

同じマニフェストから、クライアントのコードをJava, C++, PythonRubyで生成できる。
これ以上曖昧なRESTのエンドポイントは必要ない。

Goが優れていない点

不利1. フレームワークの不足

Goはまだ支配的なフレームワークを有していない。
これはGoコミュニティ内で白熱した論争のトピックとなっているが、
今のところフレームワークを使うべきではない、という。
もしシンプルなCRUD APIを立てたかったら、 DjangoRailsを使うほうが良い。

不利2. エラーハンドリング

Goでは、呼び出し元のコードでエラーをハンドリングする必要がある。
そのため、エンドユーザーに対して意味のあるエラーを返すのを簡単に忘れてしまう。

エラーのパッケージはこの問題をエラーにコンテキストとスタックトレースを追加することで解決している。

他の問題として、簡単にアクシデントによるエラー処理を忘れてしまう。
errcheckやmegacheckのような静的解析ツールはこのミスを便利に防いでくれる。

不利3. パッケージ管理

Goのパッケージ管理は決して完璧ではない。
デフォルトでは依存するライブラリのバージョンを指定する方法はなく、
再現性のあるビルドをする方法もない。
Python, Node, Rubyのいずれも優れたパッケージ管理システムを持っている。
しかし、正しいツールを使えばGoのパッケージ管理もかなり良い。

Depを使って依存性を予定したバージョンで管理することが出来る。
それとは別にVirtual Goというオープンソースツールもある。