簡體   English   中英

為什么觸發器操作符包含第二個條件?

[英]Why does a Flip-Flop operator include the second condition?

以下代碼使用觸發器操作符。

(1..10).each {|x| print "#{x}," if x==3..x==5 }

為什么結果3,4,5

我認為它應該是3,4

正如教程中所提到的,當x == 3時,該表達式變為true,並且在x == 5之前一直為真。 如果評價為假,怎么會打印'5'? 有人可以請我澄清一下嗎?

“Ruby編程語言”的重要環節是:

4.6.9.1 Boolean flip-flops

當..和...運算符用於條件(如if語句)或循環(例如while循環)時(有關條件和循環的更多信息,請參閱第5章),它們不會創建Range對象。 相反,他們創建了一種特殊的布爾表達式,稱為觸發器。 觸發器表達式的計算結果為true或false,就像比較和等式表達式一樣。 然而,關於觸發器表達的非常不尋常的事情是它的值取決於先前評估的值。 這意味着觸發器表達式具有與之相關的狀態; 它必須記住以前評估的信息。 因為它有狀態,你會期望觸發器成為某種對象。 但它不是 - 它是一個Ruby表達式,並且Ruby解釋器在其表達式的內部解析表示中存儲它所需的狀態(只是一個布爾值)。

考慮到這一背景,請考慮以下代碼中的觸發器。 請注意,代碼中的第一個..創建一個Range對象。 第二個創建觸發器表達式:

 (1..10).each {|x| print x if x==3..x==5 }

觸發器由兩個布爾表達式組成,它們在條件或循環的上下文中與..運算符連接。 觸發器表達式為false,除非並且直到左手表達式的計算結果為真。 一旦表達式成為現實,表達式就會“翻轉”為持久的真實狀態。 它保持在該狀態,隨后的評估將返回true,直到右側表達式求值為true。 當發生這種情況時,觸發器“翻轉”回到持久的錯誤狀態。 對表達式的后續計算返回false,直到左手表達式再次變為true。 在代碼示例中,觸發器被重復計算,x的值從1到10.它從假狀態開始,當x是1和2時評估為假。當x == 3時,翻轉 - 翻轉翻轉為true並返回true。 當x為4和5時,它繼續返回true。然而,當x == 5時,觸發器將翻轉為false,並對x的剩余值返回false。 結果是此代碼打印345。

..或者觸發器繼承自Perl,它從AWK獲得並在* nix中獲得。 它功能非常強大,但在你的特定用途中它是相當模糊的,並不是你想要的邏輯的好選擇,特別是在Ruby中。 而是使用:

(1..10).each {|x| puts x if (3..5) === x }

哪個輸出:

3
4
5

也就是說,當您需要從文件中提取一系列行時,它非常強大:

File.foreach('/usr/share/dict/propernames') { |li| puts li if ($. == 5 .. $. == 7) }

哪個輸出:

Agatha
Ahmed
Ahmet

Perl只使用當前讀取行(AKA $. )的行號允許更簡潔的表達式,但Ruby不支持它。

還可以選擇使用正則表達式,其行為與之前的比較相似:

File.foreach('/usr/share/dict/propernames') { |li| puts li if (li[/^Wa/] .. li[/^We/]) }

哪個輸出:

Wade
Walt
Walter
Warren
Wayne
Wendell

因為正則表達式工作,所以可以創建一個復雜的模式來根據匹配從文件中檢索行。 作為第一個,然后是第二個模式觸發器,捕獲線。 如果,在文件的后面,另一行觸發第一個模式,則再次發生捕獲,直到第二個模式匹配。 它非常強大:

File.foreach('/usr/share/dict/propernames') { |li| puts li if (
    li[/^Am/] .. li[/^An/] or
    li[/^Wa/] .. li[/^We/]
  )
}

哪個輸出:

Amanda
Amarth
Amedeo
Ami
Amigo
Amir
Amos
Amy
Anatole
Wade
Walt
Walter
Warren
Wayne
Wendell

或者,對於我們模糊代碼的朋友說:

File.foreach('/usr/share/dict/propernames') { |li| puts li if (li[/^(?:Am|Wa)/] .. li[/^(?:An|We)/]) }

我找到一段代碼來說明觸發器是如何工作的(就在這段代碼出現的同一本書中,希望它能幫助那些像我一樣有問題的人)

$state = false # Global storage for flip-flop state
    def flipflop(x) # Test value of x against flip-flop
        if !$state # If saved state is false
            result = (x == 3) # Result is value of lefthand operand
            if result # If that result is true
                 $state = !(x == 5) # Then saved state is not of the righthand operand
            end
            result # Return result
        else # Otherwise, if saved state is true
            $state = !(x == 5) # Then save the inverse of the righthand operand
            true # And return true without testing lefthand
        end
    end

您在尋找專屬系列嗎? 你可以使用三個點和cover? 方法。

(1..10).each { |x| print "#{x}," if (3...5).cover?(x) }

在你的例子中它打印3,4,5的原因是因為它表示如果x在3到5的范圍內打印它。

為了澄清@MurifoX的注釋,觸發器在x==5之前是真的,因此當x==5時是真的,但是每次在此之后計算表達式時它都是假的。 因此,你仍然看到5被打印。

觸發器表達式的計算結果為true或false,就像比較和等式表達式一樣。 然而,關於觸發器表達的非常不尋常的事情是它的值取決於先前評估的值。 這意味着觸發器表達式具有與之相關的狀態; 它必須記住以前評估的信息。 因為它有狀態,你會期望觸發器成為某種對象。 但它不是 - 它是一個Ruby表達式,並且Ruby解釋器在其表達式的內部解析表示中存儲它所需的狀態(只是一個布爾值)。 考慮到這一背景,請考慮以下代碼中的觸發器。 請注意,代碼中的第一個“..”創建一個Range對象。 第二個創建觸發器表達式:

(1..10).each {|x| print x if x==3..x==5 }

觸發器由兩個布爾表達式組成,它們在條件或循環的上下文中與..運算符連接。 觸發器表達式為false,除非並且直到左手表達式的計算結果為真。 一旦該表達式變為真,表達式“翻轉”為持久的真實狀態。 它保持在該狀態,隨后的評估將返回true,直到右側表達式求值為true。 當發生這種情況時,觸發器“翻轉”回到持久的錯誤狀態。 對表達式的后續計算返回false,直到左手表達式再次變為true。 在代碼示例中,觸發器被重復評估,x的值從1到10.它以假狀態開始,並且當x是1和2時評估為假。 當x == 3時,觸發器翻轉為真並返回true。 當x為4和5時,它繼續返回true。 然而,當x == 5時,觸發器將翻轉為假,並對x的剩余值返回false。 結果是此代碼打印345。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM