search
LoginSignup
1
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

Ruby その2 Advent Calendar 2020 Day 15

Organization

他言語の視点で見るRuby

はじめに

Ruby その2 Advent Calendar 2020 15日目の記事です!!

今年の秋頃に、Ruby Association試験を受けました。

その時の試験勉強中に、「Rubyだとこう書くのか〜〜」とか「Rubyだとこの意味になるのか〜〜」みたいなことがただあったので、本当に軽く紹介しておきます!!

(全然知らないことが多いので、多めにみてください。。。)

勉強した時の教材はこちらから。気になったは人はやってみてください!!
https://gist.github.com/sean2121/945035ef2341f0c39bf40762cd8531e0

begin ~ resucue

Rubyの例外処理と言いたら、これ。
beginブロック内で発生したエラーをresucueで拾い、エラーハンドリングをするものです。

begin
  1 / 0
rescue ZeroDivisionError => error
  p error
end

# => #<ZeroDivisionError: divided by 0>

他の言語では、try ~ catchが大半だと思います。

try {
  nonExistentFunction();
} catch (error) {
  console.error(error);
}

// > ReferenceError: nonExistentFunction is not defined

Rubyでのtryとcatch

try

Rubyにもtryはありますが、例外処理のメソッドではなく、オブジェクトに対してのメソッドです。
https://www.rubydoc.info/docs/rails/4.1.7/Object:try

Rubyでのtryは、&.ほぼ同意義です。(&.のことをnilガードと呼ぶことが多いです。)
「ほぼ」なので、少しだけ違いがあります。

&.は、オブジェクトがnilでない場合にメソッドを呼び出します。
try は、オブジェクトのメソッドを呼び出すことができるときにメソッドを呼び出します。

# &.
10&.to_s        # => "10"
10&.hoge        # => Error: undefined method `hoge' for 10:Fixnum (NoMethodError)
nil&.to_s       # nil

# try
10.try(:to_s)   # => "10"
10.try(:hoge)   # => nil
nil.try(:to_s)  # => nil

catch

Rubyでのcatchは、ブロック内でthrowが走った時にその引数と一致していれば、抜けることができるものです。
throw ~ catchでワンセットですね。

catch :error do
  puts "hoge"
  throw :error
  puts "fuga"
end
# => hoge

これはこれで、begin ~ rescueと書き方が似てはいますが、だいぶ違います。
詳しくはこちら。
https://qiita.com/harvath/items/e716179538bc1da30f88

例外処理よりかは、C言語のgotoに近いものですね。

*変数

C言語やGo言語を書いている人にとっては、*変数はかなり見覚えがあると思います。

みんな大好き、ポインタです!

tour_of_go.go

import "fmt"

func main() {
    i, j := 42, 2701

    p := &i         
    fmt.Println(*p) 
    *p = 21         
    fmt.Println(i)  

    p = &j         
    *p = *p / 37   
    fmt.Println(j) 
}

/*
42
21
73
*/

ポインタは、値のメモリアドレスを指します。
簡単に表すとこんな感じです。(例:go)

i := 42
p := &i

fmt.Println(p)  // 0xc000122020
fmt.Println(&p) // 0xc000124018
fmt.Println(*p) // 42

fmt.Println(i)  // 42
fmt.Println(&i) // 0xc000122020
fmt.Println(*i) // エラーになる
変数 アドレス値
i i = 42 &i == p = 0xc000122020
p *p == i = 42 &p = 0xc000124018

ポインタについてはこちら。
https://qiita.com/yz2cm/items/01908cdfe56c304f2a14

ただ、Rubyでの*変数ポインタではありません!!(初めて知った時、めっちゃポインタだと勘違いしていた。。。)

Rubyでは、変数を配列にするものです。つまり、to_aメソッドと同じ意味のものです。
メソッドのキーワード引数につけると、可変長引数として利用できます。

def foo (a, *b)
  p a, b
end

foo(1, 2, 3, 4)

# => 1
# => [2, 3, 4]

**変数

ちなみに、Rubyでは**変数も書くことができます。これは、Hashを意味していることが多いです。

def variadic_keyword(**hash_args)
  p hash_args
end

variadic_keyword(april:"spring", july:"summer")

# => {:april=>"spring", :july=>"summer"}

終わりに

本当にざっくり簡単に軽くまとめました!!

これ以外でもいろいろあると思うので、その都度更新していきます。
(試験の結果は聞かないでください。。。。)

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
1
Help us understand the problem. What are the problem?