欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
快速讀懂Ruby代碼問(wèn)答
本問(wèn)答的目標讀者是不了解Ruby語(yǔ)言、但有別的編程語(yǔ)言經(jīng)驗的人。 
  
Ruby語(yǔ)言的代碼可讀性是很強的。本問(wèn)答只把一些語(yǔ)法特點(diǎn)、以及別的語(yǔ)言中可能沒(méi)有或不同的東西展現出來(lái),目的在于讓有別的編程語(yǔ)言經(jīng)驗的人能快速讀懂Ruby代碼。 
  
注意本問(wèn)答講的是Ruby語(yǔ)言本身(基于版本1.9),而不是Ruby on Rails,后者是Ruby的一種DSL,語(yǔ)言面貌上和Ruby有一定差異。 
  
Q:Ruby最有特點(diǎn)的語(yǔ)法形式是什么? 
  
或許是方法后接代碼塊的大量使用,以下面這行代碼為例: 
  
   
file.each_line { |line| print line } 
  
表示在file對象上調用each_line方法,該方法的功能是依次得到每一行,傳遞給后面的代碼塊,代碼塊把傳來(lái)的行賦值給line變量,然后在代碼塊里對line進(jìn)行處理,處理完畢則從代碼塊返回each_line方法,再由它得到下一行,再一次傳遞給代碼塊?!馿ach_line這樣的方法,Ruby中稱(chēng)之為迭代器方法(iterator)。 
  
又比如這個(gè)例子: 
  
   
open('test.txt') { |f| line_array = f.readlines } 
  
用open方法打開(kāi)test.txt文件,生成了一個(gè)File類(lèi)的實(shí)例對象,并把這個(gè)對象傳遞給后面的代碼塊,賦值給變量f,然后代碼塊里對f進(jìn)行操作,操作完畢后返回open方法,open方法再把f關(guān)閉,所以這一行代碼相當于如下三行: 
  
   
f = open('test.txt') 
   
line_array = f.readlines 
   
f.close 
  
Ruby風(fēng)格寫(xiě)法的好處:一行完成,邏輯緊湊;自動(dòng)關(guān)閉文件,防止忘了f.close; 
當前scope少創(chuàng )建一個(gè)變量名f,代碼塊關(guān)閉后,f就消失了 
  
一個(gè)Ruby風(fēng)格的完整命令就是由對象、方法(包含參數)、代碼塊(包含參數)構成的。有的方法可以不接代碼塊。 
  
Q:我看到有些代碼和上面提到的寫(xiě)法不太像,是怎么回事? 
  
有些DSL看起來(lái)和Ruby語(yǔ)言本身不大像,但其實(shí)語(yǔ)法格局是一樣的,只是通過(guò)一些設定偽裝成別的風(fēng)格。 
  
大致有四點(diǎn)導致這種情況: 
  
1、隱性地調用方法,讓方法看起來(lái)像函數或關(guān)鍵詞; 
  
   Ruby中沒(méi)有函數,全都是方法。方法就得在某個(gè)對象上調用,但是這個(gè)對象可以隱藏 
   方法不在某個(gè)對象上顯式調用,那它就一定是在self所指的對象上調用 
   如
open(file)實(shí)際是self.open(file),不過(guò)open是私有方法,不能顯式寫(xiě)出對象 
  
2、省略了括起參數的括號; 
  
   如
open('test.txt','w')可以寫(xiě)成open 'test.txt', 'w' 
  
3、代碼塊的{...}改成do...end; 
  
   
open 'test.txt' do |line| 
   
end 
  
   就相當于
open('test.txt') {|line|     } 
  
   這是很常見(jiàn)的,{...}和do...end只在優(yōu)先級上有一些不同,一般都可互換 
   通常的風(fēng)格是:代碼塊里的代碼若只有一行,則用{},若有多行,則用do...end 
   這只是風(fēng)格管理,實(shí)際上即使是多行代碼,你也可以用{}括起來(lái) 
  
4、省略作為方法參數的哈希(散列)字面量的花括號。 
  
   很多方法喜歡拿一個(gè)哈希做參數,如果哈希是方法調用的最后一個(gè)參數,則花括號可省略 
   
task :name => :test 相當于 task({:name => :test}) 
  
如下一段代碼: 
  
HTMLForm.generate(STDOUT) do 
  comment "This is a simple HTML form" 
  form :name => "registration", 
       :action => "http://www.example.com/register.cgi" do 
    content "Name:" 
    input :name => "name" 
    content "Address:" 
    textarea :name => "address", :rows=>6, :cols=>40 do 
      "Please enter your mailing address here" 
    end 
  end 
end 
  
如果寫(xiě)“全”來(lái),就相當于這樣: 
  
HTMLForm.generate(STDOUT) { 
   
self.comment("This is a simple HTML form") 
   
self.form({:name => "registration", 
              
:action => "http://www.example.com/register.cgi"}) 
     
self.content("Name:") 
     
self.input({:name => "name"}) 
     
self.content("Address:") 
     
self.textarea({:name => "address", :rows=>6, :cols=>40}) 
       
"Please enter your mailing address here" 
     

  
 } 
} 
  
Q:我聽(tīng)說(shuō)Ruby分1.8和1.9兩個(gè)版本,二者的語(yǔ)法有什么不同? 
  
目前Ruby流行1.8.x和1.9.x兩個(gè)主要版本。1.9.x版使用新的解釋器YARV,比1.8.x速度快;重寫(xiě)了String類(lèi),增加了Encoding類(lèi),從此可以完善處理多字節字符;殺手應用RoR也一早支持了1.9.x版;還有一些語(yǔ)法上的改進(jìn)。 
  
本問(wèn)答以1.9版語(yǔ)法為準,兩個(gè)版本有一些語(yǔ)法差別,略提幾條區別的線(xiàn)索: 
  
§ 如果有require 'rubygems'的,為1.8版; 
  
§ 如果看見(jiàn)$KCODE的,為1.8版; 
  
§ 哈希的鍵值對之間可以用逗號(而非=>)分隔的,為1.8版; 
  
§ if condition:這種和Python一樣的寫(xiě)法(條件之后用冒號),為1.8版 
  
§ {|a,b;x,y| }的寫(xiě)法(用分號隔開(kāi)兩類(lèi)參數),一定是1.9版 
  
Q:有些寫(xiě)法感覺(jué)很奇怪,比如5.times { puts "Ruby! " },怎么理解? 
  
這種寫(xiě)法其實(shí)很酷。Ruby中一切值都是對象,包括整數。Integer類(lèi)有實(shí)例方法times,依次傳遞0到n-1給后面的代碼塊,相當于運行n次后接的代碼塊。 
  
這一代碼就是在5上調用方法times 
  
Q:Ruby代碼中很少看見(jiàn)for...in/foreach的寫(xiě)法,為什么? 
  
相比f(wàn)or i in xx的循環(huán)方式,Ruby的風(fēng)格是更喜歡用xx.each {|i|  }這種調用迭代器方法的方式。 
  
對于數組for elem in array,迭代器方法寫(xiě)作array.each { |elem|   } 
  
對于讀文件的每行for line in file,迭代器方法寫(xiě)作file.each { |line|    } 
  
相比f(wàn)or...in方式,迭代器方法更快,更靈活,更強大,比如對于一個(gè)file對象 
  
   
file.each_line { |line|    } # 每次處理一行 
   
file.each(' ') { |para|    } # 每次處理一段 
   
file.each_char { |char|    } # 每次處理一個(gè)字符 
   
file.each_byte { |byte|    } # 每次處理一個(gè)字節 
   
file.each_line.with_index(1) { |line, lineno|    } 
    
# 傳遞行時(shí),還把索引值(在這里就是行號)也傳遞給代碼塊 
  
這些都不是for...in擅長(cháng)的 
  
至于for(i=0; i<10; i++)這種寫(xiě)法,Ruby當然是寫(xiě)成
9.times {|i| }這種形式了 
  
Q:Benchmark::measure、Benchmark.measure兩種寫(xiě)法有什么區別? 
  
表示方法調用,用::還是用.,完全是一樣的,指向的是同一個(gè)方法,區別只在于作者怎么看待measure這個(gè)方法。 
  
符號::一般是用來(lái)分隔嵌套的模塊、類(lèi)、常量的,寫(xiě)成Benchmark::measure,像是表明measure是在Benchmark這個(gè)模塊中定義的函數,Benchmark只是它的容器;而寫(xiě)成Benchmark.measure,像是在說(shuō)measure是對Benchmark這個(gè)對象進(jìn)行操作。 
  
從內部實(shí)現上說(shuō),Ruby中只有方法,沒(méi)有函數;但從內涵上說(shuō),Benchmark::measure的意義更確切,所以有人愿意這樣寫(xiě)。 
  
Q:Array#each是什么意思? 
  
Array#each的寫(xiě)法并不用在實(shí)際代碼中,而是文檔中約定俗成的一種寫(xiě)法,表示Array類(lèi)中定義的實(shí)例方法: 
  
   
array = Array.new 
   
array.each {} # Array#each指的就是這里的each,是Array類(lèi)的實(shí)例所用 
  
Q:::Foobar是什么意思? 
  
其中的::是分隔嵌套模塊、類(lèi)、一般常量的分隔符,::前面沒(méi)有東西,表示到global scope去找這個(gè)常量。 
  
Q:經(jīng)常聽(tīng)到Ruby“一切皆對象”的說(shuō)法,怎么理解? 
  
嚴格來(lái)說(shuō),應該是Ruby中一切可獨立的合法語(yǔ)言片段都是表達式,表達式都要返回一個(gè)值,而一切值在Ruby中都是對象。 
  
比如true false nil也是對象,分別是TrueClass、FalseClass、NilClass的實(shí)例 
  
比如if結構可獨立,所以是表達式,所以要返回值,這個(gè)值總是一個(gè)對象,所以if結構可以賦值給一個(gè)變量: 
  
a = if x > y 
      x + 4 
    else 
      y * 2 
    end 
  
比如模塊、類(lèi)也是對象,String、Array等類(lèi)是Class類(lèi)的實(shí)例對象,Class作為對象也是Class這個(gè)類(lèi)的實(shí)例 
  
  
Q:$foo、@bar和@@baz里的$、@、@@是什么意思? 
  
Ruby沒(méi)有g(shù)lobal、local之類(lèi)關(guān)鍵詞設定變量可見(jiàn)范圍,而是采用變量自帶標記的方式 
  
§ 以小寫(xiě)字母或_開(kāi)頭的變量是局部變量 
  
§ 以$開(kāi)頭的是全局變量 
  
§ 以@開(kāi)頭的是每個(gè)對象自身的實(shí)例變量 
  
§ 以@@開(kāi)頭的是同類(lèi)對象都可訪(fǎng)問(wèn)的類(lèi)變量 
  
Q:大寫(xiě)字母開(kāi)頭的名稱(chēng)代表什么? 
  
大寫(xiě)字母開(kāi)頭的是常量,包括模塊名、類(lèi)名都以大寫(xiě)字母開(kāi)頭,如Array、Enumerable都是常量。常量的意思是這個(gè)名稱(chēng)和某個(gè)對象的聯(lián)系是固定了的,但不表示那個(gè)對象不可更改,如: 
  
  Foobar = [ 1, 2, 3 ] 
  Foobar[2] = 99 
  print Foobar # [1, 2, 99] 
  
要想常量所指的對象不可修改,那應該 
Foobar = [ 1, 2, 3 ].freeze 
  
Q:STDIN、STDOUT、STDERR和$stdin、$stdout、$stderr有什么區別? 
  
STDIN這一類(lèi)以大寫(xiě)字母開(kāi)頭,是常量;$stdin這一類(lèi)以$開(kāi)頭,是全局變量。 
  
常量不可變,STDOUT總指向屏幕顯示(除非運行ruby時(shí)在命令行設置>out 2>err之類(lèi)),變量可變,所以$stdin可以替換成別的IO/File對象。 
  
全局的輸出方法,如print puts等,總是向$stdout輸出,而非向STDOUT輸出,如: 
  
  print 1 # 這時(shí)$stdout和STDOUT是一致的,輸出到屏幕 
  $stdout = open('output_file','w') 
  print 2 # 這時(shí)輸出到output_file了 
  $stdout = STDOUT 
  print 3 # 又輸出到屏幕了 
  
Q:ARGV = ["a","b","c"]的寫(xiě)法為什么會(huì )報錯? 
  
Perl里寫(xiě)@ARGV = qw(a b c)和Python里寫(xiě)sys.argv = ["a","b","c"]都是OK的 
  
Ruby這么寫(xiě)報錯的原因其實(shí)也很簡(jiǎn)單,因為ARGV以大寫(xiě)字母開(kāi)頭,所以它是個(gè)常量,ruby解析器一啟動(dòng),ARGV常量就設置好了,再用等號賦值的方式,表示你想改變這個(gè)常量跟某個(gè)對象之間的聯(lián)系,對常量來(lái)說(shuō)這是不行的 
  
所以在Ruby里得寫(xiě)成
ARGV.replace ["a","b","c"],replace是Array類(lèi)的一個(gè)實(shí)例方法,表示不改變對象,只替換內容 
  
Q:表示"什么都沒(méi)有",用什么?null undef nil? 
  
用nil。Perl里用undef表示什么也沒(méi)有,但在Ruby里,undef是取消方法定義的關(guān)鍵詞。 
  
Q:在條件判斷中,哪些算是真值,哪些算是假值? 
  
在Ruby里false、nil表示假,其他所有對象都為真,包括0、""、[]等 
  
Q:有些方法名稱(chēng)里有?和!,是什么意思?比如nil?和strip! 
  
方法名的最后可以有一個(gè)?或!,這只是一種命名習慣,讓方法的涵義看起來(lái)更好懂 
  
加?的方法,通常都是返回true/false的 
像nil?的功能是檢測它的對象是否是nil,
obj.nil?感覺(jué)就是在問(wèn)obj是nil嗎? 
又如
File.exist?("test.txt")感覺(jué)就是在問(wèn)"test.txt"存在嗎? 
  
加!的方法,總有一個(gè)對應的不加!的方法,通常不加!的生成新對象,而加!的是對本對象進(jìn)行修改,如String類(lèi)的strip和strip!: 
  
str = "  abc  " 
new_str = str.strip # 不改動(dòng)原str對象,而是新生成一個(gè)字符串,刪去了前后空白符 
str.strip! # 直接在原str對象上改動(dòng),刪去str的前后空白符 
  
和!的使用并沒(méi)有強制性的規定,你要定義一個(gè)返回true/false的方法,不加?也可以,或者某個(gè)以?結尾的方法,不返回true/false也可,!也是??傊?和!就是一般字符,不具有限定功能,只是增強可讀性的 
  
Q:我看到有def []=(name, value)這樣的寫(xiě)法,什么意思?難道定義了"[]="這個(gè)方法? 
  
Bingo!
[]=確實(shí)是一個(gè)方法。 
Ruby語(yǔ)言中很多(但不是全部)操作符實(shí)際上都是方法,比如像+ - * / % << == ** 等都是。既然是方法,就可以在自己的類(lèi)里定義。 
  
str[2..4] = "xyz"其實(shí)相當于str.[]=(2..4,"xyz"),也就是在str對象上調用[]=方法,傳遞兩個(gè)參數2..4和"xyz" 
  
Q:我看到[1,2,3,4].from(2)的寫(xiě)法,但是在官方API里沒(méi)有看到from這個(gè)方法??? 
  
說(shuō)明from這個(gè)方法是第三方模塊加到Array類(lèi)里去的。 
  
Ruby的類(lèi)是開(kāi)放的,即使是核心的類(lèi),你也可以隨意添加方法、undef方法、增加別名等等 
比如對于核心的String類(lèi): 
  
class String 
  def to_file 
    File.open(self) 
  end 
end 
  
然后我就可以
"filename.txt".to_file得到一個(gè)file對象了 
  
Q:String#length方法和String#size方法有沒(méi)有區別? 
  
沒(méi)有區別,這兩個(gè)方法完全一樣,是同義詞。 
  
Ruby的標準API里有不少方法的用法是完全相同的,作者的考慮可能是讓不同來(lái)源的程序員都有親近感,或者在不同的上下文使用,更接近自然語(yǔ)言;我是覺(jué)得這種冗余不太必要,但對常見(jiàn)的同義詞方法,還是應知道一點(diǎn)。 
  
如String類(lèi)的length和size同義,each_line和lines同義,each_char和chars同義,each_byte和bytes同義;File類(lèi)的each和each_line以及l(fā)ines同義;Hash類(lèi)的each和each_pair同義 
  
Q:File#gets方法和File#readline方法有沒(méi)有區別? 
  
有區別,這兩個(gè)方法都是讀取文件下一行,但到文件末尾eof時(shí),再gets會(huì )返回nil,而再readline會(huì )觸發(fā)EOFError異常。 
  
Ruby標準API里也有一些這種大體相同,但有細微差別的方法。 
  
哪些方法是同義詞,完全一樣,哪些是近義,類(lèi)似但有區別,確實(shí)給學(xué)習造成了一定的困難,只能是多查。 
  
Q::encoding :xyz是什么意思? 
  
這是Symbol類(lèi)實(shí)例的字面量表示法,用個(gè)冒號放在字符之前,初學(xué)Ruby者可能容易把這個(gè)誤認為是變量名。也可以寫(xiě)作
:"encoding"這樣,看起來(lái)就像個(gè)特殊的字符串,而不是變量名了,但通常是省略引號的。 
  
Q:Symbol類(lèi)實(shí)例有什么用途? 
  
Ruby中的字符串是可變的,Symbol對象是不可變的,可以把Symbol對象理解為一種名稱(chēng),一種標簽。因為Symbol對象不可變,它用在哈希里當鍵比用字符串更有效率: 
  
person = { :name => 'Joey', :age => 21, :rank => 5 }    # 就比 
person = { 'name' => 'Joey', 'age' => 21, 'rank' => 5 } # 更加ruby 

另外,在一些方法中,經(jīng)常用symbol做參數,指代方法等的名稱(chēng),如: 
  
   
str = "abc|def|ghi" 
   
array = str.send(:split, "|") # 向str發(fā)送消息,相當于str.split("|") 
  
Q:哈希字面量的寫(xiě)法是怎樣的? 
  
用花括號,鍵和值用=>分隔開(kāi),如: 
  
hash = { :key1 => "val1", :key2 => "val2", :key3 => "val3" } 
  
Perl眾注意,這個(gè)=>是從Perl來(lái)的,但Perl里=>跟逗號完全一樣,但在Ruby里,=>跟逗號是不同的 
  
Q:哈希的鍵是有序的? 
  
1.9版本的哈希,鍵確實(shí)是有序的,你{:a => 1, :b => 2, :c => 3}用each迭代時(shí),總是首先出:a,其次出:b,然后出:c 
  
但沒(méi)看到官方保證后續版本一定也是這樣,所以這就像雜牌充電器,你照樣用來(lái)充電也沒(méi)問(wèn)題,但官方不給保修 
  
Q:不帶花括號的寫(xiě)法,比如:encoding => 'gbk'是什么意思? 
  
還是一個(gè)hash,只是省略了花括號,這種寫(xiě)法常用在充當方法調用的最后一個(gè)參數時(shí): 
  
file = File.open('test.txt', :encoding = > 'gbk')   # 相當于 
file = File.open('test.txt', {:encoding = > 'gbk'}# 第二個(gè)參數是個(gè)哈希 
  
open方法內部接了這個(gè)哈希,opt = {:encoding = > 'gbk'},就可通過(guò)opt[:encoding]獲得文件編碼值,進(jìn)行下一步處理 
  
一些DSL很喜歡用這種方式來(lái)傳遞參數,比如: 
  
class HTMLForm < XMLGrammar 
  element :form, :action => REQ, 
                 :method => "GET", 
                 :enctype => "application/x-www-form-urlencoded", 
                 :name => OPT 
  element :input, :type => "text", :name => OPT, :value => OPT, 
                  :maxlength => OPT, :size => OPT, :src => OPT, 
                  :checked => BOOL, :disabled => BOOL, :readonly => BOOL 
  element :textarea, :rows => REQ, :cols => REQ, :name => OPT, 
                     :disabled => BOOL, :readonly => BOOL 
  element :button, :name => OPT, :value => OPT, 
                   :type => "submit", :disabled => OPT 
end 
  
看起來(lái)一個(gè)element帶了好多參數,實(shí)際上呢,給它的只是兩個(gè)參數 
  
  element :button, :name => OPT, :value => OPT, 
                   :type => "submit", :disabled => OPT 
  
相當于: 
  
element(:button,{:name=>OPT, :value=>OPT, :type=>"submit", :disabled=>OPT}) 
  
參數就是一個(gè):button(symbol),一個(gè)hash 
  
Q:{a:1,b:2,c:3}也是哈希字面量么?是不是和Python的涵義一樣? 
  
不一樣。Python要這樣寫(xiě),a、b、c是三個(gè)變量,而在Ruby中(只限1.9版),這其實(shí)是 
{ :a => 1, :b => 2, :c => 3 }的另一種寫(xiě)法,a、b、c是三個(gè)symbol 
  
為什么要引進(jìn)這種寫(xiě)法呢?也是為了哈希做方法參數時(shí)好看 
  
File.open('test.txt', :encoding = > 'gbk')  # 就可以寫(xiě)成 
File.open('test.txt', encoding: 'gbk') 
  
上面的例子,寫(xiě)成這樣也可以: 
  
element :button, name: OPT, value: OPT, type: "submit", disabled: OPT 
  
Q:1..5、"a"..."z"是什么意思? 
  
是一個(gè)range對象的字面量表示法。1..5表示從1到5的范圍,包含5(2個(gè)點(diǎn)包含尾端); 
"a"..."z"表示從"a"到"z"的范圍,不含"z"(3個(gè)點(diǎn)不含尾端) 
  
這種寫(xiě)法是從Perl繼承的,但是在Perl里1..5是一個(gè)列表,要寫(xiě)成1..100000000得內存爆炸了,但在Ruby里,一個(gè)range對象只記錄首端的1和尾端的100000000,這么寫(xiě)沒(méi)問(wèn)題 
  
range對象可以迭代操作:
(1..6).each {|i| print i} 
又如
str[1..5]就是以一個(gè)range對象1..5做參數,表示第2個(gè)到第6個(gè)字符 
  
Q:=>還有什么用途? 
  
除了在hash里分隔鍵和值外,還用在異常處理語(yǔ)法里: 
  
begin # 異常處理語(yǔ)法 
   
# blah blah 
rescue ArgumentError => e # 若上面代碼觸發(fā)ArgumentError,則賦值給e 
   
# blah blah 
end 
  
還可以寫(xiě)成:
rescue => e # 任何出現的異常都賦值給e 
  
Q:這一句什么意思?m = a / b rescue 0 
  
這是一種快捷的異常處理語(yǔ)法,A rescue B,若表達式A觸發(fā)異常,則對B表達式求值并返回 
  
m = a / b rescue 0 # 假如b是0,出現除0錯誤,那么右邊的0作為返回值 
  
$stdout = open(output_file,'w') rescue STDOUT  
# 若output_file沒(méi)有寫(xiě)權限,出錯,則返回STDOUT給$stdout 
  
Q:puts、p、print有什么區別?似乎Ruby眾不喜歡用print? 
  
puts打印一個(gè)字符串,如果字符串末尾沒(méi)有"\n"則添加換行,如果有則不添加 
  
puts "abc" # 實(shí)際打印的是"abc\n" 
puts "abc\n" # 實(shí)際打印的還是"abc\n",而非"abc\n\n" 
  
Ruby中用puts的情況應該比print多吧 
  
p 則是打印供程序員調試的字符串,會(huì )把不在A(yíng)SCII范圍的字符轉義 
  
print "上下" # 打印出來(lái):上下 
p "上下" # 打印出來(lái):"\u4E0A\u4E0B" 引號也是打印出來(lái)的內容 
  
實(shí)際上 p obj相當于
print obj.inspect,而obj.inspect相當于Python里的repr(obj) 
  
Q:字符串里的#{}是什么意思?比如"a + b = #{ a + b }" 
  
雙引號內的表達式內插,如 
  
   
a = b = 3 
   
puts "a + b = #{ a + b }" # "a + b = 6" 
  
Q:"%s = %f" % ["pi", Math::PI]是什么意思? 
  
String類(lèi)的%方法,調用在一個(gè)格式字符串之上,相當于printf出來(lái)新的字符串 
  
Q:string << "a"、string << 65,array << "a",file << "a"中的<<各代表什么意思? 
  
str << "a"表示將字符"a"加到str字符串尾端 
str << 65表示將碼點(diǎn)65所代表的字符(這里也是"a")加到str字符串尾端 
  
Ruby中的字符串是可變的,用
str << "a"的方式,是在str這個(gè)對象上直接修改,比str = str + "a"快,邏輯也清晰 
  
array << "a"表示將"a"追加到array末尾,作為最后一個(gè)元素 
file << ""表示打印到file對象,相當于file.print "a" 
  
對于整數來(lái)說(shuō),<<則是位移方法。對象不同,<<的涵義也不同,很好的duck typing例證 
  
Q:<<EOF是什么意思? 
  
這叫做Here Document,Perl眾懂的。 
<<后面緊跟一個(gè)標記,從下一行開(kāi)始到出現標記的行為止,其中字符串都存入這個(gè)Here Document,例如: 
  
str1 = <<HD1.upcase + <<HD2.downcase 
aaaaaaa 
bbbbbbb 
HD1 
XXXXXXX 
YYYYYYY 
HD2 
  
p str1 # "AAAAAAA\nBBBBBBB\nxxxxxxx\nyyyyyyy\n" 
  
這種代碼相當于下面: 
  
str2 = "aaaaaaa 
bbbbbbb 
".upcase + "XXXXXXX 
YYYYYYY 
".downcase 
  
又如: 
  
eval(<<cmds) 
  a = b = 3 
  print a + b 
cmds # 上面黃色的字不是代碼,而是字符串  
  
Q:`ls`是什么意思? 
  
在操作系統中運行``里的命令,如在Windows下運行dir命令,返回dir出現的信息 
  
`dir`.each_line.select { |line| line.start_with? '2011/09/08' } 
  
# dir返回的信息,挑選每一行以"2011/09/08"開(kāi)頭的 
  
Q:/[Rr]uby/是什么意思? 
  
正則表達式的字面量表示法,和Perl的正則表達式簡(jiǎn)寫(xiě)形式一樣。 
  
Q:%w %q %Q %r是什么意思? 
  
從Perl繼承并加以變化的語(yǔ)法糖。 
  
%w后接分界符(可以是%w{} %w() %w[] %w//等等),里面的字符串以空白符分開(kāi),這些字符串各自作為數組的元素 
  
%w( abc 123 def 456) # 相當于 [ 'abc', '123', 'def', '456'] 
  
%q相當于單引號,只是中間出現\'不轉義,主要用在字符串內有很多'和"時(shí) 
  
%q{abc'def'} # 相當于 'abc\'def\'' 
  
%Q相當于雙引號,主要也是用在字符串里有很多'和",只是里面可以?xún)炔灞磉_式 
  
bar = "foo" 
%Q/foo"#{bar}"/ # => "foo\"foo\"" 
  
單獨的%//也代表雙引號,是%Q//的簡(jiǎn)寫(xiě) 
  
%r相當于//,用于創(chuàng )建正則表達式 
  
  
Q:$` $& $' $1 $2是什么意思? 
  
當一個(gè)字符串和正則表達式匹配時(shí),字符串中匹配正則表達式的那部分存入$&,之前的部分存入$`,之后的部分存入$' 
  
如果正則表達式里有捕獲括號,則第一個(gè)捕獲的子串存入$1,第二個(gè)存入$2,依次類(lèi)推 
  
這種標點(diǎn)符號式的變量是直接從Perl中繼承過(guò)來(lái)的,確實(shí)很丑陋,很影響代碼可讀性,現在Ruby對這些符號變量的使用是depreciated的 
  
要想涵義清楚點(diǎn),要么可以導入English.rb模塊 
  
require 'English' 
$MATCH      # 相當于 $& 
$PREMATCH   # 相當于 $` 
$POSTMATCH  # 相當于 $' 
  
或者動(dòng)用Regexp.last_match 
  
Regexp.last_match.to_s        # 相當于 $& 
Regexp.last_match.pre_match   # 相當于 $` 
Regexp.last_match.post_match  # 相當于 $' 
  
類(lèi)似的變量還有一些如$/ $* $.等,具體涵義可查相應的文檔,自己寫(xiě)最好是不要用了 
  
Q:=~是什么意思? 
  
從Perl繼承的,拿一個(gè)字符串和一個(gè)正則表達式進(jìn)行匹配,返回第一次匹配的位置 
和Perl不同的是,在Ruby中string =~ regexp和regexp =~ string兩種寫(xiě)法都可以 
  
Q:<=>是什么意思? 
  
a <=> b返回-1 / 0 / 1或nil,左小右大則返回-1,左大右小則返回1,左右相等則返回0 
比較沒(méi)意義(不是同類(lèi)對象比較)則返回nil,如
123 <=> "abc" 
  
Q:===是什么意思? 
  
很多類(lèi)定義了自己的===方法,涵義各不相同,例如: 
  
§ Range類(lèi)的===是測試參數是某個(gè)range的成員,如(1..10) === 5返回真 
  
§ String類(lèi)的===和==意義相同,都是測試兩個(gè)字符串的值是否相等 
  
§ Regexp類(lèi)的===和=~意義相同,測試是否匹配 
  
§ Class類(lèi)的===是測試參數是否是類(lèi)的成員 
  
String、Array、Integer這些類(lèi)本身也是對象,是Class類(lèi)的實(shí)例,所以下面都返回真 
  
   
String === "abc" 
   
Array === [1,2,3] 
   
Integer === 123 
  
有的語(yǔ)言成分依賴(lài)===,但沒(méi)有顯式地使用===,最主要的是case...when結構(見(jiàn)下一問(wèn)) 
  
另外Arra#grep方法也依賴(lài)=== 
  
a = [1, "abc", :sss, 4.6, "def", :bar ] 
p a.grep(String) # ["abc", "def"] 
  
Array#grep方法,是對數組的每個(gè)元素elem,用方法參數arg === elem為真的則保留 
這里就表示挑出String === elem為真的elem,也就是類(lèi)為String的對象 
  
Q:case...when結構的用法是什么? 
  
最常見(jiàn)的case...when結構的用法如下: 
  
generation = case birthyear 
             when 1946..1963 then "Baby Boomer" 
             when 1964..1976 then "Generation X" 
             when 1978..2000 then "Generation Y" 
             else nil 
             end 
  
case后面的表達式只求值一次,得到的值依次去被when后的對象用===比較,哪一次為真,則返回相應的值,此例中就是以1946..196、1964..1976、1978..2000三個(gè)range對象去===birthyear 
  
Q:賦值操作、方法定義和方法調用里的*是什么意思? 
  
§ 賦值操作比如: 
  
x, *y = 1, 2, 3 # x == 1; y == [2,3]  
*x, y = 1, 2, 3 # x == [1,2]; y == 3 
x, *y, z = 1, 2 # x == 1; y == []; z == 2 
  
*這標記的作用好像是在說(shuō)“你們先拿,剩下全歸我” 
在平行賦值中,左邊只可以有一個(gè)*,但是位置可以任意(1.8版本只能在最后) 
別的變量得到各自的值以后,剩下的全歸*,變成一個(gè)數組(數組有可能為空) 
  
在方法定義中的情況一樣,對于多參數而言,也是“你們先拿,剩下全歸我” 
  
def foo(a,b,*x) 
  
# 表示調用foo時(shí),至少要兩個(gè)參數,賦值給a和b,剩下全給x,x是一個(gè)數組 
  
def bar(*args) # 表示可以有任意數量的參數 
  
方法調用中*的作用和定義相反,是放在一個(gè)數組之前,把其元素拆成參數 
  
args = [1,2,3] 
bar(args) # 傳遞給bar的是一個(gè)參數,數組[1,2,3] 
bar(*args) # 傳遞給bar的是3個(gè)參數,1,2,3 
  
Q:代碼塊是對象嗎? 
  
不是。代碼塊不能獨立存在,單獨寫(xiě){|n| n * 2 },是會(huì )報錯的。 
但是代碼塊可以對象化,對象化后的代碼塊是Proc類(lèi)的實(shí)例。 
  
將代碼塊對象化的寫(xiě)法主要有兩種: 
  
   
proc1 = Proc.new {|n| n * 2 } 
   
proc2 = lambda {|n| n *2 } 
  
兩種寫(xiě)法生成的proc對象有細微差別,break和return等的行為有異。 
  
Q:為什么這樣寫(xiě)不行:foo = lambda {|n| n * 2 }; foo(5) 
  
Python類(lèi)似的寫(xiě)法foo = lambda n: n * 2可行,但在Ruby中,foo得到的是一個(gè)對象,而非函數,不能在對象上加參數,當成方法用。 
  
所以得寫(xiě)成foo.call(5),表示在foo對象上調用call方法,傳遞參數5 
  
  
Q:代碼塊{ |a; x|   }里設置參數的部分,分號后面的變量是什么意思? 
  
(1.8版本不可用)分號前面的a,用來(lái)接受方法傳遞過(guò)來(lái)的參數,自然是block-local的 
分號后面的x,則是設置別的block-local變量,在代碼塊中修改x,不會(huì )影響代碼塊外可能存在的x,如: 
  
  x = a = 9 
  3.times do |a; x| 
    x = a * 2 
    print [ a, x ] # 依次打印[0, 0][1, 2][2, 4] 
  end 
  print [ a, x ] # 仍然是[9, 9] 
  
  x = a = 9 
  3.times do |a| 
    x = a * 2 
    print [ a, x ] 
  end 
  print [ a, x ] # 變成[9, 4]了 
  
Q:->是什么意思?比如 ->(x,y=10) { print x*y } 
  
是1.9版本新加的lambda語(yǔ)法,把原本在代碼塊中的參數移到前面去了 
  
->(x,y) { print x * y } # 相當于 lambda { |x,y| print x * y } 
  
有一個(gè)好處是參數可以設置默認值,
->(x,y=10) {} 
  
有爭議的地方是和別的語(yǔ)言中的->的涵義完全不同 
  
Q:不接代碼塊的each方法是什么意思?比如e = [ 1, 2, 3, 4, 5 ].each 
  
很多方法會(huì )根據是否后接block而運行不同的功能,返回不同的值。 
  
比如這個(gè)each方法,如果后接代碼塊,則會(huì )把數組中的每個(gè)元素依次傳遞給代碼塊,讓它運行某些命令,而如果each方法未后接代碼塊,則返回一個(gè)Enumerator實(shí)例 
  
很多一般后接代碼塊的迭代方法若不加block,都返回Enumerator實(shí)例,如File類(lèi)和String類(lèi)的each_line、each_char等(這個(gè)不是語(yǔ)法規定,而是方法內部就這么處理的,具體參見(jiàn)官方API文檔) 
  
Q:Enumerator類(lèi)的作用是什么? 
  
可以說(shuō)把迭代操作這個(gè)動(dòng)作抽象化為對象。一般的用途包括: 
  
1、多個(gè)對象同時(shí)并行迭代,如: 
  
e1 = [ 1, 2, 3, 4, 5].each 
e2 = [ 99, 98, 97, 96 ,95].each 
new_array = [] 
loop { 
  new_array << e1.next 
  new_array << e2.next 

p new_array # [1, 99, 2, 98, 3, 97, 4, 96, 5, 95] 
  
2、給原來(lái)的迭代方法增加新的功能,如Enumerator類(lèi)有一個(gè)方法with_index: 
  
e1 = string.each_char 
e2 = array.each 
e1.with_index(1) {|char,index|   } # 參數1表示從1開(kāi)始計數,無(wú)參數則從0開(kāi)始 
e2.with_index {|elem,index|      } 
  
這樣傳遞給后面block的,就不僅包括原來(lái)的每個(gè)字符、每個(gè)元素,連帶把對應的索引數也傳了 
  
3、無(wú)限循環(huán)??梢远x一個(gè)帶yield的方法,轉換為Enumerator對象,實(shí)現無(wú)限循環(huán) 
  
def foo 
  i = 0;  loop { i = i + 3; yield i } 
end 
  
#foo {|i| print i} # 別運行,這是死循環(huán) 
  
e = to_enum(:foo) 
  
# to_enum的作用是把:foo這個(gè)symbol所指代的foo方法轉為Enumerator對象 
  
1234.times { e.next } # 讓它迭代1234次,可以無(wú)限迭代 
p e.next # 3705 
  
Q:yield是干什么用的? 
  
方法定義中把控制權交給代碼塊,是用來(lái)實(shí)現each這一類(lèi)迭代方法的直接途徑: 
  
def from_to_by(from, to, by) 
  x = from 
  while x <= to 
    yield x 
    x += by 
  end 
end 
  
from_to_by(3,26,4) {|x| print x, " " } # 3 7 11 15 19 23 
  
自己的迭代方法就這樣定義好了 
  
Q:iterator?是什么意思? 
  
現在一般寫(xiě)成block_given?,這就好理解一點(diǎn)了吧。 
  
在方法定義中用來(lái)判斷這個(gè)方法在調用時(shí)是否后接代碼塊 
  
def foo 
  if block_given? 
     
# blah blah 
  else 
     
# blah blah 
  end 
end 
  
這樣一個(gè)方法就可以根據是否后接block而做不同的事了 
  
iterator?是block_given?的同義詞,字面意思是問(wèn)當前方法是否用作iterator,用作iterator意味著(zhù)必接block,像each這樣的方法可以說(shuō)是iterator方法,但不是所有后接代碼塊的都是iterator,如
File.open(file) {|f| },這個(gè)時(shí)候說(shuō)open是iterator就不太妥當,而說(shuō)block_given?總是恰當的 
  
Q:方法定義和方法調用里的&是什么意思?比如def foo(a,b,&blk) 
  
在方法定義中,&連帶后面的變量名必須是最后一個(gè),表示把方法調用時(shí)的代碼塊轉換為Proc實(shí)例 
  
def foo(a,b,&blk) 
   
# blah blah 
end 
  
foo(x,y) {|n| n + 1} 
# blk的值就相當于Proc.new {|n| n + 1}了 
  
如果沒(méi)帶代碼塊,不會(huì )報錯,只是blk的值為nil了 
  
用這種方式最大的好處是:blk是一個(gè)對象,可以傳遞給別的方法 
  
而 
blk.call(x,y) 相當于 yield x,y,blk.nil? 也可以達到和 block_given? 同樣的目的,檢測是否接了代碼塊 
  
Q:array.map(&:upcase)是什么意思? 
  
這種寫(xiě)法有點(diǎn)晦澀。上面已經(jīng)說(shuō)了&的涵義,&要求它后面的對象是個(gè)Proc實(shí)例,假如不是,則調用它的to_proc方法生成一個(gè)proc 
  
而Symbol類(lèi)正好有一個(gè)實(shí)例方法to_proc 
  
:a_method.to_proc 變成的代碼塊相當于: 
  
Proc.new {|obj, *args| obj.send(:a_method,*args) } 
  
array.map(&:upcase)的理解過(guò)程是: 
  
一變:
array.map {|obj, *args| obj.send(:upcase, *args) } 
二變:
array.map {|obj, *args| obj.upcase(*args) 
三變:
array.map {|obj| obj.upcase } # upcase這個(gè)方法不需參數 
  
Q:class Foo < Bar是什么意思? 
  
表示創(chuàng )建新的類(lèi)Foo,是Bar的子類(lèi),Ruby用<形象地表示Foo和Bar之間的關(guān)系 
  
<也可以用來(lái)快速檢測兩個(gè)類(lèi)或模塊之間的關(guān)系,如String類(lèi)是Object類(lèi)的子類(lèi),則 
  
String < Object # true 
Object > String # true 
  
Q:class << obj是什么意思? 
  
打開(kāi)obj的singleton類(lèi),通常用來(lái)定義singleton方法 
  
比如str是個(gè)字符串,也就是個(gè)String類(lèi)的實(shí)例,String類(lèi)的實(shí)例方法str都可以調用 
我們又可以定義只有str這個(gè)對象才能調用的方法,這樣的方法就是str的singleton方法 
  
class << str 
  def foo # 這個(gè)foo方法只能被str調用,不能被String類(lèi)的其他實(shí)例調用 
     
# blah blah 
  end 
end 
  
Q:def obj.method是什么意思? 
  
也是定義obj的singleton方法,直接定義,沒(méi)有打開(kāi)singleton class 
  
定義所謂類(lèi)方法,也是這種方式: 
  
def String.foo 
   
# blah blah 
end 
  
實(shí)際上類(lèi)也是對象,所謂類(lèi)方法,也就是類(lèi)對象的singleton方法 
  
Q:定義方法為什么不用self作為第一個(gè)參數? 
  
Ruby是純OOP語(yǔ)言,沒(méi)有函數,全是方法,所以省了傳遞self 
  
class String 
  def foo(x,y,z) 
     
# blah blah 
  end 
end 
  
str = "abc" 
str.foo(1,2,3) 
  
# 方法定義時(shí)的參數,和方法調用時(shí)的參數,看起來(lái)就一致了 
  
Q:Ruby中的self是變量么? 
  
不是變量,而是個(gè)關(guān)鍵詞。在任何環(huán)境self都指向一個(gè)對象 
  
module Foo 
  p self          # self 為 Foo 
  class Bar 
    p self        # self 為 Foo::Bar 
    def baz 
      p self      # self 為調用此方法的對象 
    end 
  end 
end 
  
Q:sub、gsub方法是什么作用? 
  
String類(lèi)的sub方法作用是替換子串并生成新字符串,gsub是替換所有匹配子串 
對應的sub!和gsub!是在原字符串上進(jìn)行修改,不生成新對象 
  
String#replace并不是替換子串的作用,而是把字符串整個(gè)替換成別的值,但本身對象不變 
  
str = "abc" 
str.replace "def" 
# str有相同的object_id,但內容由"abc"替換為"def"了 
  
  
Q:String類(lèi)的scan方法是什么作用? 
  
從一個(gè)字符串中抽取出所有匹配的子串 
  
str = "a1b2c3d4e5" 
p str.scan(/\d/) # ["1", "2", "3", "4", "5"] 
  
可以后接代碼塊依次處理每個(gè)匹配子串 
  
str.scan(/\d/) {|c| print c} 
  
Q:Array類(lèi)的&和|表示什么意思? 
  
&表示返回兩個(gè)數組的交集,去除重復元素 
  
  
 [ 1, 1, 3, 5 ] & [ 1, 2, 3 ]   #=> [ 1, 3 ] 
  
|表示返回兩個(gè)數組的并集,去除重復元素 
  
  
[ "a", "b", "c" ] | [ "c", "d", "a" ]    #=> [ "a", "b", "c", "d" ] 
※ 修改:·sevk 于 Sep  1 10:11:18 2013 修改本文·[FROM: 122.225.48.*] 
※ 來(lái)源:·水木社區 newsmth.net·[FROM: 221.218.155.*] 
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
第18章 JavaScript中的數組-參考題
PHP開(kāi)發(fā)經(jīng)驗總結
PHP 數組和字符串互相轉換實(shí)現方法
Python入門(mén)篇之對象類(lèi)型
Ruby學(xué)習筆記
【Python之路】特別篇
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久