Ruby学习笔记

引子

刷了codecademy的ruby基础,简单做了笔记。

记住两句话:

Almost Everything in Ruby is an Object. [except block]

Every operation in Ruby is a method call.

正文

基础概念
  • data Types: Numbers, Strings, Booleans
  • Puts and print:
    • Print 输出不换行
    • puts 输出换行
  • Comments in Ruby
    • Single-line : use # sign for comment in Ruby
    • Multi-line :
      =begin
      略
      =end
      
  • getting input
    • gets.chomp:
      variable_name = gets.chomp
      
      gets is the ruby method that gets input from the user. When getting input, Ruby automatically adds a blank line (or newline) after each bit of input.chomp removes that extra line.
Control Flow in Ruby
  • If … elsif…else…end
  • Unless : use control flow to check if something is false.
  • Comparators operators, like ==,!=,<, >and so on.
  • Logical operators: and(&&), or(||) , not(!)
  • As a general rule, Ruby methods that end with ? evaluate to the boolean values true or false. For example , .include?method

​ 字符替换方法:.gsub!,(global substitution) 通常method后面加上!的表示对这个变量本身做修改,如果没有!,则是复制了该变量,在复制的变量上做了更改。

Loops & Iterators
  • while ,until, for
  • for中,当有三个.时,比如for num in 1…10, 循环9次,不包括10,当有两个.时,比如for num in 1..10,循环10次,包括10
  • break退出循环,例如:

    1
    2
    3
    4
    5
    6
    i = 20
    loop do
    i -= 1
    print "#{i}"
    break if i <= 0
    end
  • Next! 用于跳过一些步骤,例如:

    1
    2
    3
    4
    for i in 1..5
    next if i % 2 == 0
    print i
    end
  • .each iterator

  • .times iterator
Data Structure: Array and Hashes
  • Array: index from 0
  • Hashes: sort of like JavaScript objects or Python dictionaries, is a collection of key-value pairs

    hash = {
      key1 => value1,
      key2 => value2,
      key3 => value3
    }
    
    • Hash.new 会新建一个空的hash,类似于生成了一个空的{}

    • 可以给一个hash附上默认值,但是hash仍是空的表,当你访问一个不存在的key时,会返回这个默认值。例如:

      h = hash.new("nothing")
      puts h
      # {}
      puts h["kitty"]
      # nothing
      
    • 遍历hash,使用.each:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      pets = {

      "dog" => 12

      "cat" => 12

      "mouse" => 3

      }

      pets.each {|pet, age| puts "#{pet} : #{age}"}
Methods and Sorting
  • method

    • 当不清楚需要传递的参数有多少个的时候,用*, 即splat arguments。如: name可以是一个string,也可以是一组字符串数组
      1
      2
      3
      def friend(*name)
      puts "my friend(s) " + name
      end
  • sort

    • .sort!, 也可以自定义排序,默认是升序,例如:

      1
      2
      3
      books.sort! do |firstbook, secondbook|
      firstbook <=> secondbook
      end

      <=>是比较符号,例如:a<=>b,如果a > b, 1 ; a == b ,0 ; a < b, -1.

hashes and Symbols
  • symbol : a ruby symbol is like a sort of name,but it is not a string.
  • Symbol vs string : while there can be multiple different strings that all have the same value, there’s only one copy of any particular symbol at a given time.
  • Symbol 总是以:开始,以字母或_为首字符。
  • Symbol 大量出现在hash keys 或者referencing method names中, symbol作为hash keys的优势:
    • 不可更改:They’re immutable, meaning they can’t be changed once they’re created;
    • 节省内存:Only one copy of any symbol exists at a given time, so they save memory;
    • 快于字符:Symbol-as-keys are faster than strings-as-keys because of the above two reasons.
  • symbol 与string可以相互转化:.to_s and .to_sym or .intern
  • .select来对hash进行筛选。如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    grades = {
    alice: 100,
    bob: 92,
    chris: 95,
    dave: 97
    }

    grades.select {|name, grade| grade > 97}
    # ==> {:alice => 100}

    grades.select {|k,v| k == :chris}
    # ==> {:chris => 95}
  • .each_key ,.each_value , 可以单独访问hash的key 和value

The Zen of Ruby
  • simple, productive
  • a simpler ‘if’ : such as expression if boolean
  • One-line Unless : such as expression unless boolean
  • Ternary : boolean ? Do this if true: do this if false. For example: puts 3<4?”3 is smaller than 4”: “3 is bigger than 4”
  • the case statement:
    case language
      when "JS" then puts "Websites"
      when "Python" then puts "Science"
      when "Ruby" then puts "Web apps"
      else puts "I don't know"
    end
    
  • conditional assignment: ||=
  • return in ruby: 在ruby中,如果没有指明return,它的methods会默认return最后一个有值的表达式。
  • only false and nil are false value in Ruby.
  • .upto,.downto methods. for example:

    1
    2
    3
    4
    5
    6
    "L".upto("P") {|word| puts word}
    # L
    # M
    # N
    # O
    # P
  • .respond_to? : takes a symbol and return true if an object can receive that method and false otherwise.

    [1,2,3].respond_to?(:push)
    # true 这里因为数组是有push这个method的,所以是true
    
    [1,2,3].respond_to?(:to_sym)
    # false to_sym不能针对整个数组进行操作,所以是false
    
  • .push or << : add an element to the end of a array / string
Blocks, Procs, and Lambdas
  • Blocks : it is not a object. this is one of the very few exceptions to the “everything is an object” rule in Ruby.

    • block can be combined with methods like .each and .times to execute an instruction for each element in a collection (like a hash or array).

      1
      5.times {puts "I'm a block!"}
    • .collect can also use to take a block:
      .collect returns a copy of my_nums, but doesn’t change (or mutate) the original my_numsarray. use .collect! to change the array.

      1
      2
      3
      4
      5
      6
      7
      my_nums = [1,2,3]
      my_nums.collect { |num| num**2 }
      my_nums
      # ==> [1,2,3]
      my_nums.collect! { |num| num**2 }
      my_nums
      # ==> [1,4,9]
    • yield , methods accept blocks using the yieldkeyword. for example:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      def yield_name(name)
      puts "In the method! Let's yield."
      yield("Kim")
      puts "In between the yields!"
      yield(name)
      puts "Block complete! Back in the method."
      end

      yield_name("Eric") { |n| puts "My name is #{n}." }
      输出结果: In the method! Let's yield. My name is Kim. In between the yields! My name is Eric. Block complete! Back in the method.
    • 定义一个double函数,使用yield + block 的方式(不在函数里面定义,而是用block的方式去定义)
      1
      2
      3
      4
      5
      def double(number)
      yield(number)
      end

      double(2){|n| n*2}
  • Proc : “saved” block. Procs are great for keeping your code DRY, which stands for Don’t Repeat Yourself.

    • just call Proc.new and pass in the block you want to save. e.x.
      cube = Proc.new {|x| x**3}
      
    • Usage:
      [1,2,3].collect!(&cube)
      [4,5,6].map!(&cube)
      
      The & is used to convert the cubeproc into a block.
    • why Procs?
      • 是个对象:Procs are full-fledged objects, so they have all the powers and abilities of objects. (Blocks do not.)
      • 反复使用:Unlike blocks, procs can be called over and over without rewriting them.
    • .call可以直接call procs .

      1
      2
      3
      test = Proc.new {puts "hello"}
      test.call
      # ==> hello
    • Symbol, meet proc

      1
      2
      3
      4
      string = ["1","2","3"]
      nums = strings.map(&:to_i)
      # ==> [1,2,3]
      # By mapping &:to_i over every element of strings, we turned each string into an integer
  • Lambda

    • Syntax :
      lambda {|param| block }
      
    • Lambda VS Proc (super similar)
      • a lambda checks the number of arguments passed to it, while a proc does not. This means that a lambda will throw an error if you pass it the wrong number of arguments, whereas a proc will ignore unexpected arguments and assign nil to any that are missing.
      • when a lambda returns, it passes control back to the calling method; when a proc returns, it does so immediately, without going back to the calling method.**
Object-Oriented Programming
  • class : a way of organizing and producing objects with similar attributes and methods.

    • @var : an instance variable, means the var is attached to the instance of the class.
    • Scope : The scope of a variable is the context in which it’s visible to the program.
    • @@var : an class variable, belongs to the class itself.
    • $var : global variable
    • Inheritance Syntax :

      1
      2
      3
      class DerivedClass < BaseClass
      # some stuff
      end
    • Override: 在子对象中定义了与父对象一样的方法时,会自动覆盖掉父对象的方法

    • super, 当需要在子对象调用被覆盖的父对象方法时,用super,例如:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      class Creature
      def fight
      return "Punch to the chops!"
      end
      end

      class Dragon < Creature
      def fight
      puts "Instead of breathing fire..."
      super
      end
      end
    • 只能继承一个父类 :Only One!

    • attr_reader, attr_writer: you can read and update a particular variable. or just use attr_accessor to make a variable readable and writeable in one fell swoop.
      1
      2
      3
      4
      5
      6
      7
      8
      9
      class Person
      attr_reader :name
      attr_accessor :job

      def initialize(name, job)
      @name = name
      @job = job
      end
      end
  • Module: being very much like classes, but modules can’t create instances and can’t have subclasses. They’re just used to store things!

    • Ruby constants are written in ALL_CAPS and are separated with underscores if there’s more than one word.
    • One of the main purposes of modules is to separate methods and constants into named spaces. This is called (conveniently enough) namespacing
    • include mixes a module’s methods in at the instance level (allowing instances of a particular class to use the methods)
    • extend mixes a module’s methods at the class level.

不论class还是module,命名都是以大写字母开头,纯字母构成,没有数字和下横线_