微软推出新逆天开源语言Bosque,告别 for 循环,提高开发效率!
擁抱開(kāi)源的微軟近日又為開(kāi)發(fā)者帶來(lái)好消息:在受 TypeScript 語(yǔ)法類型與 ML 和 Node/JavaScript 語(yǔ)義啟發(fā)下,微軟推出了全新的開(kāi)源編程語(yǔ)言 Bosque。
Bosque?創(chuàng)作者是微軟研究院的計(jì)算機(jī)科學(xué)家 Mark Marron,他設(shè)計(jì)通過(guò)擁抱代數(shù)運(yùn)算和避開(kāi)導(dǎo)致復(fù)雜性的技術(shù),試圖創(chuàng)造出一種簡(jiǎn)單易懂的語(yǔ)言,走出 1970 年代興起的結(jié)構(gòu)化編程模型。如今,Bosque 似乎已經(jīng)實(shí)現(xiàn)了這一點(diǎn),它不再需要“for”、“while”、“do while”等循環(huán),可讓開(kāi)發(fā)者開(kāi)發(fā)效率更高。
與此同時(shí),本文的作者 Erik Pragt 也發(fā)現(xiàn)?Bosque 和 Kotlin 有著諸多的相似之處。
作者 |?Erik Pragt
譯者 | 彎月
責(zé)編 | 屠敏
出品 | CSDN(ID:CSDNnews)
以下為譯文:
昨天,我的一個(gè)同事Sahil發(fā)給我一個(gè)鏈接,鏈接的文章介紹了微軟研究院發(fā)布的新語(yǔ)言Bosque。在讀了這篇文章,看了里面的代碼示例后,我不禁想看看它和Kotlin有多少相似之處。我想通過(guò)這篇文章,分享我使用Bosque語(yǔ)言的短暫經(jīng)驗(yàn),以及它和Kotlin的比較。我不會(huì)深入討論Kotlin和Bosque的生態(tài)系統(tǒng),這篇文章的重點(diǎn)是語(yǔ)言結(jié)構(gòu)和語(yǔ)法本身。
什么是Bosque編程語(yǔ)言?
?
Bosque是微軟研究院發(fā)明的一門(mén)新的編程語(yǔ)言。在我撰寫(xiě)本文的時(shí)候,Bosque語(yǔ)言才剛滿11天!根據(jù)Bosque的GitHub頁(yè)面(https://github.com/Microsoft/BosqueLanguage),Bosque的設(shè)計(jì)目標(biāo)是“編寫(xiě)簡(jiǎn)單、明確且人和機(jī)器都容易理解的代碼”。因此,Bosque吸取了許多概念,例如不可更改性、原子構(gòu)造器、工廠等,還有豐富的類型系統(tǒng)。
Bosque是一門(mén)非常新的的語(yǔ)言,它的語(yǔ)法受到了TypeScript的啟發(fā)。從我的另一篇文章《Kotlin vs TypeScript》(https://www.jworks.io/dart-vs-typescript-vs-kotlin-js/)中,你就可以看出兩者之間有許多相似之處,因此不難想象,Kotlin和Bosque之間也會(huì)有許多共同點(diǎn)。
?
Bosque vs Kotlin:語(yǔ)法
?
Bosque的GitHub頁(yè)面上給出了一小段Bosque代碼示例,這段代碼很好地展示了它與Kotlin之間的相似性:
//?Bosque?
function?add2(x:?Int,?y:?Int):?Int?{
????return?x?+?y;
}
add2(2,?3)?//5
//?Kotlin
fun?add2(x:?Int,?y:?Int):?Int?{
????return?x?+?y;
}
add2(2,?3)?//5
盡管這段代碼非常簡(jiǎn)單,但應(yīng)當(dāng)注意到,Bosque的語(yǔ)法與非常規(guī)版本的Kotlin非常相似。唯一的區(qū)別就是關(guān)鍵字function與fun的不同,其他代碼完全一樣。我們來(lái)看看更多的示例。
Bosque網(wǎng)站上給出了一個(gè)簡(jiǎn)單的井字棋游戲(https://github.com/Microsoft/BosqueLanguage/blob/master/docs/tictactoe.md)。雖然我完全沒(méi)有編寫(xiě)B(tài)osque代碼的經(jīng)驗(yàn),但這段代碼非常直觀,除了一些像'x'#PlayerMark;(有類型的字符串)、@[ 2, 2 ](元組/結(jié)構(gòu))和this<~(cells=this.cells..(原子批量數(shù)據(jù)操作)等語(yǔ)法糖之外。
下表總結(jié)了Bosque的井字棋游戲游戲示例中用到的一些語(yǔ)言概念,以及對(duì)應(yīng)的Kotlin概念。這個(gè)列表并不完整,但可以讓你方便地理解兩種語(yǔ)言的代碼示例:
| 語(yǔ)言特性 | Bosque | Kotlin |
| 不可更改的值(Immutable Values) | 全部 | 部分(基本類型,集合) |
| 有類型的字符串(Typed Strings) | 支持 | 內(nèi)嵌類或類型別名 |
| 靈活調(diào)用(Flexible invocations) | 命名實(shí)參 | 命名實(shí)參 |
| 批量代數(shù)數(shù)據(jù)操作(Bulk Algebraic Data Operations) | x<~(f=-1, g=-2) | copy()方法 |
| 短路運(yùn)算符(o?.m) | 使用問(wèn)號(hào) | 使用問(wèn)號(hào) |
| 原子構(gòu)造器(Atomic Constructors) | 支持 | 伴生對(duì)象(Companion Objects) |
| 元組(Tuples) | 支持 | 不支持(僅支持Pair/Triple) |
| 函數(shù)類型(Function types) | 支持 | 支持 |
?
現(xiàn)在我們對(duì)兩門(mén)語(yǔ)言有了一點(diǎn)理解,接下來(lái)我們?cè)賮?lái)深入看一看井字棋游戲的代碼,看看兩者具體的比較情況。如果你想直接看結(jié)果可以點(diǎn)這里(https://gist.github.com/bodiam/749b5174d26522cdaeba43c1401cbc8d)。如果你有耐心看下去,我可以帶你閱讀一些代碼,并給出相應(yīng)的Kotlin代碼。
?
Bosque井字棋
?
井字棋的示例是一個(gè)小游戲,玩家可以明確指定走哪一步,也可以隨機(jī)走一步。游戲不需要修改狀態(tài),因?yàn)橐磺卸际遣豢尚薷牡摹?/p>
Bosque有類型字符串
在井字棋示例中我們看到的第一個(gè)語(yǔ)言概念就是有類型字符串(Typed Strings):
const?playerX:?String[PlayerMark]?=?'x'#PlayerMark;
const?playerO:?String[PlayerMark]?=?'o'#PlayerMark;
上面這段代碼創(chuàng)建了兩個(gè)常量:playerX和playerO,都是有類型的字符串。也就是說(shuō),PlayerMark類型的字符串不能與包含郵政編碼的字符串兼容。
Kotlin不支持有類型字符串,但提供了內(nèi)嵌類(Inline Class)或類型別名(Type Aliases),可以用在類似的場(chǎng)合。內(nèi)嵌類可能更好(我們稍后會(huì)講到),但現(xiàn)在先來(lái)看看類型別名。類型別名促使Kotlin代碼更接近Bosque代碼:
const?val?playerX:?PlayerMark?=?"x"?as?PlayerMark
const?val?playerO:?PlayerMark?=?"o"?as?PlayerMark
Bosque類型
接下來(lái)看看這段代碼:List[[Int, Int]]。可以想象這是一個(gè)列表,但列表的元素類型為結(jié)構(gòu)類型[Int, Int]。因此,該列表只能包含整數(shù)對(duì)。
在Kotlin中,如果類型能夠推斷出來(lái),我們就不需要明確定義,但如果要定義的話可以寫(xiě)成List<Pair<Int, Int>>,寫(xiě)法非常相似。
Bosque結(jié)構(gòu)類型
如果需要保存數(shù)據(jù),但不希望定義類,則可以使用結(jié)構(gòu)(Struct)。在Bosque中,結(jié)構(gòu)類似于:@[ 0, 0 ]。它定義了一個(gè)結(jié)構(gòu),包含兩個(gè)值:0和0。
雖然Scala等語(yǔ)言都有結(jié)構(gòu),但Kotlin從早期的某個(gè)版本開(kāi)始就不再支持結(jié)構(gòu)了。聽(tīng)起來(lái)似乎有點(diǎn)奇怪,因?yàn)楸M管有時(shí)候結(jié)構(gòu)的存在是合理的,但是結(jié)構(gòu)并不會(huì)提高代碼的可讀性,而且創(chuàng)建數(shù)據(jù)類也非常容易。同時(shí),Kotlin原生支持Pair和Triple,因此在Kotlin中可以利用to方法創(chuàng)建上述結(jié)構(gòu):0 to 0,得到的結(jié)果是一個(gè)Pair對(duì)象。
Bosque前置條件
另一個(gè)有趣的概念是前置條件(preconditions),該功能可以通過(guò)requires關(guān)鍵字檢查函數(shù)的輸入。
requires?0?<=?x?&&?x?<?3?&&?0?<=?y?&&?y?<?3;Kotlin也有同樣的概念:
require(?0?<=?x?&&?x?<?3?&&?0?<=?y?&&?y?<?3)但是,除了支持前置條件外,Bosque還支持后置條件(postconditions)。后置條件可以檢查函數(shù)是否返回了正確的值,例如ensures _result_ % 2 == 0; 可以檢查返回值是否為偶數(shù)。
Kotlin也支持范圍檢查,因此我們可以通過(guò)重構(gòu)用更加常規(guī)的形式編寫(xiě)上述代碼成。
Bosque的原位更新
有一個(gè)很不錯(cuò)的功能,但Kotlin中卻沒(méi)有:通過(guò)拷貝的方式更新一個(gè)不可修改的列表。在Bosque中可以用下面的代碼實(shí)現(xiàn):
return?this<~(cells=this.cells->set(x?+?y?*?3,?mark));上面這段代碼創(chuàng)建了cells列表的拷貝,并將x + y * 3位置上的值更新成了mark。在Scala中,該操作可以通過(guò)updated方法實(shí)現(xiàn),但Kotlin不支持這個(gè)方法。該方法已經(jīng)有了一個(gè)YouTrack問(wèn)題票,所以如果你想要這個(gè)功能,可以去為該功能投票。同時(shí),你還可以通過(guò)創(chuàng)建擴(kuò)展函數(shù)的方式來(lái)創(chuàng)建自己的updated方法:
private?fun?<E>?List<E>.updated(index:?Int,?value:?E):?List<E>?{
????return?this.toMutableList().apply?{?set(index,?value)?}
}
如果你希望編寫(xiě)一段效率更高、但可讀性較差的代碼,則可以參考重構(gòu)后的Kotlin版本,或參考上述YouTrack問(wèn)題票。
Bosque的擴(kuò)散操作符
Bosque代碼中還有一行非常有意思:
var?tup?=?opts->uniform(rnd);
nboard?=?this.board->markCellWith(...tup,?mark);
這段代碼創(chuàng)建了新的棋盤(pán)(nboard),該棋盤(pán)是當(dāng)前棋盤(pán)的拷貝,是根據(jù)一個(gè)從列表中的數(shù)據(jù)項(xiàng)半隨機(jī)(uniform,表示根據(jù)種子來(lái)選取)地創(chuàng)建的。由于tup變量是元組,因此可以利用...操作符來(lái)擴(kuò)散(spread)其內(nèi)容。
盡管Kotlin也有擴(kuò)散運(yùn)算符,但沒(méi)這么靈活。它只能在調(diào)用vararg方法的時(shí)候使用。但是,Kotlin中只能做到使用Pair的第一個(gè)或第二個(gè)值,或者更Kotlin的方式是,像下面這樣先將Pair解構(gòu):
val?(x,?y)?=?opts.random(Random(rnd))
nboard?=?this.board.markCellWith(x,?y,?mark)
但是,由于我們希望盡可能地與原始代碼相似,所以暫時(shí)線直接使用第一個(gè)和第二個(gè)值:
nboard?=?this.board.markCellWith(tup.first,?tup.second,?mark)?
結(jié)果
?
上面的比較給出了一些Kotlin和Bosque之間的異同。作為本文的結(jié)果,我們現(xiàn)在有了三個(gè)不同版本的井字棋代碼:
-
原始的Bosque代碼:https://github.com/Microsoft/BosqueLanguage/blob/master/docs/tictactoe.md
-
原始的Kotlin代碼,盡可能與上述代碼相似:https://gist.github.com/bodiam/749b5174d26522cdaeba43c1401cbc8d
-
重構(gòu)后的Kotlin代碼,功能與上面的代碼相同,但使用了更多的Kotlin最佳實(shí)踐:https://gist.github.com/bodiam/c98cef9da8660a06c76883326b21a2cb
Kotlin最佳實(shí)踐
最后一個(gè)版本(即重構(gòu)后的Kotlin代碼)使用了一些Kotlin的最佳實(shí)踐。我不知道Bosque中是否有這些結(jié)構(gòu),也許Bosque的代碼也可以改進(jìn)。我們可以通過(guò)下列變更編寫(xiě)更符合慣例的代碼:
使用內(nèi)嵌類代替類型別名
inline?class?PlayerMark(val?value:?String)這種寫(xiě)法可以給出更好的類型信息,避免在應(yīng)該使用String的地方使用PlayerMark。
在require中使用范圍檢查
不要使用單獨(dú)的比較,我們應(yīng)該使用范圍比較:
require(?0?<=?x?&&?x?<?3?&&?0?<=?y?&&?y?<?3)?//?both?statements
require(x?in?0..2?&&?y?in?0..2)??????????????//?do?the?same
去除類型信息
Bosque中的類型用法似乎很冗余。盡管Kotlin中也完全可以這樣做,但并不是必須的。所以,下面兩條語(yǔ)句是相同的:
//?this
val?allCellPositions?:?List<Pair<Int,?Int>>?=?listOf(
????0?to?0,?1?to?0,?2?to?0,
)
//?vs
val?allCellPositions?=?listOf(
????0?to?0,?1?to?0,?2?to?0,
)
去掉`this`
Bosque代碼似乎用了許多this,但在Kotlin中不需要這樣做,所以重構(gòu)后的版本中去掉了this。
?
總結(jié)
?
總之,我希望在上文中我們很好地比較了兩種語(yǔ)言,我們也很期待Bosque語(yǔ)言將來(lái)的發(fā)展,而其他語(yǔ)言如C#、TypeScript或Kotlin能否采納這些概念呢,讓我們拭目以待吧。
總結(jié)
以上是生活随笔為你收集整理的微软推出新逆天开源语言Bosque,告别 for 循环,提高开发效率!的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 陈中华:李彦宏候选工程院院士,是全中国人
- 下一篇: 修复Chrome上的ERR_TOO_MA