--- title: Astro課程 0709 - Ruby (Day1) tags: astro, ruby --- # 0709 Ruby (Day1) # 在螢幕上印出 ``` print "ab" puts "cd" #print + 換行 p "ef" #印出完整的資訊 ``` `p` 印出完整資訊,適合用來除錯 ``` a = [1 ,2 ,3] puts a # 1 2 3 print a # [1, 2, 3] 沒換行 p a # [1, 2, 3] + 換行 ``` # 程式撰寫風格 有很多種寫法 ``` a = [1, 2, 3] a = [1,2,3] {name: 'kk', age: 18} {name:'kk', age:18} { name:'kk', age:18 } { name:'kk', age:18 } ``` REPL = Read-Eval-Print Loop 註解:用來解釋Why的時候再寫 # 變數 全域變數 `$username` (盡量不要使用) 區域變數 `username` 實體變數 `@username` 類別變數 `@@username` # 邏輯短路 `a && b`: 前面`成立`才會做下一步,前面不成立不做下一步 `a || b`: 前面成立就不用做下一步,前面`不成立`會做下一步 ``` def a return 1 end def b return 2 end p a && b # 2 p a || b # 1 ``` ## `&&` vs `&` `&&` 前面的成立才會做下一步 ```ruby def a puts "aaa" # puts沒有回傳值 end def b puts "bbb" end a && b # => aaa a & b # aaa bbb ``` ## a && b的意義 a && b 的意義接近以下: ``` if (a) b end ``` ## `puts`沒有回傳值,但是`p`有回傳值 ``` def a p "aaa" end def b p "bbb" end a && b # => "aaa" "bbb" ``` 進入`irb`看`puts`和`p`的差異: ``` 2.5.2 :001 > puts "aaa" aaa => nil # 回傳的值 意思是 沒有結果 2.5.2 :002 > p "aaa" "aaa" => "aaa" #回傳它自己的東西 2.5.2 :004 > p nil nil => nil 2.5.2 :005 > puts nil => nil ``` ## `nil` vs `null` 在Ruby裡`nil`也是一個物件,代表的意思是不存在 因為是物件,所以可以操作 ``` 2.5.2 :002 > nil.nil? => true ``` 不同的程式語言`null`有不同的定義 ## `false` 和 `nil` `false` 和 `nil`是 `false` ``` def a nil end ``` 等於 ``` def a end ``` 回傳值是`nil` ## `2` 在Ruby裡2本身就是一段合法的語法 (expression),所以有回傳值 ``` 2.5.2 :003 > 2 => 2 ``` ## `||` a || b 前面成立,後面就不用做 ``` def a p "aaa" end def b p "bbb" end a || b # => "aaa" ``` ## `||=` ``` a = 1 puts a ||= 2 # => 1 ``` 如果 a 是 nil 或 false,就指定為後面的值 ``` a = false puts a ||= 2 # => 2 ``` ## 命名慣例 camelCase: `firstName` (Java常用) snake_case: `first_name` (Ruby. Python常用) ## 練習題 ``` x = 2 y = 3 請寫一段程式讓 x 與 y 對調 ``` 寫法一: 利用另一個變數暫存 ``` x, y = [2, 3] w = x x = y y = w puts x # 3 puts y # 2 ``` Ruby的特別寫法! ``` x, y = y, x # 直接交換 puts x puts y ``` # 常數 `大寫字母開頭`就是常數 `Pi = 3.1415` 在Ruby世界,常數是可以被修改的(會發生警告,但是可以執行) ```ruby 2.5.2 :001 > A = 1 => 1 2.5.2 :002 > A = 2 (irb):2: warning: already initialized constant A (irb):1: warning: previous definition of A was here => 2 ``` javascript: 不能修改 ```javascript var a = 1; undefined const b = 2; undefined b = 1; VM172:1 Uncaught TypeError: Assignment to constant variable. at <anonymous>:1:3 ``` # 變數 可以換掉集合裡的元素 (指標仍然指向同一個地方) - 字串 - 陣列 - Hash 都可以被修改 (但是數字不行修改!) 陣列 ```ruby 2.5.2 :003 > a = [1, 2, 3] => [1, 2, 3] 2.5.2 :004 > b = a => [1, 2, 3] 2.5.2 :005 > b [1] = "a" => "a" 2.5.2 :006 > b => [1, "a", 3] 2.5.2 :007 > a => [1, "a", 3] ``` 字串是類似連續的字元陣列 ``` 2.5.2 :020 > a = "123" => "123" 2.5.2 :021 > b = a => "123" 2.5.2 :022 > b[0]="x" => "x" 2.5.2 :023 > b => "x23" 2.5.2 :024 > a => "x23" ``` `.chars` method ``` "ruby".chars => ["r", "u", "b", "y"] ``` # string 字串 用單引號或雙引號把字母串在一起 ``` quote = '單引號' double_qoute = "雙引號" ``` ## 字串串接 數字+字串,ruby 會出錯(強型別語言) ``` 2.5.2 :035 > "a" + 1 Traceback (most recent call last): 3: from /Users/tingtinghsu/.rvm/rubies/ruby-2.5.2/bin/irb:11:in `<main>' 2: from (irb):35 1: from (irb):35:in `+' TypeError (no implicit conversion of Integer into String) 2.5.2 :034 > "a" + a Traceback (most recent call last): 3: from /Users/tingtinghsu/.rvm/rubies/ruby-2.5.2/bin/irb:11:in `<main>' 2: from (irb):34 1: from (irb):34:in `+' TypeError (no implicit conversion of Array into String) ``` javascript的加和減有不同轉換方式 ```javascript "10" + 1 => "101" "10" - 1 => 9 ``` 把字串變數帶入: Ruby ```ruby 2.5.2 :036 > name = "kk" => "kk" 2.5.2 :037 > puts "Hi! My name is #{name}" Hi! My name is kk => nil ``` javascript ```javascript name = "kk" => "kk" "my name is" + name => "my name is kk" `my name is ${name}` //新型的寫法 => "my name is kk" ``` # 邏輯控制 ## if ruby ``` a = 1 if a = 2 # 新手常常忘記寫 a == 2 puts "hi!" else puts "hey!" end ``` console ``` if.rb:2: warning: found = in conditional, should be == hi! ``` ruby ``` a = 1 if a == 2 puts "hi!" else puts "hey!" end ``` console ``` hey! ``` # 等號 ``` a =10 b="10" puts a === b #=> false puts a == b #=> false puts a = b #=> 10 p a = b #=> "10" ``` `1 + 2` `1 + .(2)` # `if modifier` 倒裝句 if not x = > unless x if x => unless not x # `:Symbol` 1. `Symbol`是有名字的物件(an object with name 2. `Symbol` 不是`變數`,而是`值` 3. 一個特定`Symbol`只有一個Object id (存取時效能較好) 太大量的Symbol而沒有歸還記憶體時,會出現memory leak 冷知識: 數字的位置是在奇數記憶體上(公式2n+1) `nil`, `true`, `false`在偶數記憶體位置上 ``` 2.5.2 :001 > nil.object_id => 8 2.5.2 :002 > true.object_id => 20 2.5.2 :003 > false.object_id => 0 ``` # class `.class` method ``` 2.5.2 :007 > true.class => TrueClass 2.5.2 :008 > false.class => FalseClass 2.5.2 :009 > nil.class => NilClass ``` # method 為什麼要使用method? 1. 可一直重複使用 2. 讓程式碼更容易理解 在ruby所有的方法執行完後都有回傳值 ## 參數 parameter 與 引數 argument 傳進去的是引數,規格是參數 ```ruby def say_hello_to(someone) # someone: 參數 parameter; 規格 puts "hi!, #{someone}" end ``` `同名變數`會蓋掉`同名方法` ```ruby age = 18 def age return 20 end puts "age" # => age puts age # => 18 puts age() # => 20,呼叫方法其實是用小括號,只是平時常省略 ``` ruby引數和參數個數要一樣 但是javascript 引數的個數和參數可以不一樣 javascript ```javascript function hello(a,b,c){ console.log(a,b,c) } hello(1,2) => 1 2 undefined undefined hello(1) => 1 undefined undefined undefined hello() => undefined undefined undefined undefined hello(1,2,3,4) => 1 2 3 undefined ``` ## 回傳值 return * 回傳 = 交回控制權 1. 控制權就像令牌一樣,手上有令牌,才能執行程式碼 2. 執行完後,把控制權交給呼叫的程式 ```ruby def calc_perimeter(radius) return 2 * Math::PI * radius # return: 把控制權交還給當初呼叫他的人 end puts calc_perimeter(5) # => 31.41592653589793 ``` 1. 呼叫calc_perimeter方法,並傳回5作為引數 2. 執行calc_perimeter方法 3. return交還控制權,並同時回傳計算結果 4. 把計算結果交給puts方法,並印出內容 # Rake 早期的linux `make install`,是寫在makefile裡 rake = ruby make `touch rakefile` ``` desc "migrate" namespace :db do task :migrate do puts "migrate!!!" end end ``` ```  rake -T rake db:migrate  rake db:migrate migrate!!! ``` ```ruby p task p method(:task).source_location p Rake::Task.method(:define_task).source_location p Rake.application.method(:define_task).source_location ```