專利名稱:拉姆達(dá)表達(dá)式的制作方法
拉姆達(dá)表達(dá)式背景編程語(yǔ)言持續(xù)發(fā)展以便于程序員的說(shuō)明以及高效的執(zhí)行。在早期的計(jì)算機(jī)語(yǔ) 言中,低級(jí)機(jī)器碼是普遍的。采用機(jī)器碼,計(jì)算機(jī)程序或構(gòu)成計(jì)算機(jī)程序的指令是 用機(jī)器語(yǔ)言或匯編語(yǔ)言來(lái)編寫的,并由硬件(例如,微處理器)執(zhí)行。這些語(yǔ)言提 供了控制計(jì)算硬件的有效手段,但是對(duì)程序員而言非常難以理解和開發(fā)復(fù)雜邏輯。 隨后,引入了提供各層抽象的語(yǔ)言。因此,程序員可用較高級(jí)源語(yǔ)言在較高的級(jí)別 上編寫程序,該程序然后經(jīng)由編譯器或解釋器轉(zhuǎn)換成硬件理解的較低級(jí)機(jī)器語(yǔ)言。 編程中的進(jìn)一步進(jìn)展提供了另外的抽象層,以允許比以前快得多地指定更高級(jí)的編 程邏輯。然而,這些進(jìn)步并不是在沒(méi)有處理成本的情況下發(fā)生的。編譯器和/或解釋器承擔(dān)了將高級(jí)邏輯轉(zhuǎn)換成可執(zhí)行機(jī)器碼的負(fù)擔(dān)。一般而言,編譯器和/或解釋器是接收以源編程語(yǔ)言(例如,C、 C#、 Visual Basic、 Java…)指定的程序并將由此提供的邏輯轉(zhuǎn)換成可由硬件設(shè)備執(zhí)行的機(jī)器語(yǔ)言的組件。然而, 轉(zhuǎn)換無(wú)需逐字完成。實(shí)際上,常規(guī)的編譯器和/或解釋器分析源代碼并生成非常高 效的代碼。例如,程序員編寫直觀且為人們易于理解的陳述了操作邏輯流程的代碼, 但是這通常對(duì)計(jì)算機(jī)執(zhí)行而言是低效的。編譯器和/或解釋器可標(biāo)識(shí)該低效性并通 過(guò)消除不必要的操作和/或重新排列指令的執(zhí)行同時(shí)仍實(shí)現(xiàn)預(yù)期的結(jié)果而在硬件級(jí) 上改進(jìn)程序性能。以此方式,程序員可創(chuàng)建健壯且高效的軟件程序。概述以下提出了簡(jiǎn)化概述以提供對(duì)所要求保護(hù)的主題的某些方面的基本理解。本 概述并不是廣泛綜述。它并不旨在標(biāo)識(shí)所要求保護(hù)的主題的關(guān)鍵/決定性要素,也 不旨在描繪其范圍。其唯一的目的是以簡(jiǎn)化形式提出某些概念作為以后提出的更詳 細(xì)描述的序言。簡(jiǎn)言之,所提供的主題涉及拉姆達(dá)表達(dá)式以及這種表達(dá)式在命令性和/或面向 對(duì)象的計(jì)算機(jī)編程語(yǔ)言中的應(yīng)用。拉姆達(dá)表達(dá)式提供了比常規(guī)形式更簡(jiǎn)明的指定值 或數(shù)據(jù)的方式。例如,拉姆達(dá)表達(dá)式可提供指定匿名方法的更簡(jiǎn)潔且功能性方式。拉姆達(dá)表達(dá)式也可參與類型推導(dǎo)。拉姆達(dá)表達(dá)式本身無(wú)需具有類型。相反, 它可具有參數(shù)類型和返回類型等等。為減少與拉姆達(dá)表達(dá)式的指定相關(guān)聯(lián)的冗長(zhǎng)性,這些類型不必明確規(guī)定。提供了用于基于上下文來(lái)推導(dǎo)這些類型的系統(tǒng)和方法。 另外,拉姆達(dá)表達(dá)式可便于重載解決。例如,在一方法被重載的情況中,拉姆達(dá)表達(dá)式可便于選擇一特定方法。例如,在將拉姆達(dá)表達(dá)式用作重載方法的自變量時(shí),該表達(dá)式的返回類型可用作選擇特定方法的因素。為實(shí)現(xiàn)上述和相關(guān)目的,此處結(jié)合以下描述和附圖描述了所要求保護(hù)的主題的某些說(shuō)明性方面。這些方面指示了可實(shí)施本主題的各種方式,所有這些都旨在落入所要求保護(hù)的主題的范圍之內(nèi)。當(dāng)結(jié)合附圖考慮以下詳細(xì)描述時(shí),其它優(yōu)點(diǎn)和新穎特征將變得顯而易見(jiàn)。附圖簡(jiǎn)述
圖1是用于拉姆達(dá)表達(dá)式的執(zhí)行系統(tǒng)的框圖。圖2是用于支持拉姆達(dá)表達(dá)式的編程系統(tǒng)的框圖。圖3是類型轉(zhuǎn)換系統(tǒng)的框圖。圖4是推導(dǎo)與拉姆達(dá)表達(dá)式相關(guān)聯(lián)的類型的類型推導(dǎo)系統(tǒng)的框圖。圖5是對(duì)拉姆達(dá)表達(dá)式進(jìn)行類型檢查的類型檢查系統(tǒng)的框圖。圖6是重載解決系統(tǒng)的框圖。圖7是拉姆達(dá)表達(dá)式執(zhí)行方法的流程圖。圖8是編程方法的流程圖。圖9是拉姆達(dá)表達(dá)式轉(zhuǎn)換方法的流程圖。圖IO是與拉姆達(dá)表達(dá)式相關(guān)聯(lián)的類型推導(dǎo)方法的流程圖。圖11是示例性類型推導(dǎo)方法的流程圖。圖12是重載解決方法的流程圖。圖13是編譯環(huán)境的示意性框圖。圖14是示出合適的操作環(huán)境的示意性框圖。圖15是示例計(jì)算環(huán)境的示意性框圖。詳細(xì)描述現(xiàn)在參考附圖來(lái)描述本發(fā)明的各方面,在全部附圖中相同的標(biāo)號(hào)指代相同或 對(duì)應(yīng)的元素。然而,應(yīng)當(dāng)理解,附圖和所涉及的詳細(xì)描述并不旨在將所要求保護(hù)的主題限于所公開的具體形式。相反,本發(fā)明覆蓋落入所要求保護(hù)的主題的精神和范 圍內(nèi)的所有修改、等效技術(shù)方案和替換方案。如此處所使用的,術(shù)語(yǔ)"組件"、"系統(tǒng)"等指的是計(jì)算機(jī)相關(guān)的實(shí)體,它 或者是硬件、硬件和軟件的組合、軟件、或者是執(zhí)行中的軟件。例如,組件可以是, 但不限于,運(yùn)行在處理器上的進(jìn)程、處理器、對(duì)象、可執(zhí)行代碼、執(zhí)行的線程、程 序和/或計(jì)算機(jī)。作為說(shuō)明,運(yùn)行在計(jì)算機(jī)上的應(yīng)用程序和計(jì)算機(jī)都可以是組件。 一個(gè)或多個(gè)組件可駐留在一個(gè)進(jìn)程和/或執(zhí)行的線程內(nèi),并且組件可位于一臺(tái)計(jì)算 機(jī)上和/或分布在兩臺(tái)或多臺(tái)計(jì)算機(jī)之間。此處所使用的詞語(yǔ)"示例性"意味著用作示例、實(shí)例或說(shuō)明。此處被描述為 "示例性"的任何方面或設(shè)計(jì)不一定被解釋為對(duì)于其它方面或設(shè)計(jì)是優(yōu)選或有利 的。此外,所公開的主題可使用產(chǎn)生控制基于計(jì)算機(jī)或處理器的設(shè)備來(lái)實(shí)現(xiàn)此處 詳細(xì)描述的各方面的標(biāo)準(zhǔn)編程和/或工程技術(shù)而被實(shí)現(xiàn)為系統(tǒng)、方法、裝置或制品。 如此處所使用的術(shù)語(yǔ)"制品"(或者替代地,"計(jì)算機(jī)程序產(chǎn)品")旨在涵蓋可從 任何計(jì)算機(jī)可讀設(shè)備、載體或介質(zhì)訪問(wèn)的計(jì)算機(jī)程序。例如,計(jì)算機(jī)可讀介質(zhì)可包 括但不限于,磁存儲(chǔ)設(shè)備(例如,硬盤、軟盤、磁條……)、光盤(例如,緊致盤(CD)、數(shù)字多功能盤(DVD)……)、智能卡、以及閃存設(shè)備(例如,卡、棒)。另外,應(yīng)當(dāng)理解,可采用載波來(lái)承載諸如在發(fā)送和接收郵件或訪問(wèn)諸如因特網(wǎng)或局域網(wǎng)(LAN)等網(wǎng)絡(luò)時(shí)使用的計(jì)算機(jī)可讀電子數(shù)據(jù)。當(dāng)然,本領(lǐng)域的技術(shù)人員將 認(rèn)識(shí)到,可對(duì)此配置進(jìn)行許多修改而不脫離所要求保護(hù)的主題的范圍或精神。一開始轉(zhuǎn)向圖l,示出了用于執(zhí)行拉姆達(dá)表達(dá)式的執(zhí)行系統(tǒng)100。系統(tǒng)100包 括接收器組件110和求值組件120。接收器組件110獲得拉姆達(dá)表達(dá)式并將該表達(dá) 式發(fā)送到求值組件120。求值組件120獲得該表達(dá)式,計(jì)算并返回特定類型的值。拉姆達(dá)表達(dá)式是一種簡(jiǎn)潔地指定或捕捉值和數(shù)據(jù)等的機(jī)制。在一個(gè)實(shí)例中, 可采用拉姆達(dá)表達(dá)式來(lái)指定或替換匿名方法。匿名方法允許與委托(delegate)相 關(guān)聯(lián)的程序性代碼例如被"內(nèi)聯(lián)地"表達(dá)或編寫。作為示例,假定希望對(duì)以C弁表 達(dá)為ffinumerable<customer>cs的顧客集合進(jìn)行查詢。返回低于35歲的顧客的查詢 將被指定為<formula>formula see original document page 6</formula>static bool f(customer c) {return cage < 35;}可替代地指定匿名方法以簡(jiǎn)化這一表達(dá)式的指定,例如 cs.where(delegate (Customer c) {return cage <35;})這比先前的示例更簡(jiǎn)潔,至少是因?yàn)椴恍枰付ㄐ骂?。相反,由delegate關(guān)鍵字標(biāo) 識(shí)的匿名方法被內(nèi)聯(lián)為自變量。然而,對(duì)匿名方法的指定仍是相當(dāng)冗長(zhǎng)的。此處, 可采用拉姆達(dá)表達(dá)式來(lái)替換匿名方法。根據(jù)上一示例,可利用拉姆達(dá)表達(dá)式來(lái)更簡(jiǎn) 潔且更功能性地指定信息。具體地,拉姆達(dá)表達(dá)式可對(duì)應(yīng)于cs.where(|c| c,age<35)此處,標(biāo)識(shí)了參數(shù)"c"以及表達(dá)式"c.age<35"。這遠(yuǎn)不如先前的表示那樣冗長(zhǎng), 至少是因?yàn)樗瞬槐匾木浞ㄒ约帮@式類型聲明(例如,Customer)。拉姆達(dá)表達(dá)式可被指定為由豎線括住的參數(shù)列表后跟表達(dá)式或表達(dá)式主體。 例如,拉姆達(dá)表達(dá)式可如偽BNF (巴科斯-諾爾范式)中指定的結(jié)構(gòu)化拉姆達(dá)表達(dá)式l拉姆達(dá)參數(shù)列表wffisl拉姆達(dá)表達(dá)式主體 拉姆達(dá)參數(shù)列表顯式類型化拉姆達(dá)參數(shù)列表 隱式類型化拉姆達(dá)參數(shù)列表 顯式類型化拉姆達(dá)參數(shù)列表 顯式類型化拉姆達(dá)參數(shù)顯式類型化拉姆達(dá)參數(shù)列表,顯式類型化拉姆達(dá)參數(shù)顯式類型化拉姆達(dá)參數(shù)類型標(biāo)識(shí)符 隱式類型化拉姆達(dá)參數(shù)列表隱式類型化拉姆達(dá)參數(shù)隱式類型化拉姆達(dá)參數(shù)列表,隱式類型化拉姆達(dá)參數(shù) 隱式類型化拉姆達(dá)參數(shù)標(biāo)識(shí)符 拉姆達(dá)表達(dá)式主體表達(dá)式拉姆達(dá)表達(dá)式可具有通式l參數(shù)l表達(dá)式。然而,也可構(gòu)想另外的指定方式。例 如,拉姆達(dá)表達(dá)式可用參數(shù)=>表達(dá)式、(參數(shù))=>表達(dá)式以及其它定界符和/或符號(hào) 的組合或排列的形式來(lái)聲明。句法也可在拉姆達(dá)表達(dá)式具有空參數(shù)列表的情況下有 所不同。在豎線對(duì)表達(dá)式的參數(shù)進(jìn)行定界并且存在空參數(shù)列表的情況下,所得的語(yǔ) 言符號(hào)將是相鄰的豎線字符(例如,||或| I)。這可產(chǎn)生關(guān)于用于在某些編程語(yǔ)言中表示條件"OR"(或)的相鄰的豎線的歧義。因此,可釆用替換表示,諸如但不限于,相鄰的豎線后跟等號(hào)(例如,I 1=)。然而,應(yīng)當(dāng)理解,相鄰的豎線字符可被重載并用于表示空參數(shù)列表以及條件"OR"。"l參溯表這式"形式的拉姆達(dá)表達(dá)式可對(duì)應(yīng)于"delegate(##){return表這 _^;}"形式的匿名方法。因此,拉姆達(dá)表達(dá)式可替換較冗長(zhǎng)的匿名方法。然而,在 拉姆達(dá)表達(dá)式與匿名方法之間存在差別。特別地,拉姆達(dá)表達(dá)式允許省略并推導(dǎo)參 數(shù)類型(如下文將詳細(xì)描述的),而匿名方法要求顯式規(guī)定參數(shù)類型。另外,匿名 方法的主體被寫作一語(yǔ)句塊,而拉姆達(dá)表達(dá)式的主體可以或者是表達(dá)式或者是語(yǔ)句 塊?;氐綀D1,接收器組件110接收、檢索或以其它方式獲得上述拉姆達(dá)表達(dá)式或 其表示。然后可將拉姆達(dá)表達(dá)式發(fā)送給求值組件120。求值組件120計(jì)算與該拉姆 達(dá)表達(dá)式相關(guān)聯(lián)的值并返回這一值。作為示例而非局限,系統(tǒng)100可以與一程序執(zhí) 行系統(tǒng)相關(guān)聯(lián)。拉姆達(dá)表達(dá)式可以是程序語(yǔ)句或諸如自變量等其它構(gòu)造的一部分, 而返回的值可以進(jìn)一步用于處理相關(guān)聯(lián)的語(yǔ)句。此外,接收器組件110和求值組件 120可協(xié)作以允許對(duì)嵌套和/或分層的拉姆達(dá)表達(dá)式進(jìn)行求值。例如cs.where(|c| c.age<35).Select(|c| new{name=c.name, age=c.age})該語(yǔ)句表示選擇顧客名字和年齡(Select(|c| new{name=c.name, age=c.age})),并且 從中標(biāo)識(shí)其年齡小于35歲的集合顧客(cs) (cs.where(|c|c.age<35))。圖2描繪了用于拉姆達(dá)表達(dá)式的編程系統(tǒng)或環(huán)境200。系統(tǒng)200包括開發(fā)組件 210、編譯器組件220和可執(zhí)行程序230。開發(fā)組件210從諸如程序員等用戶接收 輸入。輸入可包括含有至少一個(gè)拉姆達(dá)表達(dá)式的多個(gè)程序性語(yǔ)句或構(gòu)造。例如,語(yǔ) 句可包括拉姆達(dá)表達(dá)式作為自變量或?qū)⑵滟x值給一函數(shù)或類型。表達(dá)式可用多種形 式中的任一種來(lái)表示,這些形式包括但不限于利用相鄰的豎線(例如,|c| c.age<35) 或雙箭頭(例如,c=>C.age)來(lái)將參數(shù)與表達(dá)式主體分離。開發(fā)組件210可對(duì)應(yīng)于代碼編輯器(例如,文本或圖形的)、集成開發(fā)環(huán)境(IDE)等。編譯器組件220 (以下更詳細(xì)描述)可從開發(fā)組件210接收程序性源代碼,并生成計(jì)算機(jī)可執(zhí)行程 序230或替換地可在運(yùn)行時(shí)例如由運(yùn)行時(shí)(JIT)編譯器進(jìn)一步編譯的某種中間格 式(例如,IL (中間語(yǔ)言))。編譯器組件220也可以是IDE的一部分。圖3描繪了類型轉(zhuǎn)換系統(tǒng)300。拉姆達(dá)表達(dá)式可被分類為具有特殊轉(zhuǎn)換規(guī)則的 值。拉姆達(dá)表達(dá)式?jīng)]有類型,但可被轉(zhuǎn)換(例如,隱式地)為諸如委托類型等兼容 類型。系統(tǒng)300包括兼容性組件310和轉(zhuǎn)換組件320。這兩個(gè)組件都可位于諸如圖 2的編譯器220等編譯器內(nèi)。兼容性組件310接收例如由拉姆達(dá)表達(dá)式和委托類型 函數(shù)組成的拉姆達(dá)表達(dá)式賦值。隨后,兼容性組件可關(guān)于某些規(guī)則或條件312來(lái)分 析賦值類型以確定賦值類型是否與拉姆達(dá)表達(dá)式兼容。如果不滿足條件312,則所 賦的類型不兼容,并且可由兼容性組件310生成錯(cuò)誤或異常?;蛘?,如果滿足條件 310并且類型與拉姆達(dá)表達(dá)式兼容,則該表達(dá)式可由轉(zhuǎn)換組件320轉(zhuǎn)換成該類型。 作為示例而非局限,當(dāng)滿足各種條件312時(shí),委托類型D可與拉姆達(dá)表達(dá)式 L兼容。例如,D可具有非空(non-void)返回類型以及無(wú)引用(no ref)或傳出(out) 參數(shù)。除此之外或作為替代,D和L可能必須具有相同個(gè)數(shù)的參數(shù),并且如果L 具有顯式類型化參數(shù)列表,則D中的每一參數(shù)的類型必須與L中相應(yīng)參數(shù)的類型 相同。除此之外或作為替代,當(dāng)L的參數(shù)被給予D中相應(yīng)參數(shù)的類型時(shí),L的表 達(dá)式主體可以是可被隱式地轉(zhuǎn)換成D的返回類型的有效表達(dá)式。作為示例,假定 表示取類型A的自變量并返回類型R的值的泛型委托類型Function<A, R>:delegate R Function<A,R>(A, arg); 此外,假定以下賦值Func<int, int> f = |x| x +1;拉姆達(dá)表達(dá)式lxl x +1可由轉(zhuǎn)換組件320成功地轉(zhuǎn)換為委托類型Func<int, int>,因?yàn)楫?dāng)x被給予int類型時(shí),x+1是可隱式地轉(zhuǎn)換成int類型的有效表達(dá) 式。賦值等效于更冗長(zhǎng)的匿名方法Function<int, int> f = delegate(intx) {returnx+1};應(yīng)當(dāng)注意,拉姆達(dá)表達(dá)式允許但不要求推導(dǎo)x的類型,而匿名方法要求顯式地規(guī)定類型。轉(zhuǎn)向圖4,描繪了允許關(guān)于拉姆達(dá)表達(dá)式進(jìn)行推導(dǎo)的類型推導(dǎo)系統(tǒng)400。類型 推導(dǎo)系統(tǒng)400可以是諸如編譯器組件220 (圖2)等編譯器的一部分。類型推導(dǎo)系 統(tǒng)400包括上下文組件410和推導(dǎo)組件420。上下文組件410在接收或標(biāo)識(shí)了拉姆 達(dá)表達(dá)式之后,例如從從中獲得特定拉姆達(dá)表達(dá)式的程序接收、檢索或以其它方式 獲得與該拉姆達(dá)表達(dá)式有關(guān)的上下文信息。這一上下文信息可以是與拉姆達(dá)表達(dá)式 有關(guān)的任何信息,包括語(yǔ)句、表達(dá)式、類、類型等。上下文信息由推導(dǎo)組件420 例如經(jīng)由數(shù)據(jù)包的傳輸從上下文組件410中獲得。此外,拉姆達(dá)表達(dá)式可被提供給 推導(dǎo)組件420以便于與其相關(guān)聯(lián)的類型的類型推導(dǎo)。推導(dǎo)組件420隨后可利用該上 下文信息來(lái)推導(dǎo)諸如拉姆達(dá)表達(dá)式參數(shù)、表達(dá)式主體和/或返回類型的類型等類型。 當(dāng)然,類型推導(dǎo)可被傳播,使得所推導(dǎo)的類型可幫助推導(dǎo)其它元素的類型。因此, 推導(dǎo)組件420可生成并維護(hù)可用于進(jìn)行另外的推導(dǎo)的推導(dǎo)集430。應(yīng)當(dāng)理解,拉姆達(dá)表達(dá)式本身沒(méi)有諸如結(jié)構(gòu)類型等與其相關(guān)聯(lián)的類型。相反, 參數(shù)和表達(dá)式主體或返回值具有相關(guān)聯(lián)的類型。認(rèn)識(shí)到結(jié)構(gòu)類型的推導(dǎo)對(duì)于面向?qū)?象的語(yǔ)言而言并非是平凡的。考慮以下示例性拉姆達(dá)表達(dá)式和定義對(duì)象的類var f = (|x| x.age) class Customer{int age} class Wine{string age}不能通過(guò)簡(jiǎn)單地分析該拉姆達(dá)表達(dá)式以及customer (顧客)和wine (酒)對(duì)象類 的結(jié)構(gòu)來(lái)確定參數(shù)(x)和返回表達(dá)式值(x.age)的類型。參數(shù)可具有類型customer, 這對(duì)于age (年齡)返回整型類型?;蛘?,參數(shù)可以是對(duì)age返回string (串)類 型的wine類型。然而,類型可從上下文中推導(dǎo)??紤]以下聲明delegate R Func <A, R> (A arg) Func<Customer, bool> f 二 |x| x.age < 35;指定了取A并返回R的委托類型。拉姆達(dá)表達(dá)式然后被賦值給委托函數(shù)。從這一 附加的上下文信息中,可推導(dǎo)類型?;诶愤_(dá)表達(dá)式對(duì)函數(shù)的賦值,推導(dǎo)組件 420可確定自變量S必須為Customer。推導(dǎo)組件420然后可推導(dǎo)參數(shù)x是Customer 類型。從這一信息中,可確定x.age為來(lái)自Customer類或?qū)ο蠖x的整型類型。隨 后,例如經(jīng)由驗(yàn)證組件422通過(guò)比較返回類型來(lái)驗(yàn)證類型推導(dǎo)。此處,委托函數(shù)Func返回布爾類型(bool),并且拉姆達(dá)表達(dá)式通過(guò)年齡是否小于35的判斷來(lái)返 回布爾類型。因此,推導(dǎo)組件能夠基于上下文成功地推導(dǎo)與拉姆達(dá)表達(dá)式相關(guān)聯(lián)的 類型。實(shí)際上,拉姆達(dá)表達(dá)式向委托函數(shù)的賦值允許將上下文和類型信息下壓到拉 姆達(dá)表達(dá)式。為便于涉及拉姆達(dá)表達(dá)式的類型推導(dǎo)的清楚和理解,將描述另一示例性情形。 考慮以下0#中的類定義Namespace System.Querypublic static class Sequencepublic static IEnumerable<S〉 Sdect<T,S>(this IEnumerable<T> source, Func<T, S> selector)foreach (T element in source) yield return selector (element);假定例如用using子句導(dǎo)入了 System.Query名字空間,并給出了具有類型為string 的Name (名字)屬性的類Customer,則可采用Select (選擇)方法來(lái)從顧客列表 中選擇名字。例如List<Customer> customers = GetCustomerList(); IEnumerable<string> names 二 customers.Select(|c| c.Name);對(duì)Select的擴(kuò)展方法調(diào)用可通過(guò)將該調(diào)用重寫為靜態(tài)方法調(diào)用來(lái)處理IEnumerable<string> names = Sequence.Select(customers, |c| c.Name);可利用類型推導(dǎo)來(lái)推導(dǎo)自變量的類型。上下文信息揭示customers自變量與source (源)參數(shù)有關(guān),因此T可被推導(dǎo)為Customer。隨后,c可被給予類型Customer, 并且表達(dá)式c.Name與selector(選擇器)參數(shù)的返回類型有關(guān),從而推導(dǎo)S為string。 由此,調(diào)用等效于Sequence.Select<Customer, string> (customers, |Customer c| c.Name)并且結(jié)果為IEnumerable〈string〉類型。以下示例示出了拉姆達(dá)類型推導(dǎo)如何允許類型信息在泛型方法調(diào)用中的自變 量之間"流動(dòng)"。假定以下方法及其調(diào)用Static Z F<X, Y, X>(X value, Func〈X, Y> fl, Func<Y, Z> f2 { return f2(fl (value));double seconds = F("l: 15:30", |s| TimeSpan.Parse(s), |t| t.TotalSeconds);對(duì)于調(diào)用的類型推導(dǎo)首先以與value (值)參數(shù)有關(guān)的自變量"1:15:30"開始進(jìn)行。 由此,X可基于該自變量被推導(dǎo)為string。接著,對(duì)第一拉姆達(dá)表達(dá)式的參數(shù)s給 予推導(dǎo)的類型string。表達(dá)式TimeSpan.Parse(s)與fl的返回類型(Y)有關(guān),因此 這可被推導(dǎo)為System.TimeSpan。最后,第二拉姆達(dá)表達(dá)式的參數(shù)t被給予推導(dǎo)的 類型System.TimeSpan,并且表達(dá)式t.TotalSeconds與f2的返回類型有關(guān),從而使 得Z被推導(dǎo)為基于System.TimeSpan類的double (雙精度)類型(未示出)。因此, 該調(diào)用的結(jié)果為double類型。轉(zhuǎn)向圖5,示出了支持對(duì)拉姆達(dá)表達(dá)式進(jìn)行類型檢查的類型檢査系統(tǒng)500。類 似于圖4的系統(tǒng)400,系統(tǒng)500可形成編譯器的一部分。類型檢查系統(tǒng)500包括上 下文組件410、推導(dǎo)組件420以及類型檢查組件510。上下文組件410獲得或標(biāo)識(shí) 拉姆達(dá)表達(dá)式并例如從包括該拉姆達(dá)表達(dá)式的程序中檢索與拉姆達(dá)表達(dá)式有關(guān)的 上下文信息。這一上下文信息可以是與拉姆達(dá)表達(dá)式直接或間接相關(guān)聯(lián)的任何語(yǔ) 句、表達(dá)式、類、類型等。推導(dǎo)組件420接收該上下文信息以及要檢查的拉姆達(dá)表 達(dá)式。推導(dǎo)組件420可利用由上下文組件410提供的上下文信息以及推導(dǎo)集430 中的其它推導(dǎo)來(lái)推導(dǎo)例如拉姆達(dá)表達(dá)式參數(shù)、表達(dá)式、其元素和/或返回類型的類 型。盡管出于減少冗余度的目的,類型可從拉姆達(dá)表達(dá)式中省略,但這些類型也可 被顯式地聲明。在這一情形中,類型檢查組件510可將預(yù)期的或推導(dǎo)的類型與該顯 式類型進(jìn)行比較以確定它們是否匹配。更具體地,類型檢查組件510可從推導(dǎo)組件 420接收所推導(dǎo)的類型。此外,顯式類型可從提供給類型檢查組件510或與所推導(dǎo) 的類型一起傳遞的拉姆達(dá)表達(dá)式中獲得。類型檢查組件510可將該顯式類型和推導(dǎo) 的類型進(jìn)行比較。如果類型匹配,則不需要采取任何動(dòng)作?;蛘?,如果類型不匹配, 則類型組件可生成標(biāo)出這一事實(shí)的錯(cuò)誤或異常。圖6示出了重載解決系統(tǒng)600。系統(tǒng)600可包括上下文組件410、推導(dǎo)組件420、 以及選擇組件610。例如,自變量中的拉姆達(dá)表達(dá)式在某些情況下可影響重載解決。
上下文組件410可接收、檢索或以其它方式獲得與拉姆達(dá)表達(dá)式有關(guān)的上下文信 息。該上下文信息可被發(fā)送到推導(dǎo)組件420。推導(dǎo)組件420可利用上下文信息以及 一個(gè)或多個(gè)以往的推導(dǎo)430 (推導(dǎo)集)來(lái)推導(dǎo)例如與拉姆達(dá)表達(dá)式相關(guān)聯(lián)的類型。這些推導(dǎo)的類型然后可被傳遞給選擇組件610。選擇組件610可采用該信息以在一方法被重載時(shí)來(lái)確定或選擇該方法或委托類型。隨后可將拉姆達(dá)表達(dá)式轉(zhuǎn)換成例如 特定的委托類型。選擇組件610可采用各種過(guò)程或協(xié)議來(lái)選擇重載的方法或委托類型。例如, 給定拉姆達(dá)表達(dá)式L,如果委托類型Dl和委托類型D2具有相同的參數(shù)列表并且 從L的返回類型到Dl的返回類型的隱式轉(zhuǎn)換是比從L的返回類型到D2的返回類 型的隱式轉(zhuǎn)換更好的轉(zhuǎn)換,則將L隱式轉(zhuǎn)換成委托類型Dl是比將L隱式轉(zhuǎn)換成委 托類型D2更好的轉(zhuǎn)換。如果這些條件不為真,則沒(méi)有一個(gè)轉(zhuǎn)換是更好的。當(dāng)然, 反之亦然??紤]以下示例class ItemList<T>: List<T〉public int Sum<T>(Func<T, int〉 selector) { int sum = 0;foreach (T item in this) sum +=selector(item); return sum;public double Sum<T> (Func<T, double> selector^ double sum = 0;foreach (T item in this) sum +=selector(item); return sum;ItemLisKT〉類具有兩個(gè)Sum (求和)方法。每一方法取selector (選擇器)自變量, 該自變量從列表項(xiàng)中提取值來(lái)相加。所提取的值可以或者是整型或者是雙精度的, 并且所得的和同樣或者是整型或者是雙精度的。Sum方法可用于從訂單(order) 的細(xì)節(jié)(detail)行列表中計(jì)算和,例如class Detailpublic int UnitCount; public int double UnitPrice} void ComputeSum()(ItemList<Detail> orderDetails = GetOrderDetails(...);int totalUnits = orderDetails.Sum(|d| d.UnitCount);double orderTotal = orderDetails.Sum(|d| d,UnitPrice * d.UnitCount);}..在orderDetails.Sum的第一個(gè)調(diào)用中,兩個(gè)Sum方法都適用,因?yàn)槔愤_(dá)表達(dá)式|(1| d.UnitCount與Function〈Detail, int〉和Function<Detail, double〉都兼容。然而, 通過(guò)選擇組件610的重載解決選取第一個(gè)Sum方法,因?yàn)榈紽unction<Detail, int> 的轉(zhuǎn)換要比到FunctioiKDetail,double〉的轉(zhuǎn)換好。具體地,UnitCount是整型類型 在 orderDetails.Sum 的第二個(gè)調(diào)用 中 , 僅第二個(gè)Sum方法適用,因?yàn)槔愤_(dá)表 達(dá)式ldld.UnitPrice + d.UnitCount產(chǎn)生類型為雙精度的值。由此,選擇組件610將對(duì) 該調(diào)用選取第二個(gè)Sum方法。上述系統(tǒng)已相對(duì)于若干組件之間的交互來(lái)描述。應(yīng)當(dāng)理解,這些系統(tǒng)和組件 可包括其中指定的那些組件或子組件、所指定的組件或子組件中的某一些、和/或 另外的組件。例如,系統(tǒng)可包括上下文組件410、推導(dǎo)組件420、類型檢査器組件 510以及選擇組件610或其組合。子組件也可被實(shí)現(xiàn)為通信上耦合到其它組件而非 包括在父組件內(nèi)的組件。另外,應(yīng)當(dāng)注意, 一個(gè)或多個(gè)組件可被組合成提供聚集功 能的單個(gè)組件或被劃分成若干子組件。組件也可與此處未具體描述但本領(lǐng)域的技術(shù) 人員已知的一個(gè)或多個(gè)其它組件交互。此外,如將理解的,以上公開的系統(tǒng)和以下的方法的各部分可包括人工智能 或基于知識(shí)或規(guī)則的組件、子組件、進(jìn)程、裝置、方法或機(jī)制(例如,支持向量機(jī)、 神經(jīng)網(wǎng)絡(luò)、專家系統(tǒng)、貝葉斯信任網(wǎng)絡(luò)、模糊邏輯、數(shù)據(jù)融合引擎、分類器……) 或由其組成。這些組件及其它組件可自動(dòng)化所執(zhí)行的某些機(jī)制或進(jìn)程,以使得系統(tǒng) 和方法的各部分更適應(yīng)以及更高效和智能。例如,推導(dǎo)組件420可利用人工智能、 機(jī)器學(xué)習(xí)或類似的機(jī)制來(lái)便于類型推導(dǎo)。除此之外或作為替代,選擇組件610可采 用這些智能機(jī)制來(lái)便于重載解決。鑒于以上描述的示例性系統(tǒng),將參考圖7-12的流程圖來(lái)更好地理解可根據(jù)所 公開的主題實(shí)現(xiàn)的方法。盡管出于解釋簡(jiǎn)明的目的,方法被示出并描述為一系列框, 但是可以理解和明白,所要求保護(hù)的主題不受框的順序的限制,因?yàn)楦鶕?jù)此處所描 繪和描述的,某些框可以按不同的順序和/或與其它框同時(shí)發(fā)生。此外,并非所有 示出的框都是實(shí)現(xiàn)以下描述的方法所必需的。另外,還應(yīng)當(dāng)理解,以下以及在全部說(shuō)明書中公開的方法能夠被儲(chǔ)存在一制 品上以便于將這些方法運(yùn)送和傳輸?shù)接?jì)算機(jī)。如此處所適用的術(shù)語(yǔ)制品旨在涵蓋可 從任何計(jì)算機(jī)可讀設(shè)備、載體或介質(zhì)訪問(wèn)的計(jì)算機(jī)程序。轉(zhuǎn)向圖7,描繪了拉姆達(dá)表達(dá)式執(zhí)行方法700。在參考標(biāo)號(hào)710處,接收、檢 索或標(biāo)識(shí)拉姆達(dá)表達(dá)式。拉姆達(dá)表達(dá)式可包括零個(gè)或多個(gè)參數(shù)以及表達(dá)式或表達(dá)式 主體。參數(shù)可用多種方式從表達(dá)式定界。例如,拉姆達(dá)表達(dá)式參數(shù)可被包含在兩條豎線、圓括號(hào)內(nèi),或通過(guò)利用雙箭頭等與表達(dá)式主體分離。作為示例,拉姆達(dá)表達(dá) 式可采用"|x|x+l" 、 "(x,y)x+l"或"X=>X+1"的形式。此外,可不同地,例如 使用"||="來(lái)指定沒(méi)有參數(shù)的拉姆達(dá)表達(dá)式,以將其與條件or "II"清楚地區(qū)分。 在720處,計(jì)算拉姆達(dá)表達(dá)式的值,即對(duì)其求值。這一值可以是包括但不限于整型、 布爾和串的任何類型。在730處,返回所計(jì)算的值。例如,如果拉姆達(dá)表達(dá)式被指 定為自變量,則它可被返回到作出調(diào)用的語(yǔ)句或方法。或者,如果拉姆達(dá)表達(dá)式被 賦值給諸如委托等函數(shù),則所計(jì)算的值可被返回到該函數(shù)。圖8示出了與拉姆達(dá)表達(dá)式相關(guān)聯(lián)的編程方法800的流程圖。在參考標(biāo)號(hào)810 處,指定拉姆達(dá)表達(dá)式。作為示例,拉姆達(dá)表達(dá)式可用代碼編輯器和/或集成開發(fā) 環(huán)境來(lái)手動(dòng)、自動(dòng)或半自動(dòng)指定。拉姆達(dá)表達(dá)式可如上所述包括零個(gè)或多個(gè)參數(shù)以 及表達(dá)式或表達(dá)式主體。拉姆達(dá)表達(dá)式可利用一個(gè)或多個(gè)符號(hào)來(lái)將參數(shù)從表達(dá)式定 界的任何數(shù)目的方式來(lái)指定。例如,拉姆達(dá)表達(dá)式可被表示為"|c| cage" 、 "c =>C.age"或"(c)c.age"。此外,拉姆達(dá)表達(dá)式可在計(jì)算機(jī)可執(zhí)行程序內(nèi)被指定為 自變量或賦值給函數(shù)等等。在標(biāo)號(hào)820處,將包括拉姆達(dá)表達(dá)式的程序提供給編譯 器以供編譯。從源代碼中,編譯器可產(chǎn)生機(jī)器可執(zhí)行代碼或可在運(yùn)行時(shí)例如由運(yùn)行 時(shí)(JIT)編譯器進(jìn)一步編譯的某種中間代碼。在830處,由計(jì)算機(jī)執(zhí)行由編譯器 生成的代碼。圖9描繪了拉姆達(dá)表達(dá)式轉(zhuǎn)換的方法900。類似于匿名方法表達(dá)式,拉姆達(dá)表 達(dá)式可被分類為具有特殊轉(zhuǎn)換規(guī)則的值。該值沒(méi)有類型,但可被轉(zhuǎn)換成諸如委托類 型等其它兼容類型。在參考標(biāo)號(hào)901處,接收、檢索或以其它方式獲得或標(biāo)識(shí)拉姆 達(dá)表達(dá)式。本實(shí)例中所接收的拉姆達(dá)表達(dá)式將被賦值給一特定類型。例如delegate R Func<A,R>(A arg); Func<int, int〉 f叫xl x + 1;此處,該拉姆達(dá)表達(dá)式被賦值給一委托類型函數(shù)。在920處,確定該拉姆達(dá) 表達(dá)式是否兼容或可被轉(zhuǎn)換成它被賦值到的類型?;谒x值的類型,可能有需要 驗(yàn)證的若干條件。例如,為確定委托類型D是否與拉姆達(dá)表達(dá)式L兼容,可驗(yàn)證 以下條件(1) D具有非空返回類型以及無(wú)引用或傳出參數(shù);(2) D和L具有 相同個(gè)數(shù)的參數(shù),且如果L具有顯式類型化參數(shù)列表,則D中的每一參數(shù)的類型 必須與L中相應(yīng)參數(shù)的類型相同;以及(3)當(dāng)每一參數(shù)L被給予D中相應(yīng)參數(shù)的 類型時(shí),L的表達(dá)式主體是可隱式轉(zhuǎn)換成D的返回類型的有效表達(dá)式。如果在920處不滿足兼容性條件,則在930處,生成錯(cuò)誤或異常以指示將拉姆達(dá)表達(dá)式轉(zhuǎn)換成不兼容類型的嘗試。如果在920處滿足條件,則允許該轉(zhuǎn)換,并且在940處轉(zhuǎn)換該 拉姆達(dá)表達(dá)式。在以上示例中,該拉姆達(dá)表達(dá)式被成功轉(zhuǎn)換成委托類型Func<int, int>,因?yàn)楫?dāng)x被給予類型int時(shí),x+l是可被隱式轉(zhuǎn)換成類型int的有效表達(dá)式。這一賦值等效于使用匿名方法的更冗長(zhǎng)形式 Func〈int, int〉 f = delegate(int x) {return x + 1};圖IO是用于拉姆達(dá)表達(dá)式的類型推導(dǎo)方法1000。在標(biāo)號(hào)1010處,在程序內(nèi) 標(biāo)識(shí)拉姆達(dá)表達(dá)式。在1020處,獲得直接或間接與該拉姆達(dá)表達(dá)式有關(guān)的上下文 信息。這一上下文信息可包括類、對(duì)象、函數(shù)、方法和類型等等。例如,如果一拉 姆達(dá)表達(dá)式被賦值給一函數(shù),則該函數(shù)提供了上下文信息。如果該拉姆達(dá)表達(dá)式是 方法自變量,則該方法提供了上下文信息。在參考標(biāo)號(hào)1030處,推導(dǎo)與該拉姆達(dá) 表達(dá)式相關(guān)聯(lián)的類型。例如,拉姆達(dá)表達(dá)式參數(shù)可基于所獲得的上下文信息來(lái)推導(dǎo)。 拉姆達(dá)表達(dá)式主體元素和/或返回類型可基于先前的推導(dǎo)和上下文信息來(lái)確定。作 為示例,考慮作為自變量傳遞給泛型方法的拉姆達(dá)表達(dá)式。類型推導(dǎo)首先可獨(dú)立于 每一自變量進(jìn)行。在這一初始階段,從作為拉姆達(dá)表達(dá)式的自變量中沒(méi)有推導(dǎo)出任 何內(nèi)容。然而,在初始階段之后,可使用迭代過(guò)程從拉姆達(dá)表達(dá)式中作出附加推導(dǎo)。 特別地,可利用來(lái)自初始階段的上下文信息來(lái)便于與方法的返回類型以及類型推 導(dǎo)。這一過(guò)程可被重復(fù),直到無(wú)法作出進(jìn)一步的推導(dǎo)。圖11描繪了一示例性類型推導(dǎo)方法1100,以進(jìn)一步理解拉姆達(dá)表達(dá)式可如何 參與類型推導(dǎo)過(guò)程。方法IIOO涉及對(duì)拉姆達(dá)表達(dá)式作為方法自變量的使用。應(yīng)當(dāng) 理解,方法IIOO也可被修改成處理拉姆達(dá)表達(dá)式賦值及其其它使用。在參考標(biāo)號(hào) lllO處,在必要時(shí)對(duì)方法和非拉姆達(dá)表達(dá)式自變量推導(dǎo)類型。在1120處,將一拉 姆達(dá)表達(dá)式標(biāo)識(shí)為方法自變量。隨后,在1130處,推導(dǎo)諸如參數(shù)和表達(dá)式元素類 型等拉姆達(dá)表達(dá)式類型。推導(dǎo)可基于例如當(dāng)前的推導(dǎo)集,包括與相關(guān)聯(lián)的或作出調(diào) 用的方法和/或其其它自變量有關(guān)的那些推導(dǎo)。在1140處,進(jìn)行檢查以確定方法參 數(shù)返回類型是否與拉姆達(dá)表達(dá)式的返回類型相同。如果不是,則可能存在錯(cuò)誤代碼 指定或推導(dǎo)。因此,可在1150處生成錯(cuò)誤并且該方法終止。如果返回類型相同, 則該方法可前進(jìn)到1160,在那里確定是否存在從中不能作出任何推導(dǎo)的任何其它 拉姆達(dá)表達(dá)式。如果有,則在1120處標(biāo)識(shí)它們,并且該方法從那里繼續(xù)。如果沒(méi) 有其它拉姆達(dá)表達(dá)式,則該方法終止。作為示例,考慮以下代碼摘錄中的Select擴(kuò)展方法Namespace System.Querypublic static class Sequencepublic static IEnumerable<S> Select<T,S>(this IEnumerable<T> source, Func<T,S> selector){ 一 一foreach (source中的T元素)產(chǎn)生返回selector (元素);Select方法可用于通過(guò)以下代碼選擇一顧客列表List<Customer> customers = GetCustomerList(); IEnumerable<string〉 names = customers.Select(|c| c.Name);該對(duì)Select的擴(kuò)展方法調(diào)用可通過(guò)將該調(diào)用重寫(例如,由編譯器)為諸如以下的 靜態(tài)方法調(diào)用來(lái)處理IEnumerable<string> names = Sequence.Select(customers, |c| c.Name);由于以上代碼摘錄的類型自變量不是顯式指定的,因此它們可被推導(dǎo)。由于存在非拉姆達(dá)表達(dá)式自變量"customers",因此該類型可被首先推導(dǎo)。此處"customers" 與source參數(shù)有關(guān),并且為T類型。從該特定調(diào)用中,T可被推導(dǎo)為Customer類 型。拉姆達(dá)表達(dá)式參數(shù)c和表達(dá)式主體c.Name與Select方法的selector參數(shù)有關(guān)。 拉姆達(dá)表達(dá)式參數(shù)c對(duì)應(yīng)于類型T, T已被推導(dǎo)為類型Customer,因此c是Customer 類型。表達(dá)式主體c.Name對(duì)應(yīng)于參數(shù)S, S可被推導(dǎo)為具有類型string。從Customer 類型中,可發(fā)現(xiàn)類c.Name是諸如string的特定類型。由此,拉姆達(dá)表達(dá)式主體和 方法參數(shù)返回類型都可以是string類型。因此,類型推導(dǎo)成功完成。本調(diào)用等效于 以下顯式類型化的方法調(diào)用Sequence.SelecKCustomer, string>(customers, |Customer c| c.Name);本示例示出了如何確定類型信息以及它如何從作出調(diào)用的方法及其非拉姆達(dá) 表達(dá)式自變量流入拉姆達(dá)表達(dá)式。轉(zhuǎn)向圖12,提供了描繪重載解決方法1200的流程圖。更具體地,方法1200 例如示出了拉姆達(dá)表達(dá)式如何參與解決重載方法。在參考標(biāo)號(hào)1210處,將拉姆達(dá) 表達(dá)式標(biāo)識(shí)為例如方法自變量。在1220處,例如通過(guò)基于一推導(dǎo)集的推導(dǎo)來(lái)確定拉姆達(dá)表達(dá)式的返回類型。最后,在1230處,基于拉姆達(dá)表達(dá)式的返回類型選擇一特定重載方法。作為示例,考慮以下包括返回不同結(jié)果的兩個(gè)Sum函數(shù)的類Class List<T>int Sum (Func<T, int> f) {…} double Sum (Func<T, double〉 f{...}此處,Sum被重載?,F(xiàn)在假定指定了以下代碼-List<Product> ps ps.Sum (|p| p.Price)為確定要調(diào)用哪一 Sum并解決重載,必須確定拉姆達(dá)表達(dá)式的返回類型。此處, 指示ps是LisKProducP"類型。從這點(diǎn)中,可推導(dǎo)p是Product (產(chǎn)品)類型。然后, 基于Product類定義,可確定p.Price的類型。對(duì)該示例假定該定義揭示了 p.Price 是雙精度(double)類型。現(xiàn)在已知指定的代碼取Product并返回雙精度。因此, 該代碼是Func<Product, (101^16〉類型。從這一知識(shí)中,可選擇第二個(gè)Sum。如果 Product類定義揭示p.Price是整型(int)類型,則該代碼將是Func<Product, inP類 型。在這一情形中,盡管整型類型可被轉(zhuǎn)換成雙精度,但是選擇第一個(gè)Sum函數(shù), 因?yàn)樗歉玫钠ヅ?。如可從這一示例中理解的,不必首先選擇函數(shù)之一 (例如, 如對(duì)結(jié)構(gòu)類型化所做的),因?yàn)榛诶愤_(dá)表達(dá)式返回類型,可選擇正確的方法或 函數(shù)。圖13是描繪可用于產(chǎn)生實(shí)現(xiàn)代碼(例如,可執(zhí)行代碼、中間語(yǔ)言……)的編 譯器環(huán)境1300的框圖。編譯器環(huán)境1300包括編譯器220,它包括前端組件1320、 轉(zhuǎn)換器組件1330、后端組件1340、錯(cuò)誤檢查器組件1350、符號(hào)表1360、解析樹 1370以及狀態(tài)1380。編譯器220接受源代碼作為輸入,并產(chǎn)生實(shí)現(xiàn)代碼作為輸出。 輸入可包括但不限于如此處所描述的定界的程序性表達(dá)式或限定標(biāo)識(shí)符。編譯器環(huán) 境的組件和模塊之間的關(guān)系示出了主要數(shù)據(jù)流。出于清楚和簡(jiǎn)明的目的未示出其它 組件和關(guān)系。取決于實(shí)現(xiàn),組件可被添加、省略、拆分成多個(gè)模塊、與其它模塊組 合、和/或模塊的其它配置。編譯器220可接受具有與一元素序列的處理相關(guān)聯(lián)的源代碼的文件作為輸入。 源代碼可包括拉姆達(dá)表達(dá)式和相關(guān)聯(lián)的函數(shù)、方法和/或其它程序性構(gòu)造。編譯器 220可結(jié)合用于分析構(gòu)造和生成或注入代碼的一個(gè)或多個(gè)組件來(lái)處理源代碼。前端組件1320讀取源代碼并對(duì)其執(zhí)行詞法分析。本質(zhì)上,前端組件1320讀取源代碼中的一字符序列(例如,字母數(shù)字)并將其轉(zhuǎn)換成指示常量、標(biāo)識(shí)符、運(yùn) 算符號(hào)、關(guān)鍵字和標(biāo)點(diǎn)符號(hào)等句法元素或語(yǔ)言符號(hào)。轉(zhuǎn)換器組件1330將語(yǔ)言符號(hào)解析成中間表示。例如,轉(zhuǎn)換器組件1330可檢 査語(yǔ)言符號(hào)的句法并將其歸組為表達(dá)式或其它句法結(jié)構(gòu),后者進(jìn)而被接合成語(yǔ)句 樹。概念上,這些樹形成了一解析樹1370。此外,在適當(dāng)時(shí),轉(zhuǎn)換器模塊1330可 將列出源代碼中使用的符號(hào)名和類型信息以及相關(guān)特性的條目放置到符號(hào)表1330 中。狀態(tài)1380可用于編譯器1310在處理所接收或檢索到的源代碼并形成解析樹 1370的進(jìn)度。例如,不同的狀態(tài)值指示編譯器1310處于類定義或函數(shù)的開始、剛 聲明了類成員、或已完成了表達(dá)式的狀態(tài)中。當(dāng)編譯器進(jìn)展時(shí),它不斷地更新?tīng)顟B(tài) 1380。編譯器220可部分或完全將狀態(tài)1380展示給外部實(shí)體,后者然后向編譯器 220提供輸入?;谠创a中的構(gòu)造或其它信號(hào)(或如果有機(jī)會(huì)另外識(shí)別),轉(zhuǎn)換器組件1330 或另一組件可注入對(duì)應(yīng)的代碼以便于高效且正確的執(zhí)行。被編碼到轉(zhuǎn)換器組件 1330或其它組件的規(guī)則指示必須要完成什么來(lái)實(shí)現(xiàn)所需功能,并標(biāo)識(shí)將注入代碼 或要執(zhí)行其它操作的位置。注入的代碼通常包括一個(gè)或多個(gè)位置處添加的語(yǔ)句、元 數(shù)據(jù)或其它元素,但是該術(shù)語(yǔ)也可包括改變、刪除或以其它方式修改現(xiàn)有的源代碼。 注入的代碼可被儲(chǔ)存在一個(gè)或多個(gè)模板或以某一其它形式儲(chǔ)存。另外,應(yīng)當(dāng)理解, 可進(jìn)行符號(hào)表操縱和解析樹變換。基于符號(hào)表1360和解析樹1370,后端組件1340可將中間表示轉(zhuǎn)換成輸出代 碼。后端組件1340將中間表示轉(zhuǎn)換成可在目標(biāo)處理器中執(zhí)行或可由其執(zhí)行的指令、 對(duì)變量的存儲(chǔ)器分配等等。輸出代碼可由真實(shí)處理器來(lái)執(zhí)行,但是本發(fā)明也構(gòu)想了 可由虛擬處理器執(zhí)行的輸出代碼。此外,前端組件1320和后端組件1340可執(zhí)行諸如代碼優(yōu)化等另外的功能, 并且可將所描述的操作作為單個(gè)階段或在多個(gè)階段中執(zhí)行。編譯器220的組件的各 個(gè)其它方面本質(zhì)上是常規(guī)的,并且可用執(zhí)行等效功能的組件來(lái)替代。另外,在處理 源代碼期間的各個(gè)階段,錯(cuò)誤檢査器組件1350可檢查諸如詞法結(jié)構(gòu)中的錯(cuò)誤、句 法錯(cuò)誤甚至是語(yǔ)義錯(cuò)誤等錯(cuò)誤。在檢測(cè)到錯(cuò)誤時(shí),檢査器組件1350可中止編譯并 生成指示錯(cuò)誤的消息。為了對(duì)所公開的主題的各方面提供上下文,圖14和15以及以下討論旨在提供其中可實(shí)現(xiàn)所公開的主題的各方面的合適的環(huán)境的簡(jiǎn)要概括描述。盡管以上在運(yùn)行于一臺(tái)計(jì)算機(jī)和/或多臺(tái)計(jì)算機(jī)上的計(jì)算機(jī)程序的計(jì)算機(jī)可執(zhí)行指令的一般上下 文中描述了本主題,但是本領(lǐng)域的技術(shù)人員將認(rèn)識(shí)到本發(fā)明也可結(jié)合其它程序模塊 來(lái)實(shí)現(xiàn)。 一般而言,程序模塊包括執(zhí)行特定任務(wù)和/或?qū)崿F(xiàn)特定抽象數(shù)據(jù)類型的例 程、程序、組件、數(shù)據(jù)結(jié)構(gòu)等。此外,本領(lǐng)域的技術(shù)人員可以理解,本發(fā)明可用其 它計(jì)算機(jī)系統(tǒng)配置來(lái)實(shí)施,包括單處理器或多處理器計(jì)算機(jī)系統(tǒng)、小型計(jì)算設(shè)備、 大型機(jī)、以及個(gè)人計(jì)算機(jī)、手持式計(jì)算設(shè)備(例如,個(gè)人數(shù)字助理(PDA)、電話、 手表……)、基于微處理器或可編程消費(fèi)或工業(yè)電子產(chǎn)品等等。所示的各方面也可 在其中任務(wù)由通過(guò)通信網(wǎng)絡(luò)鏈接的遠(yuǎn)程處理設(shè)備來(lái)執(zhí)行的分布式計(jì)算環(huán)境中實(shí)施。 然而,本發(fā)明的某些(如果不是全部)方面可在獨(dú)立計(jì)算機(jī)上實(shí)施。在分布式計(jì)算 環(huán)境中,程序模塊可以位于本地和遠(yuǎn)程存儲(chǔ)器存儲(chǔ)設(shè)備中。參考圖14,用于實(shí)現(xiàn)此處所公開的各方面的示例性環(huán)境1410包括計(jì)算機(jī)1412 (例如,臺(tái)式機(jī)、膝上型計(jì)算機(jī)、服務(wù)器、手持式設(shè)備、可編程消費(fèi)或工業(yè)電子產(chǎn) 品……)。計(jì)算機(jī)1412包括處理單元1414、系統(tǒng)存儲(chǔ)器1416和系統(tǒng)總線1418。 系統(tǒng)總線1418將包括但不限于系統(tǒng)存儲(chǔ)器1416的系統(tǒng)組件耦合至處理單元1414。 處理單元1414可以是各種可用處理器的任一種。雙微處理器和其它多處理器體系 結(jié)構(gòu)也可用作處理單元1414。系統(tǒng)總線1418可以是若干種總線結(jié)構(gòu)類型的任一種,包括存儲(chǔ)器總線或存儲(chǔ) 器控制器、外圍總線或外部總線、和/或使用任意各類可用總線體系結(jié)構(gòu)的局部總 線,這些體系結(jié)構(gòu)包括但不限于,ll位總線、工業(yè)標(biāo)準(zhǔn)體系結(jié)構(gòu)(ISA)、微通道 體系結(jié)構(gòu)(MCA)、擴(kuò)展ISA (EISA)、智能驅(qū)動(dòng)電子設(shè)備(IDE) 、 VESA局部 總線(VLB)、外圍部件互連(PCI),通用串行總線(USB)、高級(jí)圖形端口 (AGP)、 個(gè)人計(jì)算機(jī)存儲(chǔ)卡國(guó)際協(xié)會(huì)總線(PCMCIA)以及小型計(jì)算機(jī)系統(tǒng)接口 (SCSI)。系統(tǒng)存儲(chǔ)器1416包括易失性存儲(chǔ)器1420和非易失性存儲(chǔ)器1422。基本輸入/ 輸出系統(tǒng)(BIOS)包括如在啟動(dòng)時(shí)幫助在計(jì)算機(jī)1412內(nèi)的元件之間傳輸信息的基 本例程,通常儲(chǔ)存在非易失性存儲(chǔ)器1422中。作為說(shuō)明而非局限,非易失性存儲(chǔ) 器1422可包括只讀存儲(chǔ)器(ROM)、可編程ROM (PROM)、電可編程ROM (EPROM)、電可擦除ROM (EEPROM)或閃存。易失性存儲(chǔ)器1420包括擔(dān)當(dāng) 外部高速緩沖存儲(chǔ)器的隨機(jī)存取存儲(chǔ)器(RAM)。作為說(shuō)明而非局限,RAM以許 多形式可用,如同步RAM(SRAM)、動(dòng)態(tài)RAM(DRAM)、同步DRAM( SDRAM)、 雙數(shù)據(jù)率SDRAM(DDR SDRAM)、增強(qiáng)SDRAM(ESDRAM)、同步鏈路(Synchlink)DRAM (SLDRAM)和直接存儲(chǔ)器總線(Rambus) RAM (DRRAM)。計(jì)算機(jī)1412也包括可移動(dòng)/不可移動(dòng)、易失性/非易失性計(jì)算機(jī)存儲(chǔ)介質(zhì)。例 如,圖14示出了盤存儲(chǔ)1424。盤存儲(chǔ)1424包括但不限于,諸如磁盤驅(qū)動(dòng)器、軟 盤驅(qū)動(dòng)器、磁帶驅(qū)動(dòng)器、Jaz驅(qū)動(dòng)器、Zip驅(qū)動(dòng)器、LS-100驅(qū)動(dòng)器、閃存卡或記憶 棒等設(shè)備。另外,盤存儲(chǔ)1424可單獨(dú)包括存儲(chǔ)介質(zhì)或與其它存儲(chǔ)介質(zhì)組合,其它 存儲(chǔ)介質(zhì)包括但不限于,諸如緊致盤ROM設(shè)備(CD-ROM) 、 CD可記錄驅(qū)動(dòng)器 (CD-R驅(qū)動(dòng)器)、CD可重寫驅(qū)動(dòng)器(CD-RW驅(qū)動(dòng)器)或數(shù)字多功能盤ROM驅(qū) 動(dòng)器(DVD-ROM)等光盤驅(qū)動(dòng)器。為便于盤存儲(chǔ)設(shè)備1424連接到系統(tǒng)總線1418, 通常使用可移動(dòng)或不可移動(dòng)接口,如接口 1426。可以理解,圖14描述了擔(dān)當(dāng)用戶和合適的操作環(huán)境1410中描述的基本計(jì)算 機(jī)資源之間的中介的軟件。這類軟件包括操作系統(tǒng)1428。操作系統(tǒng)1428可儲(chǔ)存在 盤存儲(chǔ)1424中,它用于控制并分配計(jì)算機(jī)系統(tǒng)1412的資源。系統(tǒng)應(yīng)用程序1430 利用操作系統(tǒng)1428通過(guò)儲(chǔ)存在系統(tǒng)存儲(chǔ)器1416或盤存儲(chǔ)1424上的程序模塊1432 和程序數(shù)據(jù)1434對(duì)資源的管理。可以理解,本發(fā)明可用各種操作系統(tǒng)或操作系統(tǒng) 的組合來(lái)實(shí)現(xiàn)。用戶通過(guò)輸入設(shè)備1436向計(jì)算機(jī)1412輸入命令或信息。輸入設(shè)備1436包括 但不限于,諸如鼠標(biāo)、跟蹤球、指示筆、觸摸墊等定點(diǎn)設(shè)備、鍵盤、話筒、操縱桿、 游戲墊、圓盤式衛(wèi)星天線、掃描儀、TV調(diào)諧卡、數(shù)碼相機(jī)、數(shù)碼攝像機(jī)、web攝 像頭等等。這些和其它輸入設(shè)備經(jīng)由接口端口 1438通過(guò)系統(tǒng)總線1418連接到處理 單元1414。接口端口 1438包括,例如,串行端口、并行端口、游戲端口和通用串 行總線(USB)。輸出設(shè)備1440使用與輸入設(shè)備1436相同類型端口中的某一些。 由此,例如,USB端口可用于向計(jì)算機(jī)1412提供輸入,并從計(jì)算機(jī)1412輸出信 息到輸出設(shè)備1440。提供了輸出適配器1442以說(shuō)明存在一些輸出設(shè)備1440,如顯 式器(例如,平板和CRT)、揚(yáng)聲器和打印機(jī),以及需要特殊適配器的其它輸出 設(shè)備1440。輸出適配器1442包括,作為說(shuō)明而非局限,提供輸出設(shè)備1440和系 統(tǒng)總線1418之間的連接裝置的顯卡和聲卡。應(yīng)當(dāng)注意,其它設(shè)備和/或設(shè)備的系統(tǒng) 提供了輸入和輸出能力,如遠(yuǎn)程計(jì)算機(jī)1444。計(jì)算機(jī)1412可以使用到一個(gè)或多個(gè)遠(yuǎn)程計(jì)算機(jī),如遠(yuǎn)程計(jì)算機(jī)1444的邏輯 連接在網(wǎng)絡(luò)化環(huán)境中操作。遠(yuǎn)程計(jì)算機(jī)1444可以是個(gè)人計(jì)算機(jī)、服務(wù)器、路由器、 網(wǎng)絡(luò)PC、工作站、基于微處理器的電器、對(duì)等設(shè)備或其它常見(jiàn)的網(wǎng)絡(luò)節(jié)點(diǎn)等等, 并通常包括相對(duì)于計(jì)算機(jī)1412所描述的許多或所有元件。為簡(jiǎn)明起見(jiàn),僅對(duì)遠(yuǎn)程計(jì)算機(jī)1444示出了存儲(chǔ)器存儲(chǔ)設(shè)備1446。遠(yuǎn)程計(jì)算機(jī)1444通過(guò)網(wǎng)絡(luò)接口 1448邏 輯上連接至計(jì)算機(jī)1412,然后通過(guò)通信連接1450物理地連接。網(wǎng)絡(luò)接口 1448包 含諸如局域網(wǎng)(LAN)和廣域網(wǎng)(WAN)等通信網(wǎng)絡(luò)。LAN技術(shù)包括光纖分布式 數(shù)據(jù)接口 (FDDI)、銅纜分布式數(shù)據(jù)接口 (CDDI)、以太網(wǎng)/IEEE 802.3、令牌環(huán) /IEEE 802.5等等。WAN技術(shù)包括但不限于,點(diǎn)對(duì)點(diǎn)鏈路、諸如綜合業(yè)務(wù)數(shù)字網(wǎng) (ISDN)及其變體等電路交換網(wǎng)絡(luò)、分組交換網(wǎng)絡(luò)以及數(shù)字用戶線(DSL)。通信連接1450指用于將網(wǎng)絡(luò)接口 1448連接到總線1418的硬件/軟件。盡管為 說(shuō)明的清晰起見(jiàn),示出通信連接1450在計(jì)算機(jī)1412內(nèi),然而它也可以對(duì)計(jì)算機(jī) 1412是外部的。僅出于示例性的目的,連接到網(wǎng)絡(luò)接口 1448所必需的硬件/軟件包 括內(nèi)部和外部技術(shù),如包括常規(guī)電話級(jí)調(diào)制解調(diào)器、線纜調(diào)制解調(diào)器和DSL調(diào)制 解調(diào)器的調(diào)制解調(diào)器、ISDN適配器和以太網(wǎng)卡或組件。圖15是了本發(fā)明可與其交互的示例計(jì)算環(huán)境1500的示意框圖。系統(tǒng)1500包 括一個(gè)或多個(gè)客戶機(jī)1510??蛻魴C(jī)1510可以是硬件和/或軟件(如,線程、進(jìn)程、 計(jì)算設(shè)備)。系統(tǒng)1500也包括一個(gè)或多個(gè)服務(wù)器1530。因此,系統(tǒng)1500可對(duì)應(yīng) 于兩層客戶機(jī)服務(wù)器模型或多層模型(例如,客戶機(jī)、中間層服務(wù)器、數(shù)據(jù)服務(wù)器) 以及其它模型。服務(wù)器1530也可以是硬件和/或軟件(如,線程、進(jìn)程、計(jì)算設(shè)備)。 例如,服務(wù)器1530可容納線程,以通過(guò)使用本發(fā)明執(zhí)行變換??蛻魴C(jī)1510和服務(wù) 器1530之間的一個(gè)可能的通信可以是適用于在兩個(gè)或多個(gè)計(jì)算機(jī)進(jìn)程之間傳輸?shù)?數(shù)據(jù)分組的形式。系統(tǒng)1500包括可用于促進(jìn)客戶機(jī)1510和服務(wù)器1530之間的通 信的通信框架1550??蛻魴C(jī)1510操作上連接至可用于儲(chǔ)存對(duì)客戶機(jī)1510本地的 信息的一個(gè)或多個(gè)客戶機(jī)數(shù)據(jù)存儲(chǔ)1560。類似地,服務(wù)器1530操作上連接至可用 于儲(chǔ)存對(duì)服務(wù)器1530本地的信息的一個(gè)或多個(gè)服務(wù)器數(shù)據(jù)存儲(chǔ)1540。上文所描述的包括所要求保護(hù)的主題的各方面的示例。當(dāng)然,不可能為了描 述所要求保護(hù)的主題而描述組件或方法的每一可想象的組合,但是本領(lǐng)域的普通技 術(shù)人員可以認(rèn)識(shí)到,所公開的主題的許多另外的組合和置換是可能的。因此,所公 開的主題旨在包含落入所附權(quán)利要求書的精神和范圍中的所有這樣的改變、修改和 變化。此外,就在說(shuō)明書和權(quán)利要求書中使用術(shù)語(yǔ)"包括"、"具有"或"含有" 而言,這類術(shù)語(yǔ)旨在以與術(shù)語(yǔ)"包含"用作權(quán)利要求書中的過(guò)渡詞語(yǔ)所解釋的類似 的方式為包含性的。
權(quán)利要求
1.一種計(jì)算機(jī)程序編譯系統(tǒng),包括獲得與拉姆達(dá)表達(dá)式有關(guān)的上下文信息的上下文組件;以及基于由所述上下文組件提供的上下文信息來(lái)推導(dǎo)與所述拉姆達(dá)表達(dá)式相關(guān)聯(lián)的類型的推導(dǎo)組件。
2. 如權(quán)利要求1所述的系統(tǒng),其特征在于,還包括便于指定包括零個(gè)或多個(gè) 隱式和/或顯式類型化參數(shù)以及主體的拉姆達(dá)表達(dá)式的開發(fā)組件。
3. 如權(quán)利要求2所述的系統(tǒng),其特征在于,所述拉姆達(dá)表達(dá)式采用以下形式 之一l參數(shù)l主體、||=主體、參數(shù)=>主體、(參數(shù))=〉主體、參數(shù)==>主體、以及(參數(shù))==>主體。
4. 如權(quán)利要求3所述的系統(tǒng),其特征在于,所述主體包括表達(dá)式和語(yǔ)句塊之
5. 如權(quán)利要求l所述的系統(tǒng),其特征在于,所述上下文組件從所述拉姆達(dá)表 達(dá)式向其賦值的函數(shù)中檢索上下文信息。
6. 如權(quán)利要求5所述的系統(tǒng),其特征在于,所述推導(dǎo)組件包括將所述函數(shù)的 返回類型與所述拉姆達(dá)表達(dá)式的返回類型進(jìn)行比較以驗(yàn)證所推導(dǎo)的類型的確認(rèn)組 件。
7. 如權(quán)利要求6所述的系統(tǒng),其特征在于,所述函數(shù)是委托類型和泛型委托 類型之一。
8. 如權(quán)利要求5所述的系統(tǒng),其特征在于,所述上下文組件從拉姆達(dá)表達(dá)式 參數(shù)類中檢索上下文信息。
9. 如權(quán)利要求l所述的系統(tǒng),其特征在于,還包括將所推導(dǎo)的類型與一個(gè)或 多個(gè)顯式類型進(jìn)行比較并在所述顯式類型不匹配所推導(dǎo)的類型時(shí)生成錯(cuò)誤的類型 檢查器組件。
10. 如權(quán)利要求1所述的系統(tǒng),其特征在于,還包括在所述拉姆達(dá)表達(dá)式和 一重載方法的參數(shù)相同的情況下基于所述拉姆達(dá)表達(dá)式的返回類型選擇所述方法 的選擇組件。
11. 一種計(jì)算機(jī)實(shí)現(xiàn)的拉姆達(dá)表達(dá)式轉(zhuǎn)換方法,包括 確定一拉姆達(dá)表達(dá)式的電子表示與一委托類型是否兼容;以及如果所述表達(dá)式和所述類型兼容,則將所述拉姆達(dá)表達(dá)式轉(zhuǎn)換成所述委托類 型,否則生成錯(cuò)誤。
12. 如權(quán)利要求ll所述的方法,其特征在于,確定兼容性包括分析所述委托 類型,如果所述委托類型具有空返回類型或者包括引用或傳出參數(shù),則所述拉姆達(dá) 表達(dá)式和所述委托類型不兼容。
13. 如權(quán)利要求12所述的方法,其特征在于,確定兼容性包括分析所述拉姆 達(dá)表達(dá)式和所述委托類型中每一個(gè)的參數(shù),如果所述拉姆達(dá)表達(dá)式和所述委托類型 具有不同數(shù)目的參數(shù)和/或相應(yīng)的參數(shù)是不同類型的,則所述拉姆達(dá)表達(dá)式和所述 委托類型不兼容。
14. 如權(quán)利要求13所述的方法,其特征在于,確定兼容性包括分析與所述拉 姆達(dá)表達(dá)式相關(guān)聯(lián)的表達(dá)式主體,如果所述表達(dá)式主體與所述委托類型的返回類型 是相同類型或者可被轉(zhuǎn)換成所述委托類型的返回類型,則所述拉姆達(dá)表達(dá)式和所述 委托類型兼容。
15. —種其上儲(chǔ)存有用于執(zhí)行如權(quán)利要求11所述的方法的計(jì)算機(jī)可執(zhí)行指令 的計(jì)算機(jī)可讀介質(zhì)。
16. —種計(jì)算機(jī)實(shí)現(xiàn)的重載解決方法,包括 標(biāo)識(shí)一方法自變量中的拉姆達(dá)表達(dá)式; 確定所述拉姆達(dá)表達(dá)式的返回類型;以及 基于所述返回類型選擇所述重載方法之一。
17. 如權(quán)利要求16所述的方法,其特征在于,選擇所述重載方法之一包括選 擇與所述拉姆達(dá)表達(dá)式具有相同返回類型的方法。
18. 如權(quán)利要求16所述的方法,其特征在于,選擇所述重載方法之一包括選 擇具有與所述拉姆達(dá)表達(dá)式的返回類型兼容的返回類型的方法。
19. 如權(quán)利要求16所述的方法,其特征在于,確定所述返回類型包括獲得與 所述拉姆達(dá)表達(dá)式有關(guān)的上下文信息并基于所述上下文信息推導(dǎo)所述返回類型。
20. —種其上儲(chǔ)存有用于執(zhí)行如權(quán)利要求16所述的方法的計(jì)算機(jī)可執(zhí)行指令 的計(jì)算機(jī)可讀介質(zhì)。
全文摘要
本發(fā)明涉及拉姆達(dá)表達(dá)式以及這種表達(dá)式在命令性和/或面向?qū)ο蟮挠?jì)算機(jī)編程語(yǔ)言中的應(yīng)用。拉姆達(dá)表達(dá)式可結(jié)合方法(例如,自變量、賦值……)來(lái)使用以提供更簡(jiǎn)明且功能性的代碼指定方式。此外,拉姆達(dá)表達(dá)式可參與類型推導(dǎo)和檢查以及重載解決等等。
文檔編號(hào)G06F9/45GK101233487SQ200680027768
公開日2008年7月30日 申請(qǐng)日期2006年6月23日 優(yōu)先權(quán)日2005年7月29日
發(fā)明者A·赫杰斯伯格, D·C·庫(kù)爾卡尼, D·F·布克斯, G·S·凱茨澤伯格, H·J·M·梅杰, L·伯洛格納斯, M·J·瓦納, P·A·豪拉姆 申請(qǐng)人:微軟公司