<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          技術(shù)總監(jiān)親自上陣,手?jǐn)]了一門編程語言,同事直呼哇塞!

          共 6966字,需瀏覽 14分鐘

           ·

          2022-09-20 22:06

          二哥的編程星球已經(jīng)有 810 多名 球友加入了,如果你也需要一個(gè)良好的學(xué)習(xí)氛圍,戳鏈接加入我們吧!這是一個(gè)Java學(xué)習(xí)指南+編程實(shí)戰(zhàn)+LeetCode 刷題的私密圈子,你可以向二哥提問、幫你制定學(xué)習(xí)計(jì)劃、和球友一起打卡成長(zhǎng),沖沖沖。

          前言

          大家好,我是二哥呀!

          都說程序員的三大浪漫是:操作系統(tǒng)、編譯原理、圖形學(xué);但圖形學(xué)確實(shí)是特定的專業(yè)領(lǐng)域,我們幾乎接觸不到,所以對(duì)我來說換成網(wǎng)絡(luò)更合適一些,最后再加上一個(gè)數(shù)據(jù)庫。

          這四項(xiàng)技術(shù)如果都能掌握的話,可以在 IT 行業(yè)橫著走了,加上這幾年互聯(lián)網(wǎng)行業(yè)越來越不景氣,越底層的技術(shù)就越不可能被替代;所以為了給自己的 30+ 危機(jī)留點(diǎn)出路,從今年上半年開始我就逐漸開始從頭學(xué)習(xí)編譯原理。

          功夫不負(fù)有心人,經(jīng)過近一個(gè)月的挑燈夜戰(zhàn),每晚都在老婆的催促下才休息,克服了中途好幾次想放棄的沖動(dòng),終于現(xiàn)在完成了 GScript 一個(gè)預(yù)覽版。

          預(yù)覽版的意思是語法結(jié)構(gòu)與整體設(shè)計(jì)基本完成,后續(xù)更新也不太會(huì)改動(dòng)這部分內(nèi)容、但還缺少一些易用功能。

          特性

          首先來看看保留環(huán)節(jié), GScript 是如何編寫 hello world 的。

          hello_world.gs:

                
                println("hello?world");
                
                ??gscript?hello_world.gs
          hello?world

          廢話說完了接下來重點(diǎn)聊聊 GScript 所支持的特性了。

          2802396d7eed0a60fa53620d6966c6cb.webp

          后文會(huì)重點(diǎn)說明每一個(gè)特性。

          例子

          除了剛才提到的 hello world,再來看一個(gè)也是示例代碼經(jīng)常演示的打印斐波那契數(shù)列。

                
                void?fib(){
          ????int?a?=?0;
          ????int?b?=?1;
          ????int?fibonacci(){
          ????????int?c?=?a;
          ????????a?=?b;
          ????????b?=?a+c;
          ????????return?c;
          ????}
          ????return?fibonacci;
          }
          func?int()?f?=?fib();
          for?(int?i?=?0;?i?<?5;?i++){
          ????println(f());
          }

          輸出結(jié)果如下:

                
                0
          1
          1
          2
          3

          整體寫法與 Go 官方推薦的類似:https://go.dev/play/p/NeGuDahW2yP

                
                //?fib?returns?a?function?that?returns
          //?successive?Fibonacci?numbers.
          func?fib()?func()?int?{
          ?a,?b?:=?0,?1
          ?return?func()?int?{
          ??a,?b?=?b,?a+b
          ??return?a
          ?}
          }
          func?main()?{
          ?f?:=?fib()
          ?//?Function?calls?are?evaluated?left-to-right.
          ?fmt.Println(f(),?f(),?f(),?f(),?f())
          }

          都是通過閉包變量實(shí)現(xiàn)的,同時(shí)也展示了 GScript 對(duì)閉包、函數(shù)的使用,后文詳細(xì)介紹閉包的用法。

          語法

          GScript 的語法與常見的 Java/Go 類似,所以上手非常簡(jiǎn)單。

          基本類型

          先來看看基本類型,目前支持 int/string/float/bool 四種基本類型以及 nil 特殊類型。

          變量聲明語法和 Java 類似:

                
                int?a=10;
          string?b,c;
          float?e?=?10.1;
          bool?f?=?false;

          個(gè)人覺得將類型放在前面,代碼閱讀起來會(huì)更清晰一些,當(dāng)然這也是個(gè)人喜好。

          數(shù)組

                
                //?聲明并初始化
          int[]?a={1,2,3};
          println(a);

          //?聲明一個(gè)空數(shù)組并指定大小
          int[]?table?=?[4]{};

          println();
          //?向數(shù)組?append?數(shù)據(jù)
          a?=?append(a,4);
          println(a);
          for(int?i=0;i<len(a);i++){
          ?println(a[i]);
          }

          //?通過下標(biāo)獲取數(shù)組數(shù)據(jù)
          int?b=a[2];
          println(b);

          其實(shí)嚴(yán)格來講這并不算是數(shù)組,因?yàn)樗牡讓邮怯?Go 切片實(shí)現(xiàn)的,所以可以動(dòng)態(tài)擴(kuò)容。

          以這段代碼為例:

                
                int[]?a=[2]{};
          println("數(shù)組大小:"+len(a));
          a?=?append(a,1);
          println("數(shù)組大小:"+len(a));
          println(a);
          a[0]=100;
          println(a);

          輸出:

                
                數(shù)組大小:2
          數(shù)組大小:3
          [<nil>?<nil>?1]
          [100?<nil>?1]

          Class

          類的支持非常重要,是實(shí)現(xiàn)面向?qū)ο蟮幕A(chǔ),目前還未完全實(shí)現(xiàn)面向?qū)ο?,只?shí)現(xiàn)了數(shù)據(jù)與函數(shù)的封裝。

                
                class?ListNode{
          ????int?value;
          ????ListNode?next;
          ????ListNode(int?v,?ListNode?n){
          ????????value?=v;
          ????????next?=?n;
          ????}
          }

          //?調(diào)用構(gòu)造函數(shù)時(shí)不需要使用 new 關(guān)鍵字。
          ListNode?l1?=?ListNode(1,?nil);

          //?使用 . 調(diào)用對(duì)象屬性或函數(shù)。
          println(l1.value);

          缺省情況下 class 具有無參構(gòu)造函數(shù):

                
                class?Person{
          ?int?age=10;
          ?string?name="abc";
          ?int?getAge(){
          ??return?100+age;
          ?}
          }

          //?無參構(gòu)造函數(shù)
          Person?xx=?Person();
          println(xx.age);
          assertEqual(xx.age,?10);
          println(xx.getAge());
          assertEqual(xx.getAge(),?110);

          得益于 class 的實(shí)現(xiàn),結(jié)合剛才的數(shù)組也可以定義出自定義類型的數(shù)組:

                
                //?大小為?16?的?Person?數(shù)組
          Person[]?personList?=?[16]{};

          函數(shù)

          函數(shù)其實(shí)分為兩類:

          • 普通的全局函數(shù)。
          • 類的函數(shù)。

          本質(zhì)上沒有任何區(qū)別,只是所屬范圍不同而已。

                
                //?判斷鏈表是否有環(huán)
          bool?hasCycle(ListNode?head){
          ????if?(head?==?nil){
          ????????return?false;
          ????}
          ????if?(head.next?==?nil){
          ????????return?false;
          ????}

          ????ListNode?fast?=?head.next;
          ????ListNode?slow?=?head;
          ????bool?ret?=?false;
          ????for?(fast.next?!=?nil){
          ????????if?(fast.next?==?nil){
          ????????????return?false;
          ????????}
          ????????if?(fast.next.next?==?nil){
          ????????????return?false;
          ????????}
          ????????if?(slow.next?==?nil){
          ????????????return?false;
          ????????}
          ????????if?(fast?==?slow){
          ????????????ret?=?true;
          ????????????return?true;
          ????????}

          ????????fast?=?fast.next.next;
          ????????slow?=?slow.next;
          ????}
          ????return?ret;
          }

          ListNode?l1?=?ListNode(1,?nil);
          bool?b1?=hasCycle(l1);
          println(b1);
          assertEqual(b1,?false);

          ListNode?l4?=?ListNode(4,?nil);
          ListNode?l3?=?ListNode(3,?l4);
          ListNode?l2?=?ListNode(2,?l3);
          bool?b2?=?hasCycle(l2);
          println(b2);
          assertEqual(b2,?false);

          l4.next?=?l2;
          bool?b3?=?hasCycle(l2);
          println(b3);
          assertEqual(b3,?true);

          這里演示了鏈表是否有環(huán)的一個(gè)函數(shù),只要有其他語言的使用基礎(chǔ),相信閱讀起來沒有任何問題。

                
                add(int?a){}

          當(dāng)函數(shù)沒有返回值時(shí),可以聲明為 void 或直接忽略返回類型。

          閉包

          閉包我認(rèn)為是非常有意思的一個(gè)特性,可以實(shí)現(xiàn)很靈活的設(shè)計(jì),也是函數(shù)式編程的基礎(chǔ)。

          所以在 GScript 中函數(shù)是作為一等公民存在;因此 GScript 也支持函數(shù)類型的變量。

          函數(shù)變量聲明語法如下:func typeTypeOrVoid '(' typeList? ')'

                
                //?外部變量,全局共享。
          int?varExternal?=10;
          func?int(int)?f1(){
          ?//?閉包變量對(duì)每個(gè)閉包單獨(dú)可見
          ?int?varInner?=?20;
          ?int?innerFun(int?a){
          ??println(a);
          ??int?c=100;
          ??varExternal++;
          ??varInner++;
          ??return?varInner;
          ?}
          ?//?返回函數(shù)
          ?return?innerFun;
          }

          // f2 作為一個(gè)函數(shù)類型,接收的是一個(gè)返回值和參數(shù)都是 int 的函數(shù)。
          func?int(int)?f2?=?f1();
          for(int?i=0;i<2;i++){
          ?println("varInner="?+?f2(i)?+?",?varExternal="?+?varExternal);
          }
          println("=======");
          func?int(int)?f3?=?f1();
          for(int?i=0;i<2;i++){
          ?println("varInner="?+?f3(i)?+?",?varExternal="?+?varExternal);
          }

          最終輸出如下:

                
                0
          varInner=21,?varExternal=11
          1
          varInner=22,?varExternal=12
          =======
          0
          varInner=21,?varExternal=13
          1
          varInner=22,?varExternal=14
                
                func?int(int)?f2?=?f1();

          以這段代碼為例:f2 是一個(gè)返回值,入?yún)⒍紴?int 的函數(shù)類型;所以后續(xù)可以直接當(dāng)做函數(shù)調(diào)用 f2(i).

          例子中將閉包分別賦值給 f2 和 f3 變量,這兩個(gè)變量中的閉包數(shù)據(jù)也是互相隔離、互不影響的,所有基于這個(gè)特性甚至還是實(shí)現(xiàn)面向?qū)ο蟆?/p>

          更多樣例請(qǐng)參考:https://github.com/crossoverJie/gscript/tree/main/example

          標(biāo)準(zhǔn)庫

          標(biāo)準(zhǔn)庫源碼:https://github.com/crossoverJie/gscript/tree/main/internal

          目前實(shí)現(xiàn)的標(biāo)準(zhǔn)庫并不多,這完全是一個(gè)體力活;基于現(xiàn)有的語法和基礎(chǔ)數(shù)據(jù)類型,幾乎可以實(shí)現(xiàn)大部分的數(shù)據(jù)結(jié)構(gòu)了,所以感興趣的朋友也歡迎來貢獻(xiàn)標(biāo)準(zhǔn)庫代碼;比如 Stack、Set 之類的數(shù)據(jù)結(jié)構(gòu)。

          MapString

          以這個(gè) MapString 為例:鍵值對(duì)都為 stringHashMap。

                
                int?count?=100;
          MapString?m1?=?MapString();
          for?(int?i=0;i<count;i++){
          ?string?key?=?i+"";
          ?string?value?=?key;
          ?m1.put(key,value);
          }
          println(m1.getSize());
          assertEqual(m1.getSize(),count);

          for?(int?i=0;i<count;i++){
          ?string?key?=?i+"";
          ?string?value?=?m1.get(key);
          ?println("key="+key+?":"+?value);
          ?assertEqual(key,value);
          }

          使用起來和 JavaHashMap 類似,當(dāng)然他的實(shí)現(xiàn)源碼也是參考的 jdk1.7 的 HashMap。

          由于目前并有一個(gè)類似于 Java 的 object 或者是 go 中的 interface{}, 所以如果需要存放 int,那還得實(shí)現(xiàn)一個(gè) MapInt,不過這個(gè)通用類型很快會(huì)實(shí)現(xiàn)。

          內(nèi)置函數(shù)

                
                int[]?a={1,2,3};
          //?len?返回?cái)?shù)組大小
          println(len(a));

          //?向數(shù)組追加數(shù)據(jù)
          a?=?append(a,4);
          println(a);
          //?output:?[1,2,3,4]

          //?斷言函數(shù),不相等時(shí)會(huì)拋出運(yùn)行時(shí)異常,并中斷程序。
          assertEqual(len(a),4);

          //?返回?hashcode
          int?hashcode?=?hash(key);

          也內(nèi)置了一些基本函數(shù),當(dāng)然也這不是由 GScript 源碼實(shí)現(xiàn)的,而是編譯器實(shí)現(xiàn)的,所以新增起來要稍微麻煩一些;后續(xù)會(huì)逐步完善,比如和 IO 相關(guān)的內(nèi)置函數(shù)。

          總結(jié)

          現(xiàn)階段的 GScript 還有許多功能沒有完善,比如 JSON、網(wǎng)絡(luò)庫、更完善的語法檢查、編譯報(bào)錯(cuò)信息等;現(xiàn)在拿來刷刷 LeetCode 還是沒有問題的。

          f911a3fee3ec0954620ee9fb248a8631.webp

          從這 65 個(gè) todo 就能看出還有很長(zhǎng)的路要走,我對(duì)它的終極目標(biāo)就是可以編寫一個(gè)網(wǎng)站那就算是一個(gè)成熟的語言了。

          目前還有一個(gè)問題是沒有集成開發(fā)環(huán)境,現(xiàn)在的開發(fā)體驗(yàn)和白板上寫代碼相差無異,所以后續(xù)有時(shí)間的話嘗試寫一個(gè) VS Code 的插件,至少能有語法高亮與提示。

          最后對(duì) GScript 或者是編譯原理感興趣的小伙伴可以加我微信一起交流。

          項(xiàng)目源碼:https://github.com/crossoverJie/gscript

          下載地址:https://github.com/crossoverJie/gscript/releases/tag/v0.0.6


          沒有什么使我停留——除了目的,縱然岸旁有玫瑰、有綠蔭、有寧靜的港灣,我是不系之舟。

          c1c4f697ab2d063b3e8d2e02ff122bca.webp
          瀏覽 37
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  台湾娱乐成人网综合网 | 人妻无码成人短视频 | 91麻豆网站 | 色天天男人天堂 | 做爱黄片免费观看 |