Ruby 初めのいーっぽ 【速習編】
Ruby 初めのいっーぽ
MENTAのメンティさん向けの速習メモ
全てがオブジェクト
Ruby はオブジェクト指向言語のため、全てがオブジェクト
- 文字列、配列、数値やnil、trueとかも含めてぜーんぶオブジェクト
オブジェクト.メソッド 引数
みたいな感じでメソッドを呼び出すことができる
例: 文字列 1.to_s
, nil nil.to_s
などなど
変数名は小文字のスネークケースで
例: special_price = 200
のような感じで _ で小文字を区切る
- 変数名には、小文字アルファベットと数字、アンダースコアなどが使える
- 数字から始まる変数名は使えない
- 漢字とかひらがなも使えるが一般的ではない
文字列はシングル or ダブルクオーテーションで囲む
- ダブルクオーテーションで囲むと式展開できるようになる
puts "hello #{name}"
のようにname
の内容を展開できる
数値
- アンダースコアを含めることができて無視されるので桁区切りに便利
1_000
は1000
と認識される
- 他の言語でいう、インクリメントなどの
++
,--
はない+=
,-=
はあるので使える- 例:
n += 1
など
- 丸め誤差に注意
0.1 * 0.3 == 0.3
は falseになる- rational クラスを使うといい
- 例:
0.1r * 0.3r == 0.3
は true
真偽値
if文
elseif
はelsif
となるので注意- elsif や elseは省略可能
- 後置if が便利
- 例: 1日ならポイント五倍
point *= 5 if day == 1
てな感じ
- 例: 1日ならポイント五倍
メソッドの定義
- 戻り値
- return は使わない方が主流
- 最後に評価された式がメソッドの戻り値となる
- return はメソッドを途中で抜けたいときに使われることが多い
- 引数がない場合は メソッド名の後に
()
をつけない方が主流
文字列
- %記法を使うとシングル ダブルクオーテーションをエスケープしなくても使える
%q!
はシングル%Q!
はダブルクオーテーションで囲んだのと同じくなる!
以外でも?
とか^
とか任意の記号を区切り文字に使える- かっこを区切り文字に使った時は対応する閉じ括弧になる
- 例:
puts %q! He said, "Hello."!
=>He said, "Hello."
- 例:
puts %Q< #{name} said, "Hello.">
=>Taro said, "Hello."
unless文
- if文と反対の意味をもつ文
- ただし、elsifに対応する elsunless は存在しない
- 条件文が偽になった時だけ処理を実行する
例: これらは同じ意味
status = 'error' if status != 'ok' '異常' end
status = 'error' unless status == 'ok' '異常'
case文
- 複数条件を指定する時は、elsifをなんども書くよりもcase文で書いた方がシンプル
- when節に複数の値を指定できる
例:
name = '太郎' case name when '太郎', 'Taro' 'とっとこハム' when '次郎', 'Jiro' 'ラーメン' else '謎だ' end
三項演算子
式 ? 真だった時の処理 : 偽だった時の処理
と書ける- 例:
n >= 18 ? '成人やん' : '未成年やん'
requireとload
- ライブラリなどを読み込む時に requireを使う
require ライブラリ名
などと使う- 再度 requireを しても読み込み済みのためfalseが返る
load
を使うとそのファイルを呼ぶごとに毎回指定したファイルを読み込むload ファイル名.rb
などと使う- load は
.rb
を省略できない
requireに関連して
海外のエンジニアとの交流の仕方
経緯
先日もブログ記事にしたけれども、ここ一年くらいは英語を使ってエンジニアリングをする試みを続けていて、TwitterとかでHackerNewsとかをシェアしているユーザをテキトーにフォローして話したりしていた。
その中で、めっちゃいい方法がわかったのでメモ
メモ
Twitterとかで見つけたエンジニアにDM送って、俺、日本のエンジニアなんやけど、Skypeとかで話そうぜって言ったら結構乗り気な人が多い。
アニメとかについてめっちゃ聞かれるから答えると、いっしょに笑えるのと、インドとかアメリカとか、世界各地のエンジニアリングの状況を知れるのはすっごく面白い。
代わりに日本の状況を教えてあげることにしている。
最近は、僕の周りではVue.jsとか流行ってるよーって言ったら、知ってたけどあんま使ってないな〜🤔って感じだった模様。
あと なでしこ(言語) を教えてあげたら爆笑していた。笑
話題が課題
んで、だいたい話をしていると話題がなくなってくるのが課題だったんだけれども、ちょうど今日、ポッドキャストを流しながら語ればええなと気付いて、
SEDaily を流しながらトピックごとにどう思った〜? って話すと、話が弾んだり、あちらの現場知識を聞けて、めっちゃ参考になって超有益でした。オススメです!
英語力
基本的に 基礎的な英単語とよくある言い回しだけ分かれば会話ができると思います。
エンジニアリング関連の単語はだいたい共通で通じるし、目の前のGoogleで検索して話せば理解できるし問題ない感じ。
向こうも僕たち日本人エンジニアが何やってるのかすっごく気になるって言っていたので、どんどん外のエンジニアとオンラインで話してみるといいと思います。それできっと英語力も向上するし、hiring につながるかもだし、一石二鳥だね。
Pythonのデコレーターとは
経緯
プログラミングに関して教えていたところPythonのデコレーターってなんやねんって聞かれたのでメモ
デコレーターとは
ある関数があったらそれを修飾して使えるようにするって概念がデコレーターで、これを使うことで、既存の関数の処理の前後に自分の好きな処理を付け加えることができるのがメリットだと思う。
そうすると、どっかのライブラリが提供している関数を呼んだときに自動的に実行される処理を追加できるとか、そういう便利なことができる概念って感じ。
使い道
なので使い道として例をあげると、
ある適当な文字列から、記号をのぞいて、大文字の英字列が欲しいなぁって気分だとしよう。
( men:ta%:abc
から MENTAABC
を取得したいってこと)
んで、どっかのライブラリが文字列から記号を消して文字だけを返してくれる機能を提供しているとして、それを使うと
men:ta%:abc
から mentaabc
が取得できる。
それに、文字列を大文字に変換する関数デコレーターを作って
mentaabc
から MENTAABC
が手に入ってやったねって感じ。
こんな感じに、自分でライブラリを拡張するみたいな感覚で使ったりする
追記
開始時間と終了時間をログに出す処理のデコレータを作成して、対象の処理複数個にあてるてのも使いどころとしてあると、おしえてもらった。
めっちゃ便利や.
参考
一人アドベントカレンダーを走り抜けたぞ
結果はっぴょー
終えてみての感想
途中体調が悪くなったりとなかなかしんどいタイミングはあったが、とにかく書いて進めるだけだって思っていたら自然と走り抜けられましたぁ。ちょっと疲れましたぁ。
元はといえば、こんな思い立って1分で書いたようなブログ記事から始まったのでしたね。忘れていましたw
この記事にあるように、翻訳とかOSSに貢献もしちゃおう
ってのはできていないですけれども、OS自作入門を読んだことで低レイヤーに関しての技術や知識は間違いなくつきましたし、良い経験となりました。
途中から23時以降はブログを書く時間と決めて死守するようにしたところ、どうにかその日中に書き終えることができました。
本来なら、書く内容なども準備しながら進めなければいけないのでしょうけれども行き当たりばったりでどうにか駆け抜けられたので、来年はもっと準備をして虎視眈々とアドベントカレンダーを書いていこうかなと思います。
実は私は、去年初めてのアドベントカレンダーに参加をしたのですが、そのきっかけになった 株式会社Silbird の皆さんにもう一度こんな面白いカルチャーを教えてくれてありがとうございます! と言いたいですね。
今思い返すと、とってもいい思い出になってます。見返すと情熱的で、なんだか恥ずかしい文章ですね 笑
初心忘れるべからず、情熱的なエンジニアとして今後もがんばって行きますぞー!!
上の記事から抜粋
あなたが成功したいなら、プライドを飲み込み、外に出て行って、自分がバカに見えるのを恐れないようにしなければならない。有名な俳優、ミュージシャン、プロスポーツプレイヤー、講演者でも、かつてはうまくやれていなかったのだ。それでも、ベストを尽くし続けることで、とてもうまくできるようになった。結果はいずれやってくる。何かをずっとやり続けていれば、うまくならないではいられないものである。そうなるまで、長く生き残らなければならないだけのことだ。 そして生き残るための方法は、気にしないことである。バカのように見えることを恐れてはならない。
バカにされるのを恐れるな! - mozyのかきおき
この通りだと思いました。とにかくやり続けていればきっといつか日の目をみるのでしょう。きっとね。
ベストを尽くし続けることで、とてもうまくできるようになった。結果はいずれやってくる。何かをずっとやり続けていれば、うまくならないではいられないものである
最後に
最後に、このアドベントカレンダー企画を眺めたりコメントをくれたりした、現実世界の友人の皆さん、仕事で関わっている皆さん。WBEWの皆さん。見てくれた一人ひとりのあなた、本当にありがとうございました。
やはり皆さんの反応がないと書き続けるモチベーションは保てなかったでしょうし、とにかく皆さんが反応してくれたことによってぼくは25日間駆け抜けることができました。ありがとうございました。
世界にとってはちっぽけな25日の出来事かもしれないですが、ぼくにとっては大きな25日間でした。
それではみなさま良い年末を! また来年もお会いしましょう!
【最終日!】30日でできるOS自作入門【25日目】
概要
これはMozyの1人アドベントカレンダー 2018 の25日目の記事です。
書こうとした経緯は、こちら
今日の内容
- 文字列をかけるようにする
今日やったこと
- 文字列をかけるようにどんどん作り変えていく
void putfonts8_asc( char *vram, int xsize, int x, int y, char c, unsigned char *s) { extern char hanhaku[4096]; for (; *s != 0x00; s++){ putfont8( vram, xsize, x, y, c, hankaku + *s * 16); x += 8; } return; }
一文字は 16バイト。256 * 16 で 4096 となる。
こんな感じにして、どんどん修正していくと以下のようになる。
結果
ハマりポイント
特になかった。
知ったこと
こうやって便利なライブラリやツールを先人たちが作ってくれたから、簡単に実装できる今があるのだなと感じた。
まさに巨人の肩に乗る。だ。
完遂したぞ!
巷はクリスマス 🎄ですね。
書籍から何を得たかというよりは、
おわったーーー うおーーーーーーー 1日も落とさなかったぜ!! という気分です。
書籍は全然終わっていないが、とりあえず25日書き続けることができました。 笑
完遂できた喜びと学んだことに関しては別の記事で記載します。
一人アドベントカレンダーに取り組んでいたみなさま、お疲れ様でした!
みなさん良いお年を!!!!
来年またアドベントカレンダーの季節にお会いしましょう!
p.s
ここまで続いているのを辞めるのも、なんだかもったいないので自分の限界を知るためにも書籍が終わるまでぼちぼち継続して書くことにしてみます。😝
30日でできるOS自作入門【24日目】
概要
これはMozyの1人アドベントカレンダー 2018 の24日目の記事です。
書こうとした経緯は、こちら
今日の内容
- 矢印記法を使う
- 文字を出力できるようにする
今日やったこと
- 矢印記法を使って書き直す
bootpack.c
void HariMain(void) { struct BOOTINFO *binfo = (struct BOOTINFO *) 0x0ff0; init_palette(); init_screen(binfo->vram, binfo->scrnx, binfo->scrny); for (;;) { io_hlt(); } }
動作は変わらないが、コードはスッキリしたな。
文字を出力できるようにする
ただし、ドット絵的に文字をつくって出力することになる。
書籍によると、文字は 8 x 16 の長方形の画素の集まりでかけるとのことなので、そのようにしてドット絵的に文字を作っていく。
こんな感じ。
◽️◽️◽️◽️◽️◽️◽️◽️
◽️◽️◽️◾️◾️◽️◽️◽️
◽️◽️◽️◾️◾️◽️◽️◽️
◽️◽️◽️◾️◾️◽️◽️◽️
◽️◽️◽️◾️◾️◽️◽️◽️
◽️◽️◾️◽️◽️◾️◽️◽️
◽️◽️◾️◽️◽️◾️◽️◽️
◽️◽️◾️◽️◽️◾️◽️◽️
◽️◽️◾️◽️◽️◾️◽️◽️
◽️◾️◾️◾️◾️◾️◾️◽️
◽️◾️◽️◽️◽️◽️◾️◽️
◽️◾️◽️◽️◽️◽️◾️◽️
◽️◾️◽️◽️◽️◽️◾️◽️
◾️◾️◾️◽️◽️◾️◾️◾️
◽️◽️◽️◽️◽️◽️◽️◽️
◽️◽️◽️◽️◽️◽️◽️◽️
これをそれぞれの行で◽️: 0, ◾️: 1 として 0000000, ... のようにして16進数にすると以下のようになる。
static char font_A[16] = { 0x00, 0x18, 0x18, 0x18, 0x18, 0x24, 0x24, 0x24, 0x24, 0x7e, 0x42, 0x42, 0x42, 0xe7, 0x00, 0x00 };
そして、こうやって作ったデータを8画素書くプログラムを16回回せば1文字かけるのでこんな関数を作る。
bootpack.c
void putfont8(char *vram, int xsize, int x, int y, char c, char *font) { int i; char *p, d /* data */; for (i = 0; i < 16; i++) { p = vram + (y + i) * xsize + x; d = font[i]; if ((d & 0x80) != 0) { p[0] = c; } if ((d & 0x40) != 0) { p[1] = c; } if ((d & 0x20) != 0) { p[2] = c; } if ((d & 0x10) != 0) { p[3] = c; } if ((d & 0x08) != 0) { p[4] = c; } if ((d & 0x04) != 0) { p[5] = c; } if ((d & 0x02) != 0) { p[6] = c; } if ((d & 0x01) != 0) { p[7] = c; } } return; }
ハマりポイント
ドット絵の部分w 手間がかかったw
知ったこと
超久しぶりにドット絵書いた笑
原始的だけど 8 x 16 のドットで英字があらわせると思ったらなかなか面白いな。
30日でできるOS自作入門【23日目】
概要
これはMozyの1人アドベントカレンダー 2018 の23日目の記事です。
書こうとした経緯は、こちら
今日の内容
- bootpackをどんどん読みやすく書き直していく
今日やったこと
- 構造体を使ってかきなおす
bootpack.c
void io_hlt(void); void io_cli(void); void io_out8(int port, int data); int io_load_eflags(void); void io_store_eflags(int eflags); void init_palette(void); void set_palette(int start, int end, unsigned char *rgb); void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1); void init_screen(char *vram, int x, int y); #define COL8_000000 0 #define COL8_FF0000 1 #define COL8_00FF00 2 #define COL8_FFFF00 3 #define COL8_0000FF 4 #define COL8_FF00FF 5 #define COL8_00FFFF 6 #define COL8_FFFFFF 7 #define COL8_C6C6C6 8 #define COL8_840000 9 #define COL8_008400 10 #define COL8_848400 11 #define COL8_000084 12 #define COL8_840084 13 #define COL8_008484 14 #define COL8_848484 15 struct BOOTINFO { char cyls, leds, vmode, reserve; short scrnx, scrny; char *vram; }; void HariMain(void) { char *vram; int xsize, ysize; struct BOOTINFO *binfo; init_palette(); binfo = (struct BOOTINFO *) 0x0ff0; xsize = (*binfo).scrnx; ysize = (*binfo).scrny; vram = (*binfo).vram; init_screen(vram, xsize, ysize); for (;;) { io_hlt(); } } void init_palette(void) { static unsigned char table_rgb[16 * 3] = { 0x00, 0x00, 0x00, /* 0:黒 */ 0xff, 0x00, 0x00, /* 1:明るい赤 */ 0x00, 0xff, 0x00, /* 2:明るい緑 */ 0xff, 0xff, 0x00, /* 3:明るい黄色 */ 0x00, 0x00, 0xff, /* 4:明るい青 */ 0xff, 0x00, 0xff, /* 5:明るい紫 */ 0x00, 0xff, 0xff, /* 6:明るい水色 */ 0xff, 0xff, 0xff, /* 7:白 */ 0xc6, 0xc6, 0xc6, /* 8:明るい灰色 */ 0x84, 0x00, 0x00, /* 9:暗い赤 */ 0x00, 0x84, 0x00, /* 10:暗い緑 */ 0x84, 0x84, 0x00, /* 11:暗い黄色 */ 0x00, 0x00, 0x84, /* 12:暗い青 */ 0x84, 0x00, 0x84, /* 13:暗い紫 */ 0x00, 0x84, 0x84, /* 14:暗い水色 */ 0x84, 0x84, 0x84 /* 15:暗い灰色 */ }; set_palette(0, 15, table_rgb); return; /* static char 命令は、データにしか使えないけどDB命令相当 */ } void set_palette(int start, int end, unsigned char *rgb) { int i, eflags; eflags = io_load_eflags(); /* 割り込み許可フラグの値を記録する */ io_cli(); /* 許可フラグを0にして割り込み禁止にする */ io_out8(0x03c8, start); for (i = start; i <= end; i++) { io_out8(0x03c9, rgb[0] / 4); io_out8(0x03c9, rgb[1] / 4); io_out8(0x03c9, rgb[2] / 4); rgb += 3; } io_store_eflags(eflags); /* 割り込み許可フラグを元に戻す */ return; } void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1) { int x, y; for (y = y0; y <= y1; y++) { for (x = x0; x <= x1; x++) vram[y * xsize + x] = c; } return; } void init_screen(char *vram, int x, int y) { boxfill8(vram, x, COL8_008484, 0, 0, x - 1, y - 29); boxfill8(vram, x, COL8_C6C6C6, 0, y - 28, x - 1, y - 28); boxfill8(vram, x, COL8_FFFFFF, 0, y - 27, x - 1, y - 27); boxfill8(vram, x, COL8_C6C6C6, 0, y - 26, x - 1, y - 1); boxfill8(vram, x, COL8_FFFFFF, 3, y - 24, 59, y - 24); boxfill8(vram, x, COL8_FFFFFF, 2, y - 24, 2, y - 4); boxfill8(vram, x, COL8_848484, 3, y - 4, 59, y - 4); boxfill8(vram, x, COL8_848484, 59, y - 23, 59, y - 5); boxfill8(vram, x, COL8_000000, 2, y - 3, 59, y - 3); boxfill8(vram, x, COL8_000000, 60, y - 24, 60, y - 3); boxfill8(vram, x, COL8_848484, x - 47, y - 24, x - 4, y - 24); boxfill8(vram, x, COL8_848484, x - 47, y - 23, x - 47, y - 4); boxfill8(vram, x, COL8_FFFFFF, x - 47, y - 3, x - 4, y - 3); boxfill8(vram, x, COL8_FFFFFF, x - 3, y - 24, x - 3, y - 3); return; }
struct を使った部分が構造体を使って書き直した部分。
構造体の標準的な使い方とはちょっと違くて、普通だったら
void HariMain(void) { struct BOOTINFO abc; abc.scrnx = 320; abc.scrny = 200; abc.vram = 0xa0000; }
みたいにピリオドを使って書いて、func(abc)
としてひとかたまりで受け渡しができる。
構造体にしておかないと、func(scrnx, scrny, vram, ...);
てな感じにパラメータを全て書かなきゃ行けなくなったりする。
んで、今回は、これをポインタ化するのでstruct BOOTINFO *binfo;
という風に書いている。
これで番地を表す変数となったので、
セットするためには、binfo = (struct BOOTINFO * ) 0x0ff0;
こうして、
この中のscrnx
を表したい場合は、(*binfo).scrnx
とすれば良いわけです。簡単でしょ。
ハマりポイント
ポインタ化な構造体を直接書くことが久しぶりだったので、概念を追っていくのに時間がかかった。
知ったこと
なるほど。いわゆる矢印記法を使わずに同じような部分を作っているのかなと理解できた。
どんどん現実での知識に近づいてきたぞ。と感じる。(日本語が不自由w