システムコールの定義
を読んでgrepしたり、http://lxr.free-electrons.com/ident?i= で検索してもなかなかシステムコールを定義してる箇所が見つからないなーと思ってたら、
SYSCALL_DEFINEx っていうマクロを使うようになってたのね。
SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count) { struct fd f = fdget_pos(fd); ssize_t ret = -EBADF; if (f.file) { loff_t pos = file_pos_read(f.file); ret = vfs_read(f.file, buf, count, &pos); if (ret >= 0) file_pos_write(f.file, pos); fdput_pos(f); } return ret; }
とか。
SYSCALL_DEFINEx 自体は include/linux/syscalls.h で
#define SYSCALL_DEFINE0(sname) \ SYSCALL_METADATA(_##sname, 0); \ asmlinkage long sys_##sname(void) ..(略).. #define SYSCALL_DEFINEx(x, sname, ...) \ SYSCALL_METADATA(sname, x, __VA_ARGS__) \ __SYSCALL_DEFINEx(x, sname, __VA_ARGS__) #define __PROTECT(...) asmlinkage_protect(__VA_ARGS__) #define __SYSCALL_DEFINEx(x, name, ...) \ asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \ __attribute__((alias(__stringify(SyS##name)))); \ static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ { \ long ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__)); \ __MAP(x,__SC_TEST,__VA_ARGS__); \ __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \ return ret; \ } \ static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))
とかで定義されてる。
rust で数値からenumに変換する
rustのenumを定数を列挙するためだけに使いたいということもありますね?(ないですか?)
そういう時、数値からenumに変換したいということがありますね?(ないですか?)
rustのenumはこんなふうに定義します。 rustのenumはだいぶ高機能なのでいろんなことができますが、今回は定数の列挙に使いたいという想定ですね。
enum TrafficLight{ Blue, Yellow, Red, }
このように定義するとデフォルトで0から数値がふられるので enum から数値に 変換することはできます。
fn main() { println!("{:?} = {}", TrafficLight::Blue, TrafficLight::Blue as i32); println!("{:?} = {}", TrafficLight::Yellow, TrafficLight::Yellow as i32); println!("{:?} = {}", TrafficLight::Red, TrafficLight::Red as i32); }
結果
$ cargo run Blue = 0 Yellow = 1 Red = 2
こうなります。
逆はできません。
$ cargo build src/main.rs:12:32: 12:49 error: non-scalar cast: `i32` as `TrafficLight` src/main.rs:12 let light : TrafficLight = 0 as TrafficLight; ^~~~~~~~~~~~~~~~~ error: aborting due to previous error Could not compile `light`. To learn more, run the command again with --verbose.
こうなります。
調べてみると以下がでてきますね。
書いてある通りに std::num::FromPrimitive
は削除されてしまいましたが、今は http://doc.rust-lang.org/num/num/index.html に同様な機能を持つものが入っています。
crateに頼ることになるのは遺憾ですが公式が提供してる(?)ものなのでまぁいいとしましょう。
これを使って FromPrimitive
という trait を実装すると
from_i64(n: i64) from_u64(n: u64) from_isize(n: isize) from_i8(n: i8) from_i16(n: i16) from_i32(n: i32) from_usize(n: usize) from_u8(n: u8) from_u16(n: u16) from_u32(n: u32) from_f32(n: f32) from_f64(n: f64)
これらが使えるようになるので、基本の数値型ならどれからでも変換できるようになります。
実装する必要があるのは、 from_i64
と from_u64
の2つです。
以下使い方
Cargo.toml に依存を追加しましょう
[dependencies] num = "*"
で実装してきます
extern crate num; use num::traits::FromPrimitive; impl FromPrimitive for TrafficLight { fn from_i64(n: i64) -> Option<TrafficLight> { match n { 0 => Some(TrafficLight::Blue), 1 => Some(TrafficLight::Yellow), 2 => Some(TrafficLight::Red), _ => None, } } fn from_u64(n: u64) -> Option<TrafficLight> { match n { 0 => Some(TrafficLight::Blue), 1 => Some(TrafficLight::Yellow), 2 => Some(TrafficLight::Red), _ => None, } } }
こうです。
このmatchあたりがめんどくさいのでなんとかしたいですね。いい方法があるといいんですが。
ここに数値を書かないといけないとなると網羅してるかもよくわからないし変更や追加に弱いしこれはなんとかしたいです。
(これのいい方法が知りたくてこんな記事をだらだら書いてると言っても過言ではありません。誰か教えてください。)
let blue = TrafficLight::from_i64(0 as i64).unwrap(); let yellow = TrafficLight::from_u8(1 as u8).unwrap(); let red = TrafficLight::from_usize(2 as usize).unwrap(); println!("{:?}", blue); println!("{:?}", yellow); println!("{:?}", red);
結果
$ cargo run Blue Yellow Red
できましたね
mixlib-cliのオプションで複数の値を渡す
mixlib-cli、便利ですよね。
この option
で同じオプションで複数の値を渡したい時はどうすればいいか
例えば --hosts
で複数のホストの情報を渡したいとか。
ぱっと調べた感じ&動作を見た感じでは、 cmd --hosts host1 --hosts host2
とかいう渡し方でうまく処理してくれるということはなさそう
:proc
オプションを使うとそれっぽくできる
:proc
オプションは、 Proc
を渡しておくと渡された値をその関数で前処理しておいてくれる。
options :hosts, :long => "--hosts", :proc => Proc.new { |a| a.split(",") }
↑のようにしておくと cmd --hosts host1,host2
で複数の値をカンマ区切りで渡せば、プログラム内で config[:hosts] = ["host1", "host2"]
として使える。
テーブルのカラムにないデータをEloquentのレスポンスに入れる
なんて言ったらいいかよくわからないけどタイトルみたいなことがしたいときどうするか
テーブルのデータそのものじゃなくてテーブルのデータから計算できるデータがあったとして、それをクライアントに計算させるんじゃなくてレスポンスに入れて返したいとかそんな時
普通にドキュメントに書いてあるけど、そういう時は Accessors と $appends
ってのを使うとできる
Accessors は↓これ。で、 appends については同じページの一番下に書いてある
Eloquent ORM - Laravel - The PHP Framework For Web Artisans
$appends
は Eloquent
を継承してるクラスのメンバ変数として定義しておく
class SomeModel extends Eloquent { protected $table = 'some_table'; protected $appends = array('some_append_data'); // ←これ // Accessors public getSomeAppendDataAttribute() { return "something"; } }
こうすると、 SomeModel::find($id)
とかで返ってくるデータに
"some_append_data" => "something"
も一緒に入ってくる。
Laravel4 で rename column しようとするとエラー
php artisan migrate PHP Fatal error: Class 'Doctrine\DBAL\Driver\PDOMySql\Driver' not found in .../vendor/laravel/framework/src/Illuminate/Database/MySqlConnection.php on line 59
みたいなエラーが出てなんぞ、と思っていたところ
Schema Builder - Laravel - The PHP Framework For Web Artisans
Before dropping a column, be sure to add the doctrine/dbal dependency to your composer.json file.
普通にドキュメントに書いてあった。
composer.json の "require"
に "doctorine/dbal" : "2.5.*"
を足して composer install
して解決
tmux で Not privileged to set domain environment
いつからかtmuxを起動すると
Not privileged to set domain environment. Not privileged to set domain environment.
とエラーが出るようになった。
なんだこれは。
調べるとどうも .zshrc で launchctl setenv
とかいじってるのが問題らしい。
何してたかというと、
launchctl setenv GOROOT=$GOROOT launchctl setenv GOPATH=$GOPATH
とかしていた。
IDEA とかに渡すには setenv
で GOPATH
とか設定しておかないといけないもんで、.zshrc に書きゃいいかとか安直に考えたわけだね、昔の俺。
違う違う。 launchctl
なんだから launchd
を使おう。
/etc/launchd.conf
に
setenv GOROOT=$GOROOT setenv GOPATH=$GOPATH
と書くようにすることで解決。
ちなみに $HOME/.launchd.conf
はダメ。