真面目なブログはこっち 👉 blog.s64.jp

蟻本第2版21ページの問題をHaskellで書く

FPについて学び直しメモ - 🍥shuma_yoshiokaに引き続き、プログラミング学び直し日記。「蟻本」こと「プログラミングコンテストチャレンジブック 第2版」を読みながら、問題をHaskellで解いてゆく試み。

プログラミングコンテストチャレンジブック [第2版] ?問題解決のアルゴリズム活用力とコーディングテクニックを鍛える?

プログラミングコンテストチャレンジブック [第2版] ?問題解決のアルゴリズム活用力とコーディングテクニックを鍛える?

21ページより「三角形」の問題。類似問題はこちら。

f1 (x:xs) = maximum [(f2 x xs), (f1 xs)]
f1 [] = 0

f2 x (y:ys) = maximum [(f3 x y ys), (f2 x ys)]
f2 _ [] = 0

f3 x y (z:zs) = maximum [(f4 (maximum [x, y, z]) (x + y + z)), (f3 x y zs)]
f3 _ _ [] = 0

f4 max len = if (len - max) > max then len else 0

main :: IO ()
main = do
    _ <- (readLn :: IO Int) -- n
    as <- (map read . words) <$> getLine :: IO [Int]
    print $ f1 as

ほぼ初めてということもあり、ループを使わず再帰脳づくりするのにかなり時間掛かった

FPについて学び直しメモ

OOPについて学び直しメモ - 🍥shuma_yoshioka に引き続き、雰囲気でプログラミングしているのでFP (Functional Programming, 関数型プログラミング) について雑に学び直した。
学び直しとは言うけど、そもそも関数型プログラミングは勉強したことないし、もっと言うとちゃんとHaskell書いたのも初めてになる。

手続型言語と関数型言語の違い

明確な定義は無いらしいが、言語自体に 関数の再帰呼出しによるプログラムの数式化 を助ける機構があるか否か、がポイントとなるもよう。

Javaはオブジェクトを手続型のように扱えるのがコンセプトとなる言語なので、このような言語は オブジェクト指向型言語 などのように分類されやすい (手続き型言語として分類されにくい) 。よって、手続き型言語には例えば PHP, Python などが挙げられやすい。
対し関数型として挙げられやすい言語は、Lisp, Haskell, OCaml, Erlang, Scala など。(Scalaはハイブリッドと言われがちだが)

Javaが「全てがオブジェクトである」のと同じように、関数型言語は「全てが数式である」と言える。
オブジェクト指向言語は、たとえ同じメソッドであってもそのオブジェクトが持つ状態により暗黙的に値が変わる場合が多々ある。
あまり良い例とは言い難いが、パッと出せるとこで言うと例えば、

class MyCls {
  
  private final int state1;
  private final int state2;

  public MyCls(int state1, int state2) {
    this.state1 = state1;
    this.state2 = state2;
  }

  public int calcState(int x) {
    return x * (state1 + state2);
  }
}

// App.java
public class App {

  public static void main(String[] args) {
    MyCls obj = new MyCls(2, 3);
    System.out.println(obj.calcState(5)) // 上の行を知らないと、ここの式で何が出力されるかわからない
  }
}

というのが発生する。これは決して常に悪く作用するわけではないが、参照透過性が無いと言える。
参照透過性は、入力が同じなら同じ作用と同じ値を返す状態で成立する。つまり手計算した値を直接埋め込んでも大丈夫な状態でなければいけない。

対し関数型言語とし例えばHaskellの場合、以下のようにするだろう。

data MyState = MyState { state1 :: Int, state2 :: Int }

calcState x y = x * (state1 y + state2 y)

main = do
  let my = MyState { state1 = 2, state2 = 3 }
  print $ calcState 5 my

このような参照透過性を実現する強い制約が関数型言語をそれたらしめていると言える。
そしてこのような制約のおかげで、再帰呼出しによる数式化が助けられている。

fibSeq x y = [x] ++ fibSeq y (x + y)
-- または `fibSeq x y = x : fibSeq y (x + y)`

main = do
  print $ take 10 $ fibSeq 0 1

{-
  フィボナッチ数列を求める簡単な例。
  読み方:
    1. 第一引数のみを持った配列をつくる
    2. xとyを足し合わせたものを求める
    3. 再帰呼び出しで配列を取る。第一引数はy、第二引数はさきほど足し合わせたもの
    4. それらの配列を連結する。第一引数の次に第二引数という風に結合され、さらにそれを足し合わせたもの、という形に無限に求め続ける
    5. `take 10`を使い、先頭から10番目の要素までを取り出す (現れた時点で辞める)
    6. それを標準出力へ
-}

なおパターンマッチなども特徴的だが、これらはあくまでも言語機能、糖衣構文のようなものでしかないので深くは言及しない。

関数型言語のエッセンス

関数型言語の特徴として、前述のとおり数式化可能なこと、参照透明性が高いことが挙げられる。
そうした特徴は様々な非関数型言語へも取り入れられている。たとえば、JavaのStream, Reactive Extensionsなども関数型言語の影響を受けている。

関数を引数とした関数を高階関数 (ハイオーダー ファンクション) という。Reactive ExtensionsなどのRxと呼ばれるライブラリは、FRP (Functional Reactive Programming) を実現するもの。Reactive、Observableは非同期プログラミングにおける概念なので、ここでは深く言及しない。
またKotlinなどはCollectionsとして同様の高階関数を提供している。

おしまい

他にも触っておくべきことが多そうだが、恥ずかしながら関数型言語の利用経験が少ないためすぐに思いつかなかった。そのため一旦ここで区切ることにする。
参考にした記事は、

など。

OOPについて学び直しメモ

雰囲気でプログラミングをしているので、OOP (Object-Oriented-Programming, オブジェクト指向プログラミング) について雑に学び直した。

オブジェクトとは, OOPの基本

オブジェクトとはモノのこと。オブジェクト指向とは、モノを操作する (操作できるモノを作る) プログラミングの方向性のこと。

モノには様々あるが、例えばリモコンやゲームコントローラなどのアクションを起こせる物体を想像すると良い。
可能な操作が一覧されており、命令を行うと内部の仕組みを知らなくても (隠蔽されていても) 意図した動作になる。
そうした「リモコン」と「テレビ」、「ゲームコントローラ」と「ゲーム機」のようなモノとモノ同士、つまりオブジェクトの操作を組み合わせてプログラミングしていこうという、現実世界での任務遂行方法を模倣したプログラミング手法と言える。

カプセル化 (エンカプセレーション)

OOPにおける特徴的な概念として、カプセル化が挙げられる。
前述のとおり、リモコンやゲームコントローラの使い方は知っていても、その内部の仕組みは知らないし、知らなくても問題なく利用できる。
逆に直接基盤などへ触れられるようになっていると、意図されていない操作で破壊してしまう可能性がある。
そのような操作を防ぐため、利用者向けにはボタンで操作を、ランプで状態の確認をできるようにしている。

カプセル化とはつまり、オブジェクトの持つフィールドを直接操作する必要がないよう、メソッドで覆うことを指す。これにより、外側の操作を変えずとも、メソッドの実装で実際のフィールドに対する操作を安全に、あらゆる箇所で行える。

継承 (インヘリタンス)

継承関係とは、要はIs-a関係の話である。つまり、B extends Aの場合、BはAの一種 (亜種)であると判断し、Aとして扱うこともできることの話である。
具体例で言うと、Viewの一種としてButtonやProgressBarが存在し、これらには例えば共通の「描画位置情報を返しなさい」というメソッドがあるかもしれない。それらは恐らく各々の描画情報さえあればそれを元に計算が可能であり、別の実装を必要としない。そういった共通の処理を "継承" することを指す。

紛らわしいが、共通の "メソッド名" で各々の異なる実装を呼べることは多態性になるため継承ではない。継承で話しているのはinterfaceの話である。overrideではない。

もう少し現実寄りの例にする。例えば "果物" の種類として "リンゴ", "バナナ" があるとする。果物の定義に確固たるものは無いが、たとえば ”草木の実である" とする。
つまり裏を返せばリンゴとバナナには共通処理として「木から実る機能」が存在することになる。これを各果物ごとに実装すると、人的ミスにより定義が揺らぎかねない。もしかしたら間違えて土から生やしてしまうかもしれない。

なので基底となる「果物」自体に木から実る機能を実装してしまえば、手間も掛からずミスも防げる。

多態性 (ポリモーフィズム)

多くのリモコンやゲームコントローラは、たとえ機種が異なっても説明書を読まずに利用できる。その理由には、同様のラベル、同様の形状など、説明を不要とする工夫が挙げられる。そしてそのお蔭で、知らずとも期待した動作をする。
しかしながら実際には、ボタンを押す操作により送出される信号は機種により異なる。もちろん画面上の表示も異なるだろう。

このように具体的な中身の処理を知らずとも様々な処理が起こりうるのが多態性である。同様のラベルを持つものに意味付けをし、具体的な処理は実装に任せることができる。

カプセル化で気をつけること (ワイの経験則)

カプセル化すればなんでも隠蔽できると思っちゃダメ。あくまでも1つのオブジェクト (クラス) は1つの役割だけを持つようにする。例えば、データ構造を持つ、他のデータ構造にマッピングする、該当するデータ構造を複数の永続化機構のいずれかから取り出す、など。
リンゴは自身の特徴や状態だけを持つと期待されるため、もしキャッシュ機能が埋め込まれていれば誰も想像できず、実装者は意図しない挙動で混乱するだろう。

継承や多態性で気をつけること (ワイの経験則)

自分のサブクラスになり得るものにより処理を変えたりしちゃダメ。たとえば「果物」内で「もし自分がリンゴなら」「もし自分がバナナなら」という実装をしてはいけない。何故ならあくまでも「果物」の一種に「リンゴ」や「バナナ」があるのであって、「果物」自身は自分が何になり得るのかなど気にしちゃいないから。「自分は果物だ」としか知らないし、実際に「果物」として扱われる際にはそれにより挙動が変わってしまってはいけない。実装者はデバッグ時に意図しない挙動が発生し混乱するだろう。

OOPの良いところ

適切な名前付けで実装を担保するため、変化に強い。各オブジェクトが名付けされたとおりの小さな機能のみを持つため、その名前付けされた処理が正しく実装されている限りはオブジェクト間で正しく作用する。

OOPの残念なところ

理解するのがどうも難しいらしい。関わる開発者全員がOOPに精通していること、つまり適切な名前付けと責務分離が可能なことを前提としているため、誰か1人でも理解していない場合、暗黙の了解が壊れてしまう。何が起きるかというと、各 "気をつけること" で書いていることが発生し、バグの温床になる。

各オブジェクトがあって、それをどのように調理するか、という思考を全員が身に付けるまでは手続型言語の方が良いかもしれない。

おしまい

次は、FPについて学び直しメモ - 🍥shuma_yoshioka

DiscordにSpotifyの再生中楽曲を表示する`spoticord`をWindowsで使う

弟が使い方わからなくて困ってたので、他にもわからない人居て困ってるかもと思いメモ。

spoticordとは

nations/spoticord はDiscordのステータスにSpotifyで再生中の楽曲を表示できるコマンドラインツールです。

GitHub上で公開されています。

github.com

必要なもの

実行にあたっての必須要件は以下です。

  • Node.js 8 以降
  • npm 5 以降 (nodeに付属)

今回はWindowsへ導入するにあたり、さらに以下を追加します。

1. Git for Windowsをインストールする

Gitはソフトウェアのソースコードを管理するツールです。今回は主にspoticordのダウンロード / アップデートで内部的に使われます。
Git for Windows の Download から、32bit, 64bitなどお使いのOSに合ったインストーラをダウンロードします。

私の環境の場合、記事執筆時点ではGit-2.15.1.2-64-bit.exeが該当します。

f:id:S64:20171211192814p:plain

インストーラのダウンロードが完了したら、実行しインストールを進めてください。途中複数の選択肢が表示されますが、多くの場合はそのままで問題ありません。

2. GitHubへ会員登録する

この手順は必須ではありませんが、ダウンロード時の制約を受けにくくなる等セットアップをシンプルにできるため行うことを推奨します。

GitHub.comはGitで管理されたソフトウェアを管理・公開できるサービスです。ソフトウェアの利用のみであったり、ソースコードを公開する場合は無償で利用できます。
github.com にアクセスし、Sign upから登録してください。

3. GitHub Desktopをインストールする

GitHub Desktopは GitやGitHub.com上で公開されているソフトウェアを、Git初心者でも簡単に扱えるアプリケーションです。
GitHub Desktop からインストーラをダウンロードします。

f:id:S64:20171211194946p:plain

インストーラのダウンロードが完了したら、実行しインストールを進めます。インストールは自動で進められます。
自動でのインストールが完了すると、以下の画面が表示されます。Sign into GitHub.comをクリックし、さきほど作成したGitHub.comのアカウント情報を入力してください。
もしアカウントを作成しなかった場合、下部のSkip this stepを選択します。

f:id:S64:20171211195334p:plain

入力し進めていくとConfigure Gitなどステップが表示されますが、アカウント情報を入力した場合には原則そのままで問題ありません。最後のステップまで進めFinishをクリックしてください。

4. nodistをインストールする

node (Node.js) はJavaScriptを実行するツールです。nodistはWIndows上でのセットアップを簡略化し、複数バージョンの共存を可能にできるツールです。

nodistのReleasesから、最新のインストーラをダウンロードします。記事執筆時点では、NodistSetup-v0.8.8.exeです。
ダウンロードが完了したら、そのままインストールを進めてください。

5. nodistを使いnodeをインストールする

nodistのインストールが完了したら、nodistでインストールできるnodeの一覧を確認します。コマンドプロンプト (またはPowerShell) を起動し、以下のコマンドを実行します。

nodist dist

列挙されたバージョンの中から、インストールしたいバージョンを確認し、インストール用のコマンドを実行します。例えば今回の場合、spoticordの最低要件を満たしかつ最新の長期サポート版となる8.9.3が良いかもしれません。その場合、以下のコマンドを実行します。

nodist + 8.9.3

プロンプトが返ってきたら、システムで使うnodeのバージョンを設定します。今回は8.9.3を選んだため、以下のようになります。

nodist 8.9.3

Default global pacakge update dsuccessful.と表示されれば問題ありません。

6. spoticordのソースコードをcloneする

GitHub Desktopを開き、[File] -> [Clone repository...] をクリックします。表示されたダイアログのURLタブへ移動し、Repository URL欄に以下のURLを入力します。

git@github.com:nations/spoticord.git

f:id:S64:20171211201519p:plain

[Clone]をクリックし、ソースコードをcloneします。なお、ソースコードはLocal pathに書かれたディレクトリへダウンロードされるため、誤って削除しないようにします。
エラー無く正常に画面が切り替わった場合、cloneが完了しています。今後spoticordをアップデートする際は、この画面のFetch originから行います。

7. spoticordをセットアップする

GitHub Desktopの[Repository] -> [Open in Command Prompt] (またはPowerShell)をクリックすると、spoticordのソースコードが含まれたディレクトリでコマンドプロンプト (またはPowerShell) を開くことが出来ます。コマンドプロンプトを開いたら、以下のコマンドを実行します。

npm install

これにより、spoticordが利用するライブラリがダウンロードされます。
実行できない場合、コマンドプロンプトとGitHub Desktopを一度閉じ再度行ってください。

8. spoticordを起動する / 終了する

前述のセットアップから続けて (または今後同様の手順でコマンドプロンプトを開き) 、以下のコマンドを実行するとspoticordが起動します。

node app.js

終了する際は、一般的なコマンドラインアプリケーション同様に、このプロンプト上で [Ctrl] + [C] を入力すると終了します。

spoticordに貢献する

spoticordは無償で利用でき、さらにオープンソースソフトウェアとして提供されています。
今後も継続的にアップデートされるよう、利用者は以下のような方法で貢献できるでしょう。

  • バグ等を修正し、GitHub上でPull requestを送る
  • GitHub上でプロジェクトにStarを付ける

GitHubに登録している場合、プロジェクトにStarを付けることで開発者を応援することができます。

f:id:S64:20171211202959p:plain

クリックするだけなので、是非Starを付けて応援しましょう。

わからないことあったら聞いてください。

高校時代ハロワに行って、さんざんコケにされた話

マイナーな専門性

マイナーな専門性のみを高めるのは遅かれ早かれ死へ通ずる。
将来スケールしていった時、徐々に自身のリソースが不足し手が足りなくなるか、ある時不要になって手詰まりになると相場が決まっている。
重要なのは関わるタスクを極限までアウトソースできるか、極端な話自身の専門性がいかに陳腐かである。

新たな領域に誰も参入しない理由のひとつに、アウトソースできる人間の有無、属人性の排除可否 からの持続可能性の低さが影響している場合がある。
小難しく言葉をこねたが、要はマイナーな知見があったところで必要とされない、と言えば容易に想像できるはずだ。

雇用が変わる 人材派遣とアウトソーシング ─ 外部人材の戦略的マネジメント The Upheaval of Employment

雇用が変わる 人材派遣とアウトソーシング ─ 外部人材の戦略的マネジメント The Upheaval of Employment

残る生存戦略があるとすれば、これを「自身にしかできないこと」まで昇華させられるか。値付け競争が無くなり、リソースを渇望する人間が居る限りは自身の都合で待たせてもいい。

今の時代、何かの超人になったところで安泰ということはあり得ない。何かにとっての交換可能な価値であることが必要だ。

死んだスーパーマン (こわい話 ふしぎな話)

死んだスーパーマン (こわい話 ふしぎな話)


【廃止時期追記あり】Twitter User streams APIは今後廃止されます

追記 (2018-04-08 12:39):

User streams API の廃止時期を延期することが告知されました。延期後の具体的な日付は未だ発表されていないようです。
この記事はあくまで2次情報であり情報を錯綜させる可能性があるため、これ以上の追跡を控えます。

@TwitterDev の情報などを参考にしてください。


追記 (2017-12-20 10:17):


追記 (2017-06-26 20:58):

2ヶ月前の記事が急に流れ出しましたが、特別変化はありません。公式からのアナウンスを注視してください。

また当初タイトルが Twitter User streams APIは今後数ヶ月以内に廃止されます となっておりましたが、ご指摘頂いたとおり "今後数ヶ月以内" は下書き時点でのミスリードでした。正しくは 新API公開後半年 (数ヶ月) となります。タイトルをTwitter User streams APIは今後廃止されますに改めさせて頂きました。


よく見るとミスってた。正しくコピペすると User streams will eventually be replaced by the Account Activity API. です。


ヒューマンエラーを防ぐ知恵 ミスはなくなるか (朝日文庫)

ヒューマンエラーを防ぐ知恵 ミスはなくなるか (朝日文庫)


明確な時期は出てないものの、User streams API(+ Site streams API) をdeprecateするとアナウンスされました。
deprecateと言っても、その代わりにAccount Activity APIが登場します。重要な通知関連は変わらずリアルタイムで配信されるAPIがあるってことみたい。

Account Activity API (beta) のドキュメントを読んでみると、

The Account Activity API will eventually replace the User streams and Site streams APIs. We plan to provide at least a six month migration window after the Account Activity API graduates from beta. We’ll announce the deprecation date then and encourage you to start using the Account Activity API beta in the meantime.

とあります。こっちの新APIがbeta卒業後 最低6ヶ月の移行期間を用意するってことなので、最悪たとえば明日新APIがproductionに上がった場合は 6ヶ月でUserstreamsが廃止されると取ってもいいかも。
そんなわけはないので、半年以上は使えると思ってよさそう。


Site streamsはもう新規アプリとかで使えてないので割愛。
User streamsが (リアルタイムで) 流してくれていることをおさらいすると、

  • TLのツイート
    • 投稿 / 削除 / 位置情報削除
    • 検閲を受けている場合の国コード
  • APIのrate limit通知
  • 自分のプロフィール更新
  • リプライ
  • RT
    • された / 解除された
  • ダイレクトメッセージ
  • ブロック / ブロック解除
  • ふぁぼ
    • followingが何かふぁぼった / 解除した
    • 自分のツイートがふぁぼられた / 解除された
  • フォロー
    • フォローされた / 解除された
    • followingが誰かフォローした / 解除した
  • リスト
    • 作成 / 削除 / 更新
    • 追加された / 削除された
    • followingが誰か追加した / 削除した
    • 購読された / 解除された
    • followingが何か購読した / 解除した
  • 引用された

あたり。アプリによって全てが配信されるわけではないみたいだけど、ドキュメント上はこれらがある。


新しいAccount Activity APIはWeb Hooksを利用した通知の仕組み。ストリームを繋ぎっぱなしにせず、イベントがある度に都度投げてくれるイメージ。
バッテリー節約になって良さそう。ただ外向きにHTTPを開けておく必要があるので、今後の非公式クライアントは必ずバックエンドのサーバが提供されることになりそう。開発者はサーバ維持が必要になる。

これに関してはsuruyatuでも悩みのタネみたい

Webhooksを受け取ってアプリへPushするサーバ自体はすごく大変ということではないものの、多くのユーザを抱えているアプリにとってはしっかり捌くためにそれなりのコストが発生しそう。けっこう打撃がでかい。


まだAccount Activity APIはBetaなので、これからどんどんUser streamsの提供する内容へ近付いていくと思ってます。
現状で配信がスタートしてるのはdirect_message_events、つまりDM関係のイベントのみ。
おそらくこれは先日新しいDMのAPIが出たのに合わせてということなのだと思うし、多分今後RTや"いいね"の通知も取れるようになるんじゃないかな。

ただし、TLのリアルタイム通知に関してはどうなんだろう?と個人的に疑問。

User streamsは非公式クライアントユーザが ツイートや通知のリアルタイム配信のために使っている、という側面がイメージしやすいのだけど、それ以前にTwitter APIにはけっこう厳しいRate Limitがあるので、ヘビーユーザが規制を受けずに利用するためには必須だったということ。

そういったユーザのTLはめちゃくちゃ早いので、Webhookで送るリクエストの数もバカにならない。HTTPコネクションの確立って意外とコストが高いので、TLがリアルタイムで流れるようなAPIもう出ないんじゃないかな。
出たとしても、だいぶ漏れが多くなりそう。

メッセージングプラットフォームとしてならAPI公開してもいいけど、TLまでAPI経由で読まれちゃうとTwitter, Inc.側からも広告が配信できる余地なくなっちゃうし。非公式クライアント使ってるヘビーユーザが一切収益化できない構造は辞めたいだろうし...



まとめると

  • User streamsが廃止されて、通知まわりが新しくなるよ
  • 開発者はそれなりに大変なので、小さい非公式クライアントは維持が難しいかも
  • TLのリアルタイム配信はどうなるかまだわからないけど、収益化考えると無くなってもおかしくないよね...

あたりまえポエム 君の前で息を止めると呼吸ができなくなってしまうよ

あたりまえポエム 君の前で息を止めると呼吸ができなくなってしまうよ