プログラミング初心者が問題解いてみた　１.スコープと戻り値

#はじめに
はじめまして。自分はプログラミング初心者ですが、一つのプログラムを解いてみました。
その備忘録として本記事を書きます。
Qittaへの投稿は初めてであるため、お見苦しい点や至らない点等あるかとございますが、ご容赦ください。
参考や引用に使用させていただいたサイトは「終わりに」の部分にまとめてあります。
#動作環境
本記事はRubyの環境で動作確認をしております。
また、自分は主にCloud9を使用してプログラムを実行しています。
#この記事の方針
```ruby

def rename(name) 
  name = "#{name}::CAMP"
  return name
end

name = "TECH"
rename(name)
puts name

```
上記のプログラムの結果がどのような理由で出力されるのかを確認していく。
#実行結果の分析
最終的な結果としてターミナルに出力されたのは以下のコードです。

```ruby
TECH
```
この出力された値は「name = "TECH"」で「name」という変数に代入された「TECH」であろうことは何となく予想がつきます。

何故ならこれ以外にコード上に「TECH」という値が見当たらないからです。

主な問題は２点です。
１つは、renameメソッド内にある「name = "{name = #{name::CAMP}}"」という変数nameが出力には何も影響していないこと。

そしてもう１つが、「rename(name)」でrenameメソッドを呼び出しているにも関わらず、出力されていないこと。
####スコープ
まず、1つ目の”renameメソッド内にある「name = "{name = #{name::CAMP}}"」という変数nameが出力には何も影響していない”という問題を解決するのに必要な知識がスコープです。

スコープとは何なのか、Wikipediaによると、
>スコープとは、ある変数名や関数名といった名前を参照できる範囲のこと。ある範囲の外に置いた変数等は、通常、その名前だけでは参照できない。このときこれらの変数はスコープ外である、「見えない」といわれる。 

この説明だとわかるようなわからんような、といったように感じます。

つまり、プログラミングでは変数や関数が使える範囲と使えない範囲が存在するということだと自分は認識しています。

この「変数や関数が使える範囲」のことが「スコープ」であるというイメージです。
本記事のコードで具体的に見て行きましょう。

```ruby

def rename(name) 
  name = "#{name}::CAMP" #この変数nameはrenameメソッド内でしか使用できない。
  return name
end

name = "TECH" #この変数nameはこの行より下ならどこでも使える。
rename(name)
puts name

```
上記のコードのコメントで書いたとおり、本記事のコードの場合、renameメソッド内の変数nameはrenameメソッド内でしか使えません。

ついでに言うとrenameメソッドの引数nameもrenameメソッド内でしか使えません。

正確には、ブロック内で定義された値はそのブロック内でしか使用できません。
このようなスコープはローカルスコープと呼ばれているようです。

また、本記事のコードの場合、スコープ外で定義された変数は、定義された位置より下ならどこでも使用が可能です。

この変数nameは関数の内側でも、外側でも関係なく使用できます。

実際に確かめてみましょう。本記事のコードを以下のように書き換えて実行してみます。


```ruby

def rename(name) 
  name1 = "#{name}::CAMP"
  return name
end

name2 = "TECH"
rename(name2)
puts name1

```
プログラムを実行するとエラーメッセージが出力されると思います。

これは先ほど説明した通り、renameメソッド内の変数name1はrenameメソッド外では使用できないからです。

では、「puts name1」を「puts name2」に変更してプログラムを実行してみましょう。

```ruby
TECH
```
上記のように出力されるはずです。

これで、なぜrenameメソッド内の変数nameが出力には影響しなかったのかが理解できたかと思います。

実際にコードを書く際は予期しない動作を避けたり、コードの読みやすさを重視するためにスコープの範囲はできるだけ小さくしたほうがいいと思います。

また、スコープにもいくつか種類があるので、Wikipedia等を参照してください。
###戻り値
さて、もう１つの「rename(name)」でrenameメソッドを呼び出しているにも関わらず、出力されていない、という問題を解決していきましょう。

コードをもう一度確認してみましょう。

```ruby

def rename(name) 
  name = "#{name}::CAMP"
  return name
end

name = "TECH"
rename(name)
puts name

```
先ほど変数nameを「name1」や「name2」にしていましたが、すべて「name」に直しました。

まず、renameメソッドがどういった処理が行われているのか確認していきましょう。

renameメソッドは引数を受け取り、受け取った引数を利用して変数nameを定義し、定義した変数nameを「return」でrenameメソッドが呼び出された場所に戻す処理が行われています。

この時に変数nameが戻り値になります。
戻り値とは何なのかIT用語辞典 e-Wordsによると、
>戻り値とは、プログラム中で呼び出された関数やメソッド、サブルーチンなどが処理を終了する際に、呼び出し元に対して渡す値。

何となくこの説明でも理解はできますが、かみ砕いて要約すると”関数等で呼び出し元に「return　値」で指定した値を渡す”といった感じでしょう。

実際に本記事のコードで確認してみましょう。

```ruby

def rename(name) 
  name = "#{name}::CAMP"
  return name #変数nameという値をrenameメソッドの呼び出し元に渡す。
end

name = "TECH"
rename(name) #renameメソッドの呼び出し元。
             #renameメソッド内で定義された変数nameがここに渡される。
puts name

```
上記のコードのコメント部分に書いた通り、「rename(name)」はrenameメソッド内で定義された変数nameの値になる。

なのになぜ、ターミナルには出力されないのか。
これは「return」は値を呼び出し元に返しているだけで、出力するという命令はしていないからです。

もし、本記事のコードでrenameメソッドの戻り値をターミナルに出力しようとした場合、「rename(name)」のコードを「puts rename(name)」に書き換えましょう。

すると、以下のコードが出力されるはずです。

```ruby
TECH::CAMP
TECH
```
戻り値をターミナルに表示したい場合は、出力を命令するコードを書くことに気を付けましょう。

#まとめ
本記事のコードの実行結果が「TECH」という値しかターミナルに表示されない理由は、

1. renameメソッド内で定義された変数nameは、スコープによってrenameメソッド外では使えないため、本記事のコードの「puts name」の部分には全く関係しないこと。

2. 戻り値は呼び出し元に「return 値」で指定した値を渡せるが、出力を命令するコードがないとターミナルには表示されないこと。

という2点であるというわけです。

#終わりに

最後まで自分の稚拙な記事を読んでいただきありがとうございました。
間違いや良くない点等多々あったかと思いますが、一応1つの記事を書き上げることができました。

次の機会があれば、本記事を書いて得た経験を活かしてより良い記事を作りたいと思います。

最後に引用に使ったり、参考にさせて頂いたサイトをまとめておきます。
[スコープ - Wikipedia](https://ja.wikipedia.org/wiki/スコープ)

[第3回　スコープを意識したプログラミング―その1　スコープって何？](https://gihyo.jp/dev/serial/01/code/000301)

[戻り値（返り値）とは - IT用語辞典 e-Words](http://e-words.jp/w/戻り値.html)

[Qiita Markdown 書き方 まとめ](https://qiita.com/shizuma/items/8616bbe3ebe8ab0b6ca1#3%E3%83%AA%E3%83%B3%E3%82%AF%E3%81%AE%E6%8C%BF%E5%85%A5%E7%94%BB%E5%83%8F%E3%81%AE%E5%9F%8B%E3%82%81%E8%BE%BC%E3%81%BF)