💎

TypeScriptエンジニアがRubyを触って戸惑っている点

2024/01/04に公開

自分はこれまで、TypeScript&Node.jsでバックエンドを書いてきましたが、約1ヶ月前にRailsでバックエンドを構築している会社に転職し、現在キャッチアップ中です。
その中で、たくさん戸惑う点があるのですが、ここではその内の一部をピックアップして紹介します。

シンボルの存在

シンボルとは、以下のような表記をするもので、基本的には文字列と同じような使い方をします。

:apple # こっちがシンボル
'apple' # こっちは文字列

ちなみに、JavaScriptにもRubyとは若干性質の違うシンボルは存在しますがあまり使ったことはなかったです。一方でRubyの場合は文字列と同じような感覚でめっちゃ使います。

最初これをみた時は、いや文字列だけでいいじゃん!と思いましたが、以下のような違いがあるようです。

  • シンボルは内部的には整数のため2つの値を比較する時、文字列よりも高速に比較できる
  • 同じシンボル(例えば上記の:appleを複数作るような場合)であれば全く同じオブジェクト(=参照先が同じ)であるため、複数生成する場合はメモリの使用効率が良い
  • イミュータブルのため書き換えできない

mapの中でreturnすると外側のメソッドをreturnしてしまう

こちらは、ハマった内容がそのまま以下の記事に記載されていたのでリンクを貼らせていただきます。

https://qiita.com/comorebi_notes/items/55526fe45a400383bb83

***

Rubyでは、あまり見慣れない***という記法がちょくちょく出てきます(ここで紹介するのは、もちろん掛け算やべき乗の演算子としての役割ではありません)。

*の用途

  • 配列の展開
    以下のように配列を展開する時に使います。
a = []
b = [1,2]
a.push(*b)
  • メソッドの可変長引数
    以下のように、個数に制限のない引数(=可変長引数)を受け取る時に使います。
def method(args1, args2, *other)
end

**の用途

  • ハッシュの展開
    *で配列を展開できたのと同様に、**を使うとハッシュを展開できます。
hash = { length: 50, width: 50}
{color: 'black', **hash}
  • キーワード引数
    以下のように、任意のキーワード引数を受け取る時に使います。
def foo(**hash)
  p hash #=> {:a=>1, :b=>2}
end

foo(a: 1, b: 2)

クラスのprivateメソッドは継承したサブクラスからも使える

他の言語だと普通、以下のイメージですよね。

  • public:どこからでもアクセス可能
  • protected:クラス内、サブクラスからアクセス可能
  • private:クラス内のみアクセス可能

ただ、Rubyの場合、privateメソッドは継承したサブクラスからも使えます。
え、じゃあprotectedとprivateの違いは何?ってなりますよね。

そんな方には以下の記事の解説が詳しくて勉強になると思います(逃げ)。

https://qiita.com/tbpgr/items/6f1c0c7b77218f74c63e

インターフェースがない&モジュールの存在

これは単純に慣れの問題かもですが、インターフェースの機能がないのは、疎結合な設計をする上でやっぱり少し辛いのかなと思っています。
みなさん、以下のような形で工夫されてそう。

https://qiita.com/developer-kikikaikai/items/b1e2bd1c2bbc223de534

また、モジュールの存在もこれまでにはあまり触れてこなかったものなのでまだ仲良くなりきれてない。具体的には、以下あたりが少しきつそう。

  • includeしたモジュールが複数あった場合、関数名の衝突などを考慮する必要がある
  • ぱっと見、関数がどこで定義されたものなのかわかりにくい(includeしたモジュールなのかクラス内なのか)

まとめ

これまでTypeScriptを主に使ってきた自分からすると、結構クセのある言語だなーという感じがありますが、逆に言うと勉強しがいのある言語で、「こんな書き方あるのか」と毎日新しい発見があって(今のところ)楽しいので、引き続き仲良くなれるよう精進していきます。

Discussion