スマホを落とさない技術

ズボンの左か右ポケットに入れる

後ろのポケットや、ジャケットには入れない。何らかの拍子に飛び出して落ちることがある。

カバンに入れない

財布を取り出そうとしたタイミングで落ちたりするので、カバンには入れない
対策としてカバンの横にスマホ専用ポーチをつけておくと良い

スマホを持たない

スマホを持たなければ、落ちない

はてなブックマークのホッテントリがほぼ機能していない件について

アフィリエイトサイトの食い物に

結構昔はお世話になってたんですが、最近ではSEOの食い物にされているなぁという感想しか出てこない。特に、アフィリエイトサイトなどで、何らかの方法ではてなブックマークを大量につけているメディアが目立つようになってきた。アフィリエイトでもとりわけ還元率が高いクレジットカードなどのブログ記事がよく流れてくる。

Yahooのトップページがホッテントリ入り

ある日、Yahooのトップページがホッテントリ入りした。原因はスパムアカウントと思われるアカウントが大量にハテブをしたことが原因。おそらく何らかのハテブを自動的につけてホッテントリ入りさせてくれる情報商材系ツールが、お試しで使われているように見える。

これからも増え続けてきそう

もし、このはてぶ自動増殖ツールXがこれからも使われ続けて、はてなが対策しなかったらホッテントリは意味をなさなくなってきそう・・。

もしもレコメンド型ニュース系アプリがAIスピーカーに参入したら

AIスピーカーについて

日本でもGoogle Homeを初め、AIスピーカーが普及し始めてきました。音声認識や音声合成の技術は、各社が開発しやすいように用意されているようです。
まだ、日本で登場して間もないですが、いち早く食べログによる近くのおすすめのお店を教えてくれる機能や、ピカチュウと話しかけるとピカチュウと会話できる機能(Google Home)おもしろい機能も増えてきました。その際、AIの声も変わるのでAIが交代して話しているように聞こえるので面白いです。

ラジオDJ AI

さて、こうしたAIスピーカーですが、最新のニュースや話題を音声でお届けするニュースAIももちろんありますが、それは予め用意された原稿をAIが読み上げているにすぎない状態です。こうしたAIによるニュース配信が、もし個人に特化したニュースや話題の提供に進化したとしたらどうでしょう。すでにアプリ市場では、スマートニュースやグノシーなどが個人の趣味嗜好に特化したニュースや話題の配信を行っています。そのように、ニュースや話題の配信を個人にレコメンドして配信できたら朝の時間を有意義に過ごせるように思うのです。

スレッドに名前をつける

スレッドがコケたときに、スレッドの名前が表示される。エラー時の原因特定に便利。

use std::thread;
thread::Builder::new() .name("thread name".to_string()) .spawn(move || { println!("Hello, world!"); });
カテゴリー: Rust

flat_map で Vec<String> を得る

flat_map だと、 cloned() しないと、 Option<&String> になってエラーになる。
Vec<String> として取り出したい場合は、 cloned() をつける。

let result: Vec<String> = vec![Some("hoge".to_owned()), None] .iter() .flat_map( |f| f ) .cloned() .collect();
println!("{:?}", result);
カテゴリー: Rust

Rust Option入門者向けの補足追記

Option

https://doc.rust-lang.org/std/option/enum.Option.html の補足追記です。

この記事は MIT ライセンスです。

is_some

Someならtrue

let x: Option<u32> = Some(2);
assert_eq!(x.is_some(), true);
let x: Option<u32> = None;
assert_eq!(x.is_some(), false);

is_none

Noneならtrue

let x: Option<u32> = Some(2);
assert_eq!(x.is_none(), false);
let x: Option<u32> = None;
assert_eq!(x.is_none(), true);

as_ref

Option を Option<&T> に変換する。この手法によって、元の値には触れず、参照のみを受け取ります。
borrow は発生しません。

let num_as_str: Option<String> = Some("10".to_string());
// First, cast `Option<String>` to `Option<&String>` with `as_ref`,
// then consume *that* with `map`, leaving `num_as_str` on the stack.
let num_as_int: Option<usize> = num_as_str.as_ref().map(|n| n.len());
println!("still can print num_as_str: {:?}", num_as_str);

as_mut

Option を Option<&mut T> に変換

let mut x = Some(2);
match x.as_mut() { Some(v) => *v = 42, None => {},
}
assert_eq!(x, Some(42));

expect

オプションをアンラップし、Someの中身を返す。
unwrapと異なる点は、panicが発生した場合に、msgが流れる

let x = Some("value");
assert_eq!(x.expect("the world is ending"), "value");

unwrap

Some(v) から vを取り出す。
もとの変数からは移動されてしまうので注意。
Noneだった場合はpanicが発生する

let x: Option<&str> = None;
x.expect("the world is ending"); // panics with `the world is ending`

unwrap_or

アンラップ時に、Noneだった場合は、orで指定したものを返す。制約として同じ型のものでなければいけない。

assert_eq!(Some("car").unwrap_or("bike"), "car");
assert_eq!(None.unwrap_or("bike"), "bike");

unwrap_or_else

アンラップ時にNoneだった場合は、or_elseで指定したクロージャの結果を返す。

let k = 10;
assert_eq!(Some(4).unwrap_or_else(|| 2 * k), 4);
assert_eq!(None.unwrap_or_else(|| 2 * k), 20);

map

アンラップ時にSomeだった場合は、Some(v)のvをクロージャに渡し、結果をSome(s)として受け取る。Noneだった場合はそのままNoneになる。

map_or

アンラップ時にSomeだった場合は、Some(v)のvをクロージャに渡し、結果をsとして受け取る。Noneだった場合はデフォルト値が渡される。結果sとデフォルト値は同じ型。

let x = Some("foo");
assert_eq!(x.map_or(42, |v| v.len()), 3);
let x: Option<&str> = None;
assert_eq!(x.map_or(42, |v| v.len()), 42);

map_or_else

Someだった場合もNoneだった場合もクロージャに渡す。結果の型はそれぞれのクロージャで同じでなければいけない。

let k = 21;
let x = Some("foo");
assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 3);
let x: Option<&str> = None;
assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 42);

ok_or

Option型をResult型に変換する。失敗だった場合の処理は新たに追加する。

let x = Some("foo");
assert_eq!(x.ok_or(0), Ok("foo"));
let x: Option<&str> = None;
assert_eq!(x.ok_or(0), Err(0));

or_or_else

Option型をResult型に変換する。失敗だった場合の処理は、クロージャで計算する。

let x = Some("foo");
assert_eq!(x.ok_or_else(|| 0), Ok("foo"));
let x: Option<&str> = None;
assert_eq!(x.ok_or_else(|| 0), Err(0));

iter

イテレータに変換する。next()すると結果が変える。
二回next()するとNoneになる。

let x = Some(4);
assert_eq!(x.iter().next(), Some(&4));
let x: Option<u32> = None;
assert_eq!(x.iter().next(), None);

iter_mut

iterと一緒だが、ミュータブル

let mut x = Some(4);
match x.iter_mut().next() { Some(v) => *v = 42, None => {},
}
assert_eq!(x, Some(42));
let mut x: Option<u32> = None;
assert_eq!(x.iter_mut().next(), None);

and

引数の条件もSomeでなければ、全体的にNoneになる。

let x = Some(2);
let y: Option<&str> = None;
assert_eq!(x.and(y), None);
let x: Option<u32> = None;
let y = Some("foo");
assert_eq!(x.and(y), None);
let x = Some(2);
let y = Some("foo");
assert_eq!(x.and(y), Some("foo"));
let x: Option<u32> = None;
let y: Option<&str> = None;
assert_eq!(x.and(y), None);

and_then

NoneのときはNoneを返すが、Someだった場合は、クロージャの計算結果を Some<U> として返す。

fn sq(x: u32) -> Option<u32> { Some(x * x) }
fn nope(_: u32) -> Option<u32> { None }
assert_eq!(Some(2).and_then(sq).and_then(sq), Some(16));
assert_eq!(Some(2).and_then(sq).and_then(nope), None);
assert_eq!(Some(2).and_then(nope).and_then(sq), None);
assert_eq!(None.and_then(sq).and_then(sq), None);

or

どちらかに値が入っていれば、最初にHITした値が帰る

let x = Some(2);
let y = None;
assert_eq!(x.or(y), Some(2));
let x = None;
let y = Some(100);
assert_eq!(x.or(y), Some(100));
let x = Some(2);
let y = Some(100);
assert_eq!(x.or(y), Some(2));
let x: Option<u32> = None;
let y = None;
assert_eq!(x.or(y), None);

or_else

値が含まれていればSomeを返すが、含まれていない場合は、クロージャが呼ばれその結果を返す。クロージャの結果はSomeかNoneである。

fn nobody() -> Option<&'static str> { None }
fn vikings() -> Option<&'static str> { Some("vikings") }
assert_eq!(Some("barbarians").or_else(vikings), Some("barbarians"));
assert_eq!(None.or_else(vikings), Some("vikings"));
assert_eq!(None.or_else(nobody), None);

get_or_insert

Nonen場合は、vをオプションに挿入し、含まれている値への変更可能な参照を返す。

let mut x = None;
{ let y: &mut u32 = x.get_or_insert(5); assert_eq!(y, &5); *y = 7;
}
assert_eq!(x, Some(7));

get_or_insert_with

Noneの場合、クロージャによって計算された値をオプションに挿入し、含まれている値への変更可能な参照を返す。

let mut x = None;
{ let y: &mut u32 = x.get_or_insert_with(|| 5); assert_eq!(y, &5); *y = 7;
}
assert_eq!(x, Some(7));

take

オプションから値を取り除き、Noneをその場所に残す。

let mut x = Some(2);
x.take();
assert_eq!(x, None);
let mut x: Option<u32> = None;
x.take();
assert_eq!(x, None);
カテゴリー: Rust

Goolgleの3D素材(作品)のプラットフォーム Poly

Poly

Polyは CC-BYという緩いライセンスで3D素材(作品)を公開できる3Dプラットフォーム。自身の作品もアップロードすることができて、他人の作品にいいねもできる。
3D素材(作品)は、著作権表示をすれば自由に利用することができる。ARやVRが加速してきているのでこういった素材サイトで、ぐっと開発の敷居が下がるような気がしている。

iPhone X Plusが来年もし出たら・・・

予め調べてなかったのが悪いんだけど普段Plus使いなので、この情報はキツイ。
それまでに、iPhoneX Plusと iPhone X 分稼がなくてはいけない。。

あ、そうか。稼げばいいのだ。
iPhone X Plusを1年待つなんて無理だし、何よりVRと相性がいい有機ELを無視できない。

有機ELはVRと相性がいい

有機ELは、応答速度が速いのでVR酔いが起きにくく、様々なHMDで使われている。
すでにARKitを使ったVRゲームも出ているので、すぐにでも開発したい!

今は、 poly という3D素材のプラットフォームがあるので、これを参考にして何か作ってみようと思っている。

Apacheで同じURLでもwebsocketとhttpを両方見れるようにする

半年ほど悩んでいたのですがやっと解決できたのでまとめます。
WebsocketではHTTPをUpgradeしたプロトコルとして扱われ、COMETとは違いajaxやiframeなどによるコネクションをポーリングする技術とは異なる双方向通信を実現するプロトコルです。
なのでWebsocket自体に予約されたポートは無く、クライアントからは80や443で通信することも可能です。といっても、サーバー側がWebsocketに対応している必要があります。

前提条件

同じURIだけど、websocketとhttp両方見れるようにしたい

例えばストリーミングを行うAPIがあったとします。

/api/v1/streaming

このAPIのリクエスト時に、 http://(https://)であれば、 COMET等の技術によりコネクションがポーリングされストリーミングで受信処理が行われる用にしたいが、
ws://(wss://) の場合は、websocketでストリーミングで受信処理を行わるようにしたい場合、Apacheでは下記のようにすると問題が出ます。

ProxyPass /api/v1/streaming/ ws://localhost:4000/
ProxyPassReverse /api/v1/streaming/ ws://localhost:4000/
ProxyPass /api/v1/streaming/ http://localhost:4000/
ProxyPassReverse /api/v1/streaming/ http://localhost:4000/

これだと、最初のProxyPassで潰されてしまい、httpの通信に失敗してしまいます。
この場合、wsの場合はmod_rewriteを使うことで解決できます。
websocketは、ConnectionがUpgradeになるので、それをrewriteの条件に指定することでwebsocketの場合のみwsに接続するように変更する事ができます。

 RewriteEngine On RewriteCond %{HTTP:Connection} Upgrade [NC] RewriteCond %{HTTP:Upgrade} websocket [NC] RewriteRule /api/v1/streaming/(.*) ws://localhost:4000/api/v1/streaming/$1 [P,L] ProxyPreserveHost On ProxyPass /api/v1/streaming/ http://localhost:4000/api/v1/streaming/ ProxyPassReverse /api/v1/streaming/ http://localhost:4000/api/v1/streaming/ ProxyPass / http://localhost:3000/ ProxyPassReverse / http://localhost:3000/

参考URL