日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
F#運(yùn)算符定義規(guī)則總結(jié)

本文將討論的是F#運(yùn)算符相關(guān)定義規(guī)則的問題,這些規(guī)則覆蓋大多數(shù)開發(fā)場景。希望通過本文能對大家了解F#運(yùn)算符規(guī)則有所幫助。

創(chuàng)新互聯(lián)專注于企業(yè)成都營銷網(wǎng)站建設(shè)、網(wǎng)站重做改版、微山網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、html5成都商城網(wǎng)站開發(fā)、集團(tuán)公司官網(wǎng)建設(shè)、外貿(mào)網(wǎng)站制作、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為微山等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。

#T#

F#允許開發(fā)人員定義或重載各類運(yùn)算符,合理利用這一規(guī)則可以讓編程變得方便,讓代碼更容易閱讀。例如,在使用F#的MailboxProcessor的時(shí)候,我會習(xí)慣于定義一個(gè)運(yùn)算符來代替顯式的Post操作:

 
 
  1. let (>>) m (agent: MailboxProcessor<_>) = agent.Post m 

這樣便可以這樣發(fā)送消息:

 
 
  1. let agent = MailboxProcessor.Start(fun o -> async { o |> ignore });  
  2. "hello world" >> agent 

不過,F(xiàn)#的運(yùn)算符定義規(guī)則較為復(fù)雜,要搞清楚編譯器的整體處理方式著實(shí)花費(fèi)了一番功夫。比較奇怪的是,即便是《Expert F#》中對于這個(gè)話題也沒有詳細(xì)的敘述——更夸張的是MSDN的文檔也相當(dāng)馬虎,甚至有代碼缺失以及與試驗(yàn)不符情況(因?yàn)檫€沒有正式發(fā)布?)。于是我連看帶試,最終打算總結(jié)一番,作為備忘的同時(shí)也算是補(bǔ)充互聯(lián)網(wǎng)資源。

運(yùn)算符重載

F#中允許在global級別重載一個(gè)運(yùn)算符,甚至“覆蓋”原有的定義。例如,我們可以寫一個(gè)Operator模塊,其中只有一個(gè)“加號”的定義:

 
 
  1. // operator.fs  
  2. #light  
  3. module Operator  
  4. let (+) (a:int) (b:int) = a * b 

我們可以在另一個(gè)模塊中引入Operator模塊,于是兩個(gè)整數(shù)的“加法”便可以得出乘法的效果了:

 
 
  1. 1 + 2 |> printfn "%i" // 2 

從中也可以看出,胡亂重載運(yùn)算符實(shí)在是一種沒事找事的方式。因此,現(xiàn)在這篇文章純粹都是在“談技術(shù)”,所有的內(nèi)容,包括示例都不代表“***實(shí)踐”。

運(yùn)算符的組成

在F#中,自定義運(yùn)算符可以由以下字符組成:

 
 
  1. ! % & * + - . / < = > ? @ ^ | ~ 

目前在MSDN中,《Operator Overloading (F#)》一文寫到“$”也可以作為運(yùn)算符的組成,不過***的F#編譯器(v1.9.7.4)中會對此作出“警告”,表示以后它將成為一個(gè)F#的保留字,不允許用作運(yùn)算符。

在F#中,每個(gè)運(yùn)算符不限長度。也就是說,如果您喜歡的話,完全可以定義這樣的一個(gè)運(yùn)算符來表示整數(shù)加法:

 
 
  1. let (!%&*+-./<=>?@^|~!%&*+-./<=>?@^|~) (x : int) (y : int) = x * y 

F#會將運(yùn)算符編譯為程序集中具體的方法,其命名遵循一定規(guī)則。不過在使用時(shí)我們并不需要關(guān)心這些。如果您對這方面的具體信息感興趣,可以參考MSDN中《Operator Overloading (F#)》一文。

前綴與中綴運(yùn)算符

前綴(prefix)運(yùn)算符,表示運(yùn)算符出現(xiàn)在運(yùn)算數(shù)之前,例如“負(fù)號”便是個(gè)前綴運(yùn)算符:

 
 
  1. let a = 1  
  2. -a |> printfn "%i" // -1 

中綴(postfix)運(yùn)算符,表示運(yùn)算符出現(xiàn)在兩個(gè)運(yùn)算數(shù)之間,例如最常見的“加法”便是個(gè)中綴運(yùn)算符:

 
 
  1. 1 + 2 |> printfn "%i" // 3 

在自定義運(yùn)算符時(shí),F(xiàn)#并不允許我們指定某個(gè)運(yùn)算符是前綴還是中綴運(yùn)算符,編譯器會自動根據(jù)運(yùn)算符的“首字母”來決定它是前綴還是中綴的。例如,首字母為“感嘆號”的運(yùn)算符便是“前綴”運(yùn)算符:

 
 
  1. let (!+) (x:int) (y:int) = x + y 

根據(jù)這個(gè)規(guī)則,我們只能將“!+”作為前綴運(yùn)算符來使用:

 
 
  1. 1 (!+) 2 |> printfn "%i" // 編譯失??!  
  2. !+ (!+ 1 2) 3 |> printfn "%i" // 6 

關(guān)于某個(gè)字母表示前綴還是中綴運(yùn)算符,您可以參考《Operator Overloading (F#)》一文中的表格。可以發(fā)現(xiàn),大部分運(yùn)算符都是中綴的,而只有少數(shù)是前綴運(yùn)算符。至于后綴運(yùn)算符……F#并不支持后綴運(yùn)算符。

F#運(yùn)算符的優(yōu)先級

每個(gè)運(yùn)算符有其自己的優(yōu)先級(precedence),優(yōu)先級表示一個(gè)表達(dá)式中連續(xù)出現(xiàn)多個(gè)運(yùn)算符時(shí),究竟哪個(gè)運(yùn)算符先生效。例如,我們都知道“先乘除后加減”:

3 + 4 * 5 |> printfn "%i" // 23那么,我們自定義的運(yùn)算符優(yōu)先級又如何呢?F#同樣是通過運(yùn)算符的首字母來決定它的優(yōu)先級的,關(guān)于不同首字母的優(yōu)先級高低,可以參考MSDN中《Symbol and Operator Reference (F#)》的Operator Precedence一節(jié),它按照優(yōu)先級從低到高列舉所有的運(yùn)算符。

例如“除號”的優(yōu)先級比“加號”高,因此:

 
 
  1. let (+/) (x:int) (y : int) = x / y  
  2. let (/+) (x:int) (y : int) = x + y  
  3. 4 + 4 / 2 |> printfn "%i" // 6  
  4. 4 /+ 4 +/ 2 |> printfn "%i" // 4 

值得注意的是,如果兩個(gè)運(yùn)算符的首字母相同,則F#便認(rèn)為兩個(gè)運(yùn)算符的優(yōu)先級相同,而不在比較它們后續(xù)字符的優(yōu)先級高低。不過在優(yōu)先級的判定中有個(gè)特例,那就是“點(diǎn)”,它并不參與優(yōu)先級的比較中,此時(shí)便以后面的字符為準(zhǔn)了:

 
 
  1. let (.+) (x:int) (y:int) = x + y  
  2. let (..*) (x:int) (y:int) = x * y  
  3. // 仍然是“先乘除后加減”  
  4. 3 .+ 4 ..* 5 |> printfn "%i" // 23  
  5. 3 ..* 4 .+ 5 |> printfn "%i" // 17 

當(dāng)然,括號可以改變運(yùn)算符的優(yōu)先級,這點(diǎn)再正常不過了。還有一點(diǎn),便是“轉(zhuǎn)發(fā)”操作(即本文代碼中出現(xiàn)的“|>”),它以“|”作為首字母。根據(jù)規(guī)則,它的優(yōu)先級是很低的(在自定義運(yùn)算符中是***的)。因此,無論我們左側(cè)的表達(dá)式中使用了什么樣的運(yùn)算符,都是***才進(jìn)行“轉(zhuǎn)發(fā)”操作。

運(yùn)算符的相關(guān)性

每個(gè)運(yùn)算符都有其相關(guān)性(associativity)。相關(guān)性的作用是,一旦一個(gè)表達(dá)式中連續(xù)出現(xiàn)優(yōu)先級相同的運(yùn)算符,那么它們究竟是從左向右計(jì)算(左相關(guān)),還是從右向左計(jì)算(右相關(guān))。
例如,最普通的“除號”便是左相關(guān)的:

 
 
  1. 4 / 2 / 2 |> printfn "%i" // 1 

而List操作的“連接符”(連接單個(gè)元素與一個(gè)列表)便是右相關(guān)的:

 
 
  1. 1 :: 2 :: 3 :: [] |> printfn "%A" // [1; 2; 3] 

在F#中,運(yùn)算符的相關(guān)性也是由首字母決定的,您可以在MSDN中《Symbol and Operator Reference (F#)》的Operator Precedence一節(jié)查到所有字符的相關(guān)性。

例如,“大于號”是左相關(guān)的,因此:

 
 
  1. let (>+) (x:int) (y:int) = x + y  
  2. let (>*) (x:int) (y:int) = x * y  
  3. 3 >+ 4 >* 5 |> printfn "%i" // 35  
  4. 3 >* 4 >+ 5 |> printfn "%i" // 17而“^”是右相關(guān)的:  
  5. let (^+) (x:int) (y:int) = x + y  
  6. let (^*) (x:int) (y:int) = x * y  
  7. 3 ^+ 4 ^* 5 |> printfn "%i" // 23  
  8. 3 ^* 4 ^+ 5 |> printfn "%i" // 27 

自然,括號可以改變運(yùn)算符的相關(guān)性。

一元運(yùn)算符

之前我們討論的大都是二元運(yùn)算符(即需要兩個(gè)運(yùn)算數(shù)),不過有一個(gè)字符比較特殊,它便是“~”,我們可以利用它來定義一個(gè)“一元運(yùn)算符”:

 
 
  1. let (~-) (x:int) = x + 1  
  2. let a = 1  
  3. -a |> printfn "%i" // 2 

這效果是不是很神奇?因此,如果您要重載現(xiàn)有的運(yùn)算符,請一定三思而后行。

為類型定義運(yùn)算符

之前我們一直在討論“全局”級別的運(yùn)算符。事實(shí)上,運(yùn)算符也可以定義在某個(gè)類型內(nèi)部。例如:

 
 
  1. // 定義  
  2. type Rational(numer, denom) =  
  3.  
  4.     member r.Numer = numer  
  5.     member r.Denom = denom  
  6.  
  7.     static member (-) (x:Rational, y:Rational) =  
  8.         let n = x.Numer * y.Denom - y.Numer * x.Denom  
  9.         let d = x.Denom * y.Denom  
  10.         new Rational(n, d)  
  11.  
  12.     static member (~-) (v:Rational) = new Rational(-v.Numer, v.Denom)  
  13.  
  14. // 使用  
  15. let r1 = new Rational(1, 2)  
  16. let r2 = new Rational(2, 3)  
  17. let r3 = r1 - r2  
  18. let r4 = -r1 

至于運(yùn)算符的優(yōu)先級、相關(guān)性等性質(zhì),都與上文描述的保持一致。


網(wǎng)站題目:F#運(yùn)算符定義規(guī)則總結(jié)
本文鏈接:http://www.5511xx.com/article/djciihg.html