# Ruby(01/14) Day 26 五倍紅寶石(第八屆共筆)(2021/8/02)
## 慣例
- 幾乎所有東西都是物件,連數字也是,會有狀態跟行為
- 命名用蛇式 snake_case
- `+ - * / =` 都跟我們平常的認知不同
其實這些運算是方法,後面的值是參數
ex: 5 + 3
可以看成 5 .+ (3)
5 這個物件用 + 方法,帶入 3 這個參數
ex: 5 == 3 (5跟3比較)
可以看成 5 .== (3)
5 這個物件用 == 方法,帶入 3 這個參數
- 結尾不加 ;
- 用兩格空白做縮排
- 參數不用 ( ) 包起來
- 註解用 #
- 只有 nil 跟 false 是假的,其他都是真的
- nil = 用物件來表示不存在或是空值
- do end 可以跟 { } 做替換
- 方法有寫 ? 通常會回傳布林值
- 方法有寫 ! 通常會有副作用,最好先看手冊再用
## 印東西出來
= JS console.log()
### puts
只能印出值,會換行,沒有回傳值
### print
只能印出值,不會換行,沒有回傳值
### p
能印出型態跟裡面的值,會換行,有回傳值
## 宣告變數、常數
### 兩者差異:
在 Ruby 只差在命名方式不同而已
變數用小寫英文當開頭 a = 1
常數用大寫英文當開頭 A = 1
如果把常數 reassigned,Ruby 只會警告你,不會噴出無法重新賦值的錯誤訊息,還是可以正常運作
### 變數種類
- 區域變數:username
- 全域變數:$username
預設值 = nil
- 實體變數:@username
預設值 = nil
- 類別變數:@@username
## array 陣列
```=rb
a = [1, 2, 3, 4, 5]
# 印出最後一個元素
puts a[-1]
puts a[last]
# 印出第一個元素
puts a[first]
# 在 rails 裡面可以用 second 或 third 印出第二、第三元素,但 Ruby 內沒有
# 印出 [1, 2,... , 9, 10]
p (1..10).to_a
```
### 加入元素
- .push
- <<
## range 範圍
1~10
(1..10)
a~z
("a".."z")
A~Z
("A".."Z")
## hash 雜湊
跟 JS 物件寫法類似,用在有一堆資料要儲存的時候,沒有順序之分
```=rb
# name 是 key,"kk" 是 value
# 下面是語法糖衣,後來才有的,因為別的程式都這樣寫,改這樣比較方便
a = {
name: "kk",
age: 31
}
# 原本長下面這樣,:name才是他 key 的真面目
# : 叫做符號
a = {
:name => "kk",
:age => 31
}
# 如果要印出 name 的值要寫
p a[:name]
# 不能寫
p a["name"]
# 印出所有 key 或 value
p a.keys
p a.values
```
## method 方法
**在 Ruby 的物件沒有屬性,只有方法。**
如果有同樣名稱的變數跟方法,沒有用()呼叫的時候,會優先讀取到變數。
```=rb
# 方法寫法:
def aa()
end
# 如果沒參數可省略()
def aa
end
# 有參數也可省略(),但會不好閱讀,所以不建議省略
def aa(name)
# 用雙引號或是%Q()搭配 #{} 可印出變數值
puts "hi #{name}"
# 用單引號或是%q()無法印出變數值
puts 'hi #{name}'
end
# 如果引數跟變數數量不同會噴出 ArgumentError(given 2,expected 1)
aa("kk", 123)
# return 跟 JS 一樣會有回傳值,不會印出
# 方法內的 return 通常會省略,沒寫的話會自動回傳最後一行的結果
def say_hello
# 印出 hi
puts "hi"
end
# 印出 nil,因為沒寫 return 會自動回傳最後一行的結果,且 puts 沒有回傳值
p say_hello
```
- .map = .collect
對每個元素做事
- .filter = .select
過濾我要的出來
- .reject = 相反的 .select
過濾掉我不要的
- .reduce = inject
歸納,通常用在加總
### 沒有 scope chain
在 ruby 的方法內的變數如果沒定義不會跑出去外面找,跟 JS 不同
```=rb
a = 1
def hello
puts a
end
# 噴出NameError => 沒有 a 這個變數
hello()
```
### 小數點
可用 to.f 轉換成浮點數,或是運算時直接改成有寫小數點
```=rb
puts 10/3.0 => 3.333
puts 10/3 => 3 (無條件捨去)
```
#### 進位
- .round()四捨五入
- .floor()無條件捨去
- .ceil()無條件進位
- .to_i()無條件捨去
.round(2) 代表四捨五入至小數點後第二位
## 判斷式
### if else
elsif 中間沒有 e,因為跟 elseif 唸起來都一樣,但比較短
[小弘說法](https://twitter.com/yukihiro_matz/status/989061019287900162)
```=rb
a = 1
if (a > 0)
puts "hi"
elsif (a > 1)
puts "hello"
else
puts "oaoaoa"
end
```
#### if 倒裝句
```=rb
puts "宅在家裡" if weather == "下雨"
# 等同於
if weather == "下雨"
puts "宅在家裡"
end
```
#### if 超省略寫法
```=rb
def is_adult?(age)
if age >= 18
return true
else
return false
end
end
# 可寫成:
def is_adult?(age)
age >= 18
end
```
### unless
沒事不要用 unless,用 if not 就好,不要搭配 else 使用,會變得不好懂
unless = if not
unless not = if
### case when
if else 的語法糖衣
```=rb
# .. 代表 range 範圍,0..3 等同 age >= 0 且 age <= 3
case age 0..3
puts ...
when age 4..10
puts ...
when age 11..18
puts ...
else
puts ...
end
```
## 例外處理
跟 JS 的 try、catch 一樣, Ruby 用 begin、rescue去做
Ruby 的錯誤類型都可以被歸在 Exception 底下,StandardError 只是其中的一個比較大的錯誤類型
StandardError 代表常見的錯誤類型,下面還有很多子錯誤
Ruby 的錯誤類型:[Exception](https://ruby-doc.org/core-2.5.1/Exception.html)
```=rb
# 分母帶0會得到 ZeroDivisonError
# 寫法1:
def tt(a, b)
return a / b
end
# 用 begin、rescue 捕捉錯誤
begin
tt(1, 0)
# 用 StandardError 可以捕捉到所有常見錯誤,也可以不省略不寫,變成 rescue => e
rescue StandardError => e
puts e
end
# 寫法2:
def tt(a, b)
return a / b
## 可以省略 begin end 不寫,只寫 rescue 就好
rescue => e
puts e
end
# 用 begin、rescue 捕捉錯誤
begin
tt(1, 0)
# 用 StandardError 可以捕捉到所有常見錯誤,也可以不省略不寫,變成 rescue => e
rescue StandardError => e
puts e
end
```
## 迴圈
### REPL 無窮迴圈
一直在空轉,一個互動式環境
Read-Eval-Print Loop
讀取-評估(evaluate)-輸出 循環
在 node 或 irb 環境內就是一直在做這個循環
### for
迴圈:以圈數為主,看要繞幾圈 => for 迴圈
迭代:以元素為主,全部元素巡一次 => 類似 forEach
```=rb
for name in names
puts name
end
```
### while
```=rb
# 條件寫在外面
x = 0
while x < 10
puts x
# Ruby 沒有 x++ 的用法
x += 1
end
```
until = while not 沒事別用 until,不好懂
### loop
```=rb
loop do
puts i
i += 1
# 條件寫在裡面
break if i > 10
end
```
### method 式迴圈
```=rb
# 印出五次 hello ruby
5.times do
puts "hello ruby"
end
# 印出1~10
1.upto(10) do |i|
puts i
end
# 印出10~1
10.downto(1) do |i|
puts i
end
```
## Std 標準庫
為了省效能,不常用的方法不會放在裡面
要用的時候可以用 require "" 打包進來用
---
###### tags: `Ruby`