蓝天,小湖,湖水中一方小筑

Ruby learning log

Just studied Ruby with the tutorial on website rubylearning.com in the past week, and here are some knowledge gained those days.

General

  • Ruby is free format and case sensitive.

  • Besides commenting one line code with leading #, Ruby can use =being and =end to define a comment block.

  • Everything in Ruby is object. Which means 1.5 means a float number but 1.times can generate a enumerator.

  • Ruby use nil to indicate a NULL object

  • Only false and nil is false. Be careful, you have to face the fact that if 0 will do not enter else branch in Ruby, which is different with other language I have learned.

  • There is no ++ and -- in Ruby, you can work around with +=1 and -=1 sometimes.

  • Constant name must start with capital letter, and local variable must start with lowercase letter or underscore(_). Program can not be executed if name do not obey this rule (hmm… Python use force indent, while Ruby use force name type).

  • In Ruby, constant, class and module are all treated as constant, so must follow the constant name rule.

  • Parentheses are optional while defining or calling function, so all the code following is legal:

    foobar foobar()

    foobar(a, b, c) foobar a, b, c

    def foo bar puts bar end

    def foo(bar) puts bar end

  • .to_i, .to_f and .to_s are used to convert object to integer, float and string.

  • You can insert underscore(_) in integer number to make it more readable.

Variable and method

  • Global, local, instance and class variable are defined in different way
  • Variable with prefix $ means global variable
  • Variable with prefix @ means instant variable in class, like self.var in Python
  • Variable with prefix @@ means the class variable, like static variable in C++
  • Ruby also include some built in variable:
  • $0 means the filename.
  • $: means search path, which is a list, like the sys.path in Python.
  • $$ means the process id.
  • Usually, a variable can be assigned default value with this syntax: var ||=
  • Only ?, ! and = can be used as suffix to the method
  • method name ends with ? means this method will return boolean value.
  • method name ends with ! means this method will do changes on original object instead of creating new copy.
  • method name ends with = can used to define operator.
  • If no return at last of function, the value of last expression will be returned as return value.
  • Argument of method can be defined as *args, which means the method can accept uncertain number of argument.
  • Seems there is no **args in Ruby, arguments passed with *args will lost information of argument name. The **args used in Python method can accept argument with name.
  • alias can be used to define a alias for a method/operator/global var/regular expression back-ref, but not local var/class var/constant. The object pointed by new name will NOT updated after updating old one.

String

  • Ruby use puts to print string to screen, and gets to receive string from standard input.
  • puts is used like a keyword, but actually it is a method defined in Ruby kernel
  • puts method will invoke to_s method of an object
  • Strings fetched with gets will usually be tidied by chomp method
  • You can use + to connect string. Like Python, it will create a new string object, so the performance may downgrade if connecting too may string with +
  • String defined by single quota and double quota are different. A string defined by single quota only convert \\\\ to \\, which means 'a\\\n' == 'a\n', and all the three character will be printed out with puts. While the double quota will convert all escape string, further more, it will also handle the expression interpolation #{}.
  • There are three methods to compare string, ==, eql? and equal?. The first two methods compare string content while the last one compares object id.
  • A magic keyword %w can be used to build string array, like this: %w{ab cd ef gh \n} == [“ab”, “cd”, “ef”, “gh”, “\\n”].

Flow control and code block

  • if..else..end, and the else if is written as elsif in Ruby. (hmm… we have else if, elseif and elif yet, and now we have elsif, seems we only need elf now).
  • There is reverse if, named unless, help to write complex logic?
  • There is cond ? a : b operator in Ruby.
  • There is a switch-case model in Ruby, case..when..else..end
  • Code blocks are defined in { } (single line) or do..end (multiple line). The { } has higher precedence than do..end.
  • Code block followed by function will be executed after yield called in the function.
  • Can pass argument to block by passing argument to yield.
  • Method block_given? can be used in function to check whether this function has block followed.

Array, range and hash

  • Seems there is no index error in Ruby, you will get nil if try to access element out of array size.
  • ARGV means command line arguments, which is an array.
  • Range can be generated via a..b or a...b, the list generated with three dots do not contain b.
  • .to_a method can convert a range object to array.
  • There is a === operator in range object, check whether the element is included in range.
  • Name start with : is a symbol, which is unique in global.
  • There is a symbol table in Ruby, which contains function, class variable (variable start with @) and user defined symbol. Symbol.all_symbols can be used to get all symbol name, w/o colon.
  • Symbol can not be used as a left value. It is just a symbol, can be used as right value.
  • For string comparison and hash index, a temp string will create a new object each time, which may reduce the performance.
  • There is a to_s method for symbol, and a to_sym method for string.
  • Save information in string if take more concern on content, and symbol for object id.
  • Hash (dict in python) can use any object as key, which is different with Python.
  • It is recommended to use symbol to replace the string index
  • Hash can be defined via {key: val} or {key => val}. If using the first method, the key can not be a string, but a name obey the variable rule, and Ruby will convert it to symbol. That is: {a: 2} == {:a => 2}

File

  • Usual way for using File: File.open() do |f| .. end
  • Can define file encoding and internal encoding in the open command, which is better than built-in open of Python
  • Find.find() will traverse the directory, include sub directory.
  • File.new() can open a random access file, which can response to .seek method.

Regular expression

  • Pattern enclosed by slash is an regular expression object, /foobar/
  • Both string and regular expression has match method. RE use match while string use =~.
  • .match in RE will return MatchData object of matched, or nil for not found.
  • =~ in string will return index if found, or nil for not found.

Class

  • class is a first-class object in Ruby, which is an object of Class.
  • As mentioned before, the class name must has first character uppercased.
  • Create a new object with ClassName.new, which will invoke allocate method to allocate space and initalize method for initialization.
  • Variable with prefix @ is class variable, which can be used in the whole object, seems like the self. variable in Python, but in Ruby, name with self. must function, then, the first character must be uppercased.
  • methods method can be used to printed out all methods in class, like the dir in Python.
  • responsed_to? method can be used to check whether the method exists in the object. If not, Ruby first will check whether there is method_mission method first, and then throw exception of not found.
  • Every class in Ruby is open, which means you can update any class, include built-in class like string, at anytime. But make sure you will not bring the conflict into exist class.
  • A more safer way is define a sub-class, and override the needed method.
  • In Ruby, one class can only be inherit from a single class. However, module can be used as multi inherit, seems like the interface in Java.
  • If calling super in one class, the method in parent class will be executed, but different syntax can cause different result:
  • Calling super with no parentheses, then the argument in sub method will be passed to parent method.
  • Calling super with empty parentheses, then the default value of parent method will be used, and error will be reported if no default value defined.
  • Calling super with value, then pass this value to parent method.
  • Abstract class, seems more like syntax sugar. Calling undefined method in parent class, and implement the method in subclass.
  • The default access rule for method in class is public, can add protect/private before def if needed.
  • Those access type can be only applied to method, the instance/class variable is private by default.

Proc

  • Like lambda in Python, but named Proc in Ruby.
  • Each code block created by lambda is a object of Proc class, which can be executed by calling .call method.
  • Here is a example for lambda with argument: lambda {|x| "Hello #{x}"}.call “Hell”`

Load and require

  • load and require are methods defined in Object, but more like a keyword during usage.
  • File included by load will be loaded every time program executed, while require only once.
  • Pass filename w/o suffix to require, and require will find the file in the path. If the suffix is rb, then imported as source file. For library suffix, like .so, .dll, require will import them as Ruby extension.
  • require will return true or false after execution complete.

Exception

  • A special class, user can throw it via raise.
  • Default exception type is RuntimeError, but can be changed by passing class name to raise
  • Use rescue to handle the exception.