ham-capのブログ

プログラミング学習の記録

【Ruby】ファイルの中身をぶっこ抜け!(Fileクラス・IOクラスを使ってファイルの中身を取得します)

もくじ

したいこと

任意のファイルから中身を取り出したい。※今回の記事ではファイルという言葉の中にディレクトリは含みません。

やり方

結論からいうと、

file = File.open("hoge")
content = file.read

これで変数contentの中にhogeというファイルの中身がそのまま文字列として格納されます。

以下で詳しく説明します。

Fileクラス

ファイルに対してなにかしたい場合はFileクラスを使えばおkです。とてもわかりやすい名称で僕のような初心者にも親切です。

Fileクラスに関してリファレンスマニュアルではこう説明されています。

ファイルアクセスのためのクラスです。 通常 Kernel.#open または File.open を使って生成します。 IO クラスがインクルードしている File::Constants は File クラスに関係する定数を格納したモジュールです。また File::Stat は stat 構造体( stat(2) 参照)を表すクラスです。

docs.ruby-lang.org

Rubyのコード内で何かを扱おうとするときは何かしらのオブジェクトにする必要があり、ファイルはFileクラスのオブジェクトとして扱うことになります。 そのオブジェクトはリファレンスマニュアルにあるように、File.openのようにopenメソッドを使用して生成するのが一般的なようです。

・・・。

なんか違和感あるなと思いませんか?

僕はリファレンスマニュアルのこの説明を読んで、実際にirbで試してみたりして動くことは確認したのですが、ややしばらくの間なんとなくこの使い方に違和感がありました。

で、あるとき思いました。

File.newじゃないんかい。」と。

そう。他のクラスのオブジェクトを生成する際は毎回newメソッドを使っています。 なのに今回はopenなんかい。

そう思って確認したら、なんのことはない、newメソッドもちゃんとありました。

なんならopenとまとめて記載されています。 要するに、まぁ似たような(同じ?)もんってことです。(厳密に言うと違うのかもしれませんが、僕レベルでは気にする必要がない程度なんじゃないかと思います。) 書き方もほぼ同じです。

new(path, mode = "r", perm = 0666) -> File
open(path, mode = "r", perm = 0666) -> File
open(path, mode = "r", perm = 0666) {|file| ... } -> object

path で指定されるファイルをオープンし、File オブジェクトを生成して返します。 path が整数の場合はファイルディスクリプタとして扱い、それに対応する File オブジェクトを生成して返します。IO.open と同じです。ブロックを指定して呼び出した場合は、File オブジェクトを引数としてブロックを実行します。ブロックの実行が終了すると、ファイルは自動的にクローズされます。ブロックの実行結果を返します。

docs.ruby-lang.org

じゃあなんでわざわざopenメソッドが定義されていて、それを使うのが一般的なんでしょう。

正直、ちゃんとした理由は知りません。

が、個人的にはそっちのほうが直感的にわかりやすいからっていうのが大きいんじゃないかと思ってます。

頭の中で日本語で考えるときも 「ファイルオブジェクトを新しく生成する(File.new)」よりも「ファイルを開く(File.open)」の方がファイルをいじくってる感が出てませんか?(個人の感想です)

というかnewってそもそも動詞として訳しにくい。

まぁとにかく、あとはopenの引数に自分が開きたいファイルの名前を渡してあげればおkです。

IOクラス

話が脇道にそれてしまった気もしますが、たぶん大丈夫です。

リファレンスマニュアルにおけるnewopenの説明の中にこんな記載がありました。

IO.open と同じです。

IOってなんじゃい。

この感じだとクラスですね。

リファレンスマニュアル召喚。

基本的な入出力機能のためのクラスです。

以上。ほーん。 InputOutputでIOね。

Fileクラスの話をしていたはずなのに、なんでIOクラスの話になるかと言うと、IOクラスがFileクラスのスーパークラスだからです。言い換えると、FileクラスはIOクラスを継承しているクラスになります。

IOクラスのInputとOutputというのは主語が 「Rubyで書かれたプログラムの」になるわけで、あるプログラムに対するあらゆるInとOutを司るクラスということだと思います。

なので、その「あらゆるInとOut」の中にはプログラムの外部にあるファイルの情報をとってきたり、なんらかの結果を外部ファイルとして出力したりということも当然含まれるため、こういう継承関係になっているのだと思います。

ここでもう一度、この記事の冒頭で書いたコードを見てみます。

file = File.open("hoge")
content = file.read

一行目はFileクラスの説明で書いたように、openメソッドを使ってFileオブジェクトを生成しています。

そして二行目でやることはreadというメソッドを使ってFileオブジェクトから中身を取得することなのですが、実はこのreadメソッドはFileクラスのメソッドではなくIOクラスのメソッドです。

readメソッド

readメソッドの説明も見てみます。

read(length = nil, outbuf = "") -> String | nil

length バイト読み込んで、その文字列を返します。 引数 length が指定された場合はバイナリ読み込みメソッド、そうでない場合はテキスト読み込みメソッドとして動作します。既に EOF に達していれば nil を返します。ただし、length に nil か 0 が指定されている場合は、空文字列 "" を返します。例えば、open(空ファイル) {|f| f.read } は "" となります。

このメソッドを使って取得したファイルの中身というのは改行文字等も含めてまるごと一行の文字列になります。 そのため、そこから更に何らかの情報を得たい場合は、行数を調べるために改行文字を数える、単語数を調べるために区切り文字を指定して切り分ける、といったようにひと手間加える必要があります。

IOクラスにはこの他にもファイルの中身をぶっこ抜いてくる系のメソッドがいくつもあって、例えばreadlinesというメソッドはreadと同じくファイルの中身を全て読み込んで返してくれますが、readが全てまるっと何の下ごしらえもしていない一行の文字列として返してくれるのに対し、readlines各行を要素として持つ配列を返してくれます。つまり、こちらが改行文字を数えたりしなくても、ちゃんと行を認識して切り分けてお皿に盛ってくれるわけです。(優しい)

この辺に関しては優劣ではなく仕様なので、自分が書きたい処理に適したメソッドを使えば幸せになれると思います。

まとめ

こんな短いコードのために長々と書いてしまいましたが、何はともあれこれで無事にファイルの中身をぶっこ抜いてくることができました。

あとは煮るなり焼くなりお好きにどうぞ。

記載内容に間違い等があった場合にはこっそり教えていただければ幸いです。 最後までお読みいただきありがとうございました。

【Ruby】ファイルの詳細な情報をまとめてゲットするゾ

したいこと

特定のファイルの詳細な情報(ファイルのサイズ・タイプ・オーナーのユーザID等)を取得したい。 ※以下、この記事内でファイルという言葉を使う場合は基本的にディレクトリも含んでいます。

File::Statクラス

あるファイルの詳細情報を取得したいときにはFile::statクラスを使うと便利です。以下、リファレンスマニュアルによる説明です。

ファイルの情報を格納したオブジェクトのクラス。 FileTest に同名のモジュール関数がある場合はそれと同じ働きをします。ただ、ファイル名を引数に取るかわりに Stat 自身について判定する点が違います。

docs.ruby-lang.org

はい。後半のモジュール関数がどうのこうのというのは正直僕もよくわかっていませんが、今回はそこはそんなに重要じゃない(と思う)ので深くつっこみません。

重要なのはFile::Statクラスのオブジェクトはファイルの情報を格納できるということです。(そのまんま)

このクラスのインスタンスメソッドの多くはそのオブジェクトの特定の情報を返してくれるものなので、それらのメソッドを使用して自分の欲しい情報を取得するという使い方になります。

例えば、あるファイルのサイズを知りたい場合はsizeメソッドを用いて以下のような書き方ができます。

file = File.stat("hoge")
file.size

statメソッドの引数には情報を取得する対象となるファイルのファイル名を渡します。 この場合、変数fileにはhogeというファイルの各種情報がまとめて格納されていて、その中からファイルサイズの情報をsizeメソッドを使用して取り出しているということになります。

初めてこのクラスを使ったときに個人的にちょっと面白かったのは、File::Statクラスのオブジェクトを作成する際にはFileクラスのstatメソッドを使用するということ。なるほど。クラス名が::でつながっている理由が何となくわかった気がします。 実際にはFile::Stat.newでも作成できますが、そこはかとなくもっちゃりしてませんか?(個人の感想です)

Dir.globと組み合わせる

さて、File::Statクラスを使ってファイルの詳細情報をゲットする方法は以上なのですが、それだけだと面白くないので僕が実際にやった具体的な使い方を紹介します。

僕がこのFile::Statを使う必要があったのは、カレントディレクトリにある全ファイルの情報を取得したかったからです。 そこで使用したのが、このブログの前々回の記事でご紹介したDir.globとの組み合わせです。 File.statを使用する際の引数は対象となるファイルのファイル名です。そしてDir.globはファイル名を取得するためのメソッドです。

もう大体わかると思いますが、要はDir.globでファイル名を取得して、それをそのままFile.statの引数として渡してしまえば、それらのファイル全ての詳細情報を取得できるということです。

というわけで、僕が実際に書いたのはこんな感じです。

file_names = Dir.glob("*")
files = []
file_names.each do |name|
  files << File.stat(name)
end

これでカレントディレクトリの全てのファイル情報が取得できました。(今回は隠しファイルは含めていません。)

流れとしては、

  1. Dir.globでファイル名を取得
  2. filesという空の配列を用意
  3. eachによる繰り返し処理で配列filesFile::Statオブジェクトを順番に入れていく

となります。 この配列から任意のファイルの特定の情報を取り出す場合、

files[0].size

のように、インデックスでどのオブジェクトか指定したうえでメソッドを使用します。

トラップ

非常に便利なこのFile::Statですが、1点注意があります。

それはFile::Statが格納している情報にはファイル名が含まれていないということ。 これほんとトラップだと思います。 だってよく考えてください。 ここまでの流れからして、

file = File.stat("hoge")
file.name

こんなふうにすればhogeって取得できそうなもんじゃないですか。 でもダメなんです。いくら引数でファイル名を渡していようとそれはそれ、これはこれです(?)

まるで「あなたもうファイル名は知ってるじゃない。私がなんで教えてあげなきゃいけないの?」と意地悪されているような気分になります。

ほんとに謎仕様。

なので、ファイル名は別の変数で用意するか、1つのオブジェクトに入れてしまいたい場合は新しくクラスを定義するのがいいと思います。僕は後者の方法で使用しました。

というわけで、今回はこんな感じです。

記載内容に間違い等があった場合にはこっそり教えていただければ幸いです。 最後までお読みいただきありがとうございました。

【Ruby】case文をハッシュに置き換えると幸せになれるかもしれない話

rubocop大先生に怒られる

先日あるプログラムを書いていて、一応実装が終わったのでrubocop大先生の検閲を受けた際、こんなふうにoffenceが出て怒られました。

Style/HashLikeCase Consider replacing case-when with a hash lookup

どうやら「可能であればcase文をハッシュに置き換えろ」ということのようです。 一瞬なんのことかわかりませんでしたが、ググりつつやってみて理解できたのでまとめます。

解決法

結論から言うと、変数の中身の文字列と等しい値はどれか、のような単純な条件の場合にcase文で分岐させるのではなく変数を利用してハッシュから取り出すようなロジックにしろってことらしいのです。

例えばこんな場合。

fruit = 'apple'
case fruit
when 'lemon'
  puts '黄色'
when 'orange'
  puts ''
when 'apple'
  puts ''
end

変数fruitの中身とwhen節の値とを上から順番に照らし合わせていって、真だったwhen節の式が評価されます。この場合は「赤」と表示されるわけです。

これをcase文を使わずにハッシュで再現すると、

colors = {
  'lemon' => '黄色',
  'orange' => '',
  'apple' => ''
}
fruit = 'apple'
puts colors[fruit]

こうなります。

どちらも最終的には「赤」という文字列が出力されるのですが、やってること自体は全然違います。 これ個人的にすごくアハ体験でした。 野暮ったさがないような気がします。

なぜcase文をハッシュに置き換えるほうがいいのか

リファレンスマニュアルのcase文の説明にはこうあります。

case は一つの式に対する一致判定による分岐を行います。when 節で指定された値と最初の式を評価した結果とを演算子 === を用いて比較して、一致する場合には when 節の本体を評価します。

docs.ruby-lang.org

つまり、case文は最初に指定した式とwhen節で指定する値が等しいかどうかを演算子===を用いて判定することのみに特化した文であると考えられます。

そうなると、case文を用いた場合はwhen節を上から順にひたすら照合していくことになるため、場合によっては処理に時間がかかります。

それに対してハッシュを用いた方法の場合、やることはハッシュの中からキーを使って値を取り出すだけなのでcase文を用いた場合に比べて早く処理できる可能性が高いです。

rubocopにこのoffenceが実装されるきっかけになったissueがGitHubにあったのでリンクを貼っておきます。

github.com

このissue内でも処理速度について検証が行われていて、ハッシュを使ったほうがcase文を使うよりも処理速度が速いということを確認できます。

またこれは個人的な感想ですが、上にも書いたとおりハッシュを使ったほうが読みやすいように感じました。 case分はどうしてもwhen節が大量に連なって野暮ったくなりがちだと思うので。

僕のようにプログラミングを勉強中で、超小規模なプログラムしか書かないのであれば問題ないと思いますが、大きなプログラムを作る際にはcase文だと巨大になりすぎる場合もあるように思います。

しかも速度も遅いとなれば、プログラム全体の実行速度に悪い影響を与える要因になるかもしれません。

そのように考えていっても、case文をハッシュに置き換える意義は大きいですし、だからこそrubocopにもそのチェック機能が実装されたのだと思います。

奥が深いですね。

というわけで、今回はこんな感じです!

記載内容に間違い等があった場合にはこっそり教えていただければ幸いです。

最後までお読みいただきありがとうございました。

【Ruby】カレントディレクトリのファイル名を取得する(隠しファイル込み)

したいこと

カレントディレクトリに存在するファイル・ディレクトリの名前を取得したい。隠しファイルの名前も取得したい。

※以下、この記事中ではファイルという呼び方ばかり使っていますが、基本的にディレクトリも含んでいると考えてください

Dirクラス

結論から言うと、Dirクラスのglobメソッドをつかえばいけます。

どう書けばいいかを端的に知りたい方は一番下までスクロールしてもらえればすぐコードが見られます。

docs.ruby-lang.orgdocs.ruby-lang.org

ワイルドカードの展開を行い、パターンにマッチするファイル名を文字列の配列として返します。パターンにマッチするファイルがない場合は空の配列を返します。 ブロックが与えられたときはワイルドカードにマッチしたファイルを引数にそのブロックを 1 つずつ評価して nil を返します

とのこと。 書式としてはglob(pattern, flags = 0, base: nil, sort: true)のようになりますが、第1引数のpattern以外は省略できます。 指定したワイルドカードのパターンと一致するファイル名を配列にして返してくれるメソッドです。 第1引数に指定できるワイルドカードは以下のとおり。

記号 意味
* 空文字列を含む任意の文字列
? 任意の一文字
[] 鈎括弧内のいずれかの文字
{} コンマで区切られた文字列の組合せに展開
**/ ワイルドカード */ の0回以上の繰り返し

正直**/とかはよく分からないけど今回は割愛。

で、今回のタイトルにあるとおりカレントディレクトリに存在する全てのファイルとディレクトリの名前を取得したい場合は、とにかく全ての文字列にマッチしてくれればいいので*を使ってDir.glob("*")とすればおk。秒殺。

ただし、ワイルドカードはデフォルトの挙動としてファイル名の先頭にある.にマッチしないようになっています。 つまり隠しファイルにはマッチしません。 でも隠しファイルの名前も含めて取得する必要がある場合もあると思います。 そんなときに使えるのが第2引数。 この部分にフラグを指定してやればマッチの挙動を変更できます。

フラグってなんやねんと思われる向きもあると思います。僕も思いました。 なので簡単に書いておきます。

File.fnmatch

リファレンスマニュアルでは、globメソッドの第2引数で使用できるフラグというのはFileクラスのfnmatchメソッドで使用されるものと同じだと説明されています。 ではFileクラスのfnmatchメソッドとは何でしょう。 これもリンクを貼っておきます。

docs.ruby-lang.org

ファイル名のパターンマッチ fnmatch(3) を行います。 path が pattern にマッチすれば真を返します。そうでない場合には false を返します。

というわけで、今回使っているDir.globと似たようなメソッドで、ワイルドカードにマッチするファイル名を返してくれます。 Dir.globとの細かい違いについては上記のリンクを参照してください。

肝心のフラグについてですが、以下の種類があります。

フラグ 使用時の挙動
FNM_NOESCAPE エスケープ文字 \ を普通の文字とみなす
FNM_PATHNAME ワイルドカード *, ?, []/ にマッチしなくなる
FNM_CASEFOLD アルファベットの大小文字を区別せずにパターンマッチを行う
FNM_DOTMATCH ワイルドカード *, ?, [] が先頭の . にマッチするようになる
FNM_EXTGLOB {} 内のコンマで区切られた文字列の組合せにマッチするようになる

そのままドンピシャで書いていますが、今回のように隠しファイルにもマッチしてほしい場合にはFNM_DOTMATCHを第2引数で使用すればいいということになります。 これらは定数で、File::FNM_NOESCAPEのような形で使用できます。

というわけで、隠しファイルも含めたカレントディレクトリのファイル名を取得するには、

Dir.glob("*", File::FNM_DOTMATCH)

とすればおkです。

息子さんが隠しているあんなファイルやこんなファイルも全て衆目に晒すことができます。いともたやすく行われるえげつない行為(D4C)ですね。

では、今回はこんな感じです。 最後まで読んでいただきありがとうございました。

【Ruby】IndexErrorを起こさずに要素数の異なる二次元配列(配列の配列)をtransposeする

したいこと

RubyのArrayクラスが持つインスタンスメソッドtransposeはレシーバとなる二次元配列内の要素数が一致していないとIndexErrorが発生して上手く動かないため、それを避けるために各配列の要素数を揃える処理を書きたい。

二次元配列って何さ?

二次元配列というのは「配列を要素として持っている配列」のことです。

こんな感じ。

array = [["a", "b", "c"], ["d", "e", "f"], ["g", "h", "i"]]

中に入っている配列は外側の配列arrayの要素なので、添字がついています。 もし["a", "b", "c"]を呼び出したければarray[0]とやればいいし、更にその中の"b"を呼び出したければarray[0][1]とすればOK。

普通の配列を任意の要素数で区切って二次元配列を作ることができるメソッドもある。これはまた別の機会に書きます。

それと、今更だけどこの「配列の配列」を「二次元配列」と呼ぶのが一般的かどうかはよく分からない。けどたぶん通じる。

transposeメソッドって何さ?

Arrayクラスのインスタンスメソッド。

何ができるメソッドなのかを理解するためにとりあえずリファレンスマニュアルを読みます。

自身を行列と見立てて、行列の転置(行と列の入れ換え)を行います。転置した配列を生成して返します。空の配列に対しては空の配列を生成して返します。

それ以外の一次元の配列に対しては、例外 TypeError が発生します。各要素のサイズが不揃いな配列に対しては、例外 IndexError が発生します。

出典:docs.ruby-lang.orgclass Array (Ruby 3.0.0 リファレンスマニュアル)

とのこと。

僕と同じぐらいのプログラミングレベルのそこのあなた。

分かります。その顔は「日本語でおk。」の顔です。僕には分かります。

特に「行列と見立てて」の意味がわからなくないですか?僕は分かりませんでした。 初見で分かった人は結構すごいと思うので、オプーナを買う権利を与えます。

コードで見てみます。

#この配列を行列と見立てると、
array = [["a", "b", "c"], ["d", "e", "f"], ["g", "h", "i"]]

#こんな感じ
array = [["a", "b", "c"],
         ["d", "e", "f"],
         ["g", "h", "i"]]

#これをtransposeするとこうなる
array.transpose
=>[["a", "d", "g"]["b", "e", "h", ]["c", "f", "i"]]

リファレンスマニュアルの説明にある「行列の転置(行と列の入れ換え)」というのはこういうこと。 言い方を変えると、各配列のインデックス番号が同じものをまとめて配列にする。(例えばインデックス番号が0である"a", "d", "g"がまとめられて配列になる。)

で、各要素のサイズが不揃いな場合はIndexErrorが発生しますよと。 つまり仮に要素数が3つの配列と5つの配列と7つの配列があったとして、それらの行と列を入れ替えようと思っても、そもそも持っている要素の数があっていないから行列に見立てることができずにtransposeさん的にはNGになっちゃうってことのようです。

本題

さて、今回やりたいことは冒頭に書いたとおりtransposeメソッドを使用する際にIndexErrorが発生するのを回避すること。そのために配列の要素数を揃えたい。

例えば以下のように要素数の異なる配列を要素として持つ二次元配列があるとします。

array = [["a", "b", "c"], ["d", "e", "f", "g"], ["h", "i"]]

これをtransposeしようとすると以下のようにエラーが発生します。 f:id:ham-cap:20210317140205p:plain こうならないためには各配列の要素数を一致させる必要があります。 どうするかというと、素数が足りていない配列にnilを追加するだけです。 他にもっといいやり方があるのかもしれませんが、僕にはこれぐらいしか思いつきませんでした。

これを実装するために必要な処理を考えてみた結果、以下の流れでいけるのではと思いました。

  1. 最も多くの要素を持つ配列を見つけて、その要素数を上限値として設定する
  2. 各配列の要素数を調べて、1.で設定した上限に対して足りていない配列を探す
  3. 2.で見つかった配列に対して、要素数が上限値に達するまでnilを代入する

で、僕が書いたコードがこちら。

#要素数の異なる二次元配列
array = [["a", "b", "c"], ["d", "e", "f", "g"], ["h", "i"]]
#変数maxを用意し、配列array内で最も多い要素数を代入する
max = array.max_by { |a| a.size }.size
#各配列の要素数が最大値に達するまでnilを代入し、結果を変数adjusted_arrayに代入する
adjusted_array = array.each do |a|
                    while a.size < max
                      a << nil
                    end
                  end
=> [["a", "b", "c", nil], ["d", "e", "f", "g"], ["h", "i", nil, nil]]

で、これをtransposeすると、

adjusted_array.transpose
=> [["a", "d", "h"], ["b", "e", "i"], ["c", "f", nil], [nil, "g", nil]]

できました。

できる人からすると「ふーん。」って感じだと思いますが、whileを使うことを思いついたときはちょっと嬉しかったです。 ちなみに、僕はmax_byメソッドも知らなかったですし、whileを実戦投入したのも初めてでした。

まとめ

というわけで、見事IndexErrorを回避して要素数の異なる二次元配列をtransposeすることに成功しました。

僕は今回、フィヨルドブートキャンプのとある課題を作成する過程でこの処理を考えたのですが、結局そちらは二次元配列にする前に全要素数を調整するという方向性で実装することにしたため、今回の方法は採用しない予定です。

ですが、せっかく考えたものが日の目を見ないのはもったいないので今回ブログの記事にさせてもらいました。 ビギナーにとっては自分が考えたコードひとつひとつが脳みそにかいた汗の結晶なので、そのまま忘れ去るのはもったいないのです。 こんな記事でも誰かの役に立てればいいなぁと思いつつ、今回は終わりです。 もし、間違っている箇所や誤解を招く表現を見つけた方はそっと優しく教えていただければ幸いです。くれぐれも優しくお願いします。

どうでもいいですが、実はこの実装を考えていた時間よりもこの記事を書くまでにかかった時間のほうがはるかに長いです。文章で説明するの難しい。

自己紹介

始めまして。ham-cap(ハムキャップ)と申します。

今日からフィヨルドブートキャンプというプログラミングスクール(コミュニティ?)でWeb開発について学び始めました。

カリキュラムの中にアウトプットの練習としてブログ開設も含まれていたのと、もともとブログをやってみたいと思っていたので、サクッと開設して早速初めての記事を書いているというわけです。

 

自己紹介がてら学習遍歴を書いてみます。

・Progate(HTML&CSSjQueryJavaScript、Sass、Command Line、SQL、Git、RubyRuby on Rails

・ドットインストール(Ruby

Railsチュートリアル(1〜10章)

 

うん。初心者ですねw

なんとなくお察しの方もいらっしゃると思いますが、Railsチュートリアルの11章の最初ぐらいで「なるほど。完全に理解した←」という状態になりましてプログラミング学習において本格的に課金することを決意しました。(それ以前にちょっと金ドブしてますが、それはまた別のお話w)

 

で、ツイッターで情報収集したところフィヨルドブートキャンプというサービスがめちゃくちゃ( ・∀・)イイ!!と聞きまして、早速受講者や運営側のブログを読んだりツイッターで検索したりして評判を確認。どうやら信用できそうだと思えたので申し込みをしたのが今日の午前中でした。

 

さて、プロフィールにも書きましたが、このブログは基本的にはプログラミング学習の進捗状況のアウトプットとしてゆるめに書いていく予定です。

イッタランドでエンジニア界隈の方々の恐ろしさを垣間見ているので、技術関係の踏み込んだ話についてはできる限り正確に書いていくつもりですが、当然間違うこともあります。

初心者というのを言い訳にしてはいけないとはわかっていますが、どうぞお手柔らかにお願いできればと思います。

 

とまぁプログラミングがどうのこうのと情報発信することに若干ビビっているのも事実なんですが、せっかくブログを公開するわけですから、僕と同じようにプログラミングを学んでいる方とも繋がっていけたらいいなと思いますので気軽に絡んでいただければ嬉しいです。

 

そんなわけで今日からよろしくお願いします。

今日はこんな感じです。