成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Zig是碼農們期待已久的C語言的替代品嗎?

開發 前端
從很多方面來說,我整個編程生涯都像是在等待C的替代產品的漫長等待。20年前,盡管我用C ++。 隨著時間的流逝,我了解到C ++是一個復雜的怪物,無論我讀了多少本書,都永遠無法馴服。

與以前的C競爭者(例如C ++,D,Java,C#,Go,Rust和Swift)的比較

從很多方面來說,我整個編程生涯都像是在等待C的替代產品的漫長等待。20年前,盡管我用C ++。 隨著時間的流逝,我了解到C ++是一個復雜的怪物,無論我讀了多少本書,都永遠無法馴服。

我認為Yossi Kreinin和他的C ++常見問題解答(https://yosefk.com/c++fqa/)在總結我對C ++討厭的各個方面都做得很好。

因此,在成為一名專業的C ++程序員時,我總是著眼于其他選擇。 第一個有希望的替代品是D。D最初看起來很有前途,但經過仔細檢查,我認為D實際上只是一個根本上不好的主意的清理版本。 C ++的主要問題之一是它的接收器語言設計方法。

當用C和Lua實現一個簡單的游戲引擎時,我意識到與C ++相比,同時保留這兩種語言的思路實際上更少了。 它給我帶來了對C的重新熱愛。盡管有其所有局限性,C是一種相當簡單的語言,可以提供很多控制。

Java和C#在許多方面只是嘗試重新實現C ++。他們可能使事情變得更簡單,但最終卻陷入了虛擬機和90年代面向對象的編程炒作中。不是說Java或C#不好,其中很多可能與那些支持臃腫的IDE和過度設計的語言的相關社區有關。

Zig是碼農們期待已久的C語言的替代品嗎?

C簡單性的回歸

從Google轉到Go是對多余的C ++,D,Java和C#的歡送。Go將我們帶回到了起點,回到了C。Go重新設想了如果不冒險走C ++道路,C可能會是什么。我們得到的是一種簡單的語言,它修復了我在C語言中經常遇到的許多問題。

但是故事還沒有結束。 緊隨Go之后,我們得到了Rust。 最初,我認為Rust實際上是D應該一直以來的目標。 對C ++應該是什么的真正的重新思考。 Rust保持了低級控制,高級抽象機制和手動內存管理,但增加了無與倫比的類型安全性。 一切看起來都太好了,難以置信。

坦率地說,我認為是。我記得能夠在兩天內用Go編寫一些不錯的程序。朱莉婭,我目前的最愛也有些相似。另一方面,學習Rust就像學習Haskell。在做任何有用的事情之前,只需了解許多概念和理論即可。

如果C ++教會了我任何東西,那就是要重視簡單性,而Rust不會這樣做。

后來,我從互聯網上許多Rust用戶的評論中學到了,Rust重復了C ++的主要缺點之一。它的編譯時間確實很慢。我認為沒有什么比等待C ++編譯破壞我編程的樂趣了。聽起來好像Rust更糟了。那是一個破壞交易的因素。

Zig是碼農們期待已久的C語言的替代品嗎?

Swift-我想愛的語言

我20年來一直是蘋果的忠實粉絲。 我很喜歡Cocoa GUI庫,并在沒有iPhone之前就對Objective-C進行了編程,突然,每個人和他們的寵物都在用Objective-C進行編程。

是的,Objective-C有點笨拙,但它的簡單性具有一定的美感。 與C ++不同,它是對C語言的相當簡單的補充。 根據經驗,您實際上可以真正快速地教初級開發人員Objective-C。

因此,Swift的發布讓我覺得我已經達到了編程的必殺技。最終,一種非常現代的語言與Objective-C很好地集成在一起,因此我們仍然可以使用很棒的Apple庫,例如Cocoa。

Swift從Rust那里借來了很多想法,從很多方面來說,我認為我們終于為普通人獲得了Rust。可以在相當短的時間內學會Swift。

但是我在Swift方面的經歷好壞參半。 即使在今天,我也仍然無法正確表達語言的問題,因為它似乎可以解決很多問題。

我將iPhone應用程序從Objective-C移植到了Swift。 我最好的經歷之一是Swift僅僅由于嚴格的類型系統就發現了一大堆錯誤,這些系統捕獲了在Objective-C中不可見的問題,而這在編譯時至少是關于類型的,這是眾所周知的。

與C ++,C#和Java相比,我會說Swift是更好的語言。 Swift幾乎解決了我所有有關C ++的特定問題。 但是我每次使用Go時都意識到,編寫Go程序比Swift有趣得多。 但是Go的錯誤處理有點糟糕,它重復了具有空指針的百萬美元錯誤。 Swift避免了這兩個問題。

上次與Julia在一起很長時間后,我回到Swift時,看到Swift的一些問題變得更加清晰:

Swift語法不適合函數式編程

從Objective-C繼承的Smalltalk啟發式語法在面向對象的編程中很好地工作,但是對于函數式編程卻非常糟糕。將函數用作一等公民時,您無需費心確保參數名稱正確。

面向對象的編程和函數式編程之間的停戰。Swift試圖為兩個不同的主人服務,并為此遭受痛苦。在進行非常實用的樣式編程時,您希望您的函數主要是自由函數。這些更易于傳遞并在函數設置中使用。

但是Swift最終主要是面向OOP人群,將函數放在方法中。 一旦完成了許多函數編程,這就會變得很麻煩。

Zig適合編程領域的何處?

因此Swift從來沒有真正成為我最終的通用編程語言。如果我想以更高的抽象級別進行編程,獲得高性能并完成工作,我將選擇Julia。

但這仍然為C之類的替代品留下了未填補的空間。朱莉婭(Julia)不能真正取代C。它吞噬了內存,無法產生小的二進制文件,不適合使其他語言可以使用的庫。您不想使用它來創建OS內核或進行微控制器編程。

Go和Rust都真的接近于替換C。Go擺脫了使用C的簡單性和使用感。但是它使用垃圾回收并不能完全替代C。與Java相比,在Go中對內存使用的更多控制仍然是毫無價值的,因為您可以獲得指針,并且實際上可以創建自己的輔助分配器。

Rust降低了手動的內存分配,但是未能復制C的簡單性和感覺。也許這兩種語言之間是否有什么可以填補的空間?

確實有。 我認為這就是Zig。 Zig比Go更復雜,但比Rust更易于學習和使用。

但是,這樣的Zig總結并不能使語言公正。Zig為表帶來了很多新想法,這很有道理,并且使Zig編碼的體驗非常獨特。但是在深入探討之前,讓我們先看一下基礎知識。

正確掌握基礎知識

如果我們要學習另一種類似C的語言,我們將無法重復C ++最糟糕的情況,例如糟糕的編譯時間。 Zig如何解決這些問題?

我遇到了V編程語言的創建者Alexander Medvednikov進行的測試。這是編譯具有400 K函數的文件的測試:

  • C 5.2秒 gcc測試
  • C ++ 1分25秒 g ++ test.cpp
  • Zig 10.1秒 Zig build-exe test.zig
  • Nim 45秒 nim c test.nim
  • Rust 30分鐘 rustc test.rs 后Rust停止
  • Swift 在30分鐘的swiftc測試后停止
  • D 6分鐘后 segfault dmd test.d
  • V 0.6秒 v test v

Rust,Swift和D都失敗了。Medvednikov用更少的行數對這些語言進行了進一步的測試,Rust再次表現出了最差的預期。

正如您在列表中所看到的,Zig是最杰出的演員。 盡管很難不注意到V語言會在不到一秒鐘的時間內完成所有操作。 這使我想起更詳細地探索V。 快速掃描表明它可以手動分配內存,泛型和可選(必須明確允許使用空指針)。

Zig內存分配

如果不進行手動內存管理,您將無法使用C語言。進行C風格編程的人都希望這樣做。如果我不需要,那么我可以為Julia編程。

Zig沒有提供Rust所提供的那種最高的安全性,但是如果不這樣做,它所獲得的是一個對于初學者來說更容易掌握和使用的模型。

需要在Zig中分配內存的任何內容都將分配器作為參數。 因此Zig非常明確地說明了何時需要內存管理。

這是我編寫的一個簡單函數,它使用32位無符號整數n并將其拆分為十進制數字:

  1. fn decimals(alloc: *Allocator, n: u32) !Array(u32) { 
  2. var x = n
  3. var digits = Array(u32).init(alloc); 
  4. errdefer digits.deinit(); 
  5. while (x >= 10) { 
  6. try digits.append(x % 10); 
  7. xx = x / 10; 
  8. try digits.append(x); 
  9. return digits; 

請注意,必須使用分配器分配用于保留各個十進制數字的數組數字,該分配器是十進制函數的參數。

這就是Zig真正的光芒所在。 確保您不會忘記分配內存在C語言中很難。而且很容易以錯誤的位置結束內存。 Zig從Go復制了延遲概念。 但是除了推遲它還有errdefer。 如果您不了解Go,那么從本質上講,延遲是將行或代碼塊的執行推遲到函數退出之前的一種方法。

為什么這么好? 因為它使您可以確保某些代碼得以運行,而不管退出該函數之前使用了什么復雜的if-else語句。

  1. errdefer digits.deinit(); 

上面的行與正常的Go延遲有所不同,因為只有在返回錯誤代碼的情況下,它才會執行。因此,如果一切正常,那么它將永遠不會運行。

在呼叫站點,我們將使用常規延遲來確保我們不會忘記釋放分配給數字的內存。

  1. const digits = try decimals(allocator, 4123); 
  2. defer digits.deinit(); 
  3. for (digits.items) |digit| { 
  4. try print("{},", .{digit}); 

從我在Zig玩游戲方面的有限經驗,我會說這是一個很好的系統。分配器和defer的結合使用使您非常清楚要分配和釋放內存的位置,同時可以輕松正確地進行分配。

C兼容

許多類C語言的問題是它們無法與C配合使用。這意味著從該語言調用C函數應該很容易,而從C對該語言調用函數應該很容易。

此外,您編寫程序的一般方式應該與C完全兼容,因此您不必創建較大的C抽象級別。例如。C ++對C語言不是很友好,因為沒有大量包裝就無法在C中使用典型的C ++庫。

但是Zig非常C,因為它沒有暴露C不會得到的奇怪的東西。 結構中沒有vtable(C ++中的虛擬函數表)。 沒有C知道如何調用的構造函數或析構函數。 也沒有任何例外,C也會在捕獲方面遇到困難。

從Zig使用C很簡單。 實際上,Zig的創建者會聲稱Zig比C本身更擅長使用C庫。

  1. const c = @cImport({ 
  2. @cDefine("_NO_CRT_STDIO_INLINE", "1"); 
  3. @cInclude("stdio.h"); 
  4. }); 
  5. pub fn main() void { 
  6. _ = c.printf("hello\n"); 

如您所見,Zig解析C頭文件并包含來自C的類型和函數沒有問題。實際上Zig是完全成熟的C編譯器。您可以根據需要使用Zig編譯C程序。

同樣,將Zig函數暴露給C也很容易。這是一個Zig函數,采用32位整數并返回32位整數。

  1. export fn add(a: i32, b: i32) i32 { 
  2. return a + b; 

通過將export放在它的前面,可以使我們與程序鏈接的C代碼可以訪問它。實際上,我們的主要功能是在C代碼部分中定義的,并且使用了Zig中定義的功能。

  1. #include <stdint.h>int32_t add(int32_t a, int32_t b); 
  2. int main(int argc, char **argv) { 
  3. assert(add(42, 1337) == 1379); 
  4. return 0; 

這意味著您可以輕松地開始將較大的C程序的某些部分轉換為Zig并繼續進行編譯。 移植程序時,這是一項非常強大的功能。 過去讓我很容易地從Objective-C移植到Swift的原因是,我可以一次用Swift版本替換一個Objective-C方法,進行編譯并看到一切仍然有效。

實際上,通過允許您自動將C程序轉換為Zig代碼,Zig使其變得更加容易。 這是Zig編譯器內置的:

  1. $ zig translate-c foobar.c 

當然,該代碼不是最佳的,可能有點混亂。但這有點像使用Google翻譯進行自然語言翻譯。這是一個很好的起點,可以節省大量的體力勞動。您可以稍后自己手動修復細節。

極簡主義

極簡主義首先吸引了很多人使用C編程。 這就是Go正確的事情,并使編程變得很高興。 您可以輕松地將整個程序放在腦子里。

現在,如果您開始閱讀Zig并查看我在這里給您的源代碼示例,它可能看起來很復雜。 有些語言結構可能看起來很奇怪。 可以很容易地感覺到它是一種復雜的語言。

因此,弄清Zig不支持的所有事物實際上非常有用:

  • 沒有類繼承,例如C ++,Java,Swift等。
  • 通過Go之類的接口沒有運行時多態性。
  • 沒有泛型。 您不能像在編譯時檢查的Swift中那樣指定通用接口。
  • 沒有函數重載。您不能多次使用不同的參數編寫具有相同名稱的函數。
  • 沒有異常拋出。
  • 沒有閉包。
  • 沒有垃圾收集。
  • 沒有用于資源獲取的構造函數和析構函數是初始化(RAII)。

但是,通過巧妙地使用一些核心功能,Zig能夠提供幾乎相同的功能:

  • 類型可以在編譯時像對象一樣傳遞。
  • 標簽工會。在其他編程語言中也稱為求和類型或變體。
  • 函數指針。
  • 實數指針和指針算術。
  • Zig代碼可以在編譯時部分評估。您可以使用comptime關鍵字將代碼標記為在編譯時可執行。
  • 函數和類型可以與結構相關聯,但不能物理存儲在結構中,因此C代碼不可見。

在Zig中模擬泛型

例如。通過利用在編譯時運行代碼的能力,在Julia中創建了類似于模板的內容。洛里斯·克羅(Loris Cro)有一篇很好的文章更詳細地描述了這一點。我將僅使用該文章中的示例來快速了解該想法。

我們可以定義例如一個稱為LinkedList的函數,該函數只能在編譯時調用,該函數采用鏈表中元素的類型,然后返回包含以下元素的鏈表類型:

  1. fn LinkedList(comptime T: type) type { 
  2. return struct { 
  3. pub const Node = struct { 
  4. prev: ?*Node = null, next: ?*Node = null, data: T, 
  5. }; 
  6. first: ?*Node = null, last: ?*Node = null, len: usize = 0
  7. }; 

這利用了結構可以是匿名的事實。 您不需要給他們起個名字。 但是,此功能需要一點包裝。 注意這一部分:

  1. pub const Node = struct { prev: ?*Node = null, next: ?*Node = null, data: T,}; 

這里有許多Zig特定功能在起作用,需要一些解釋。 在Zig中,可以在定義結構時將值分配給結構成員。 成員可以是在編譯時或運行時存在的字段。 上一個:?* Node = null是結構字段的一個示例,該字段在編譯時存在,但其默認值為null。 那瘋狂的*前綴呢?

在Zig中,* Node表示類似于C / C ++的指向Node類型對象的指針。但是,由于Zig除非明確允許,否則不允許指針為null,因此必須添加?。指示指針可以為空。

節點本身被設置為周圍匿名結構的字段。 但是,由于將其定義為const,因此僅在編譯時存在。 如果在運行時檢查LinkedList結構的內存,則找不到與Node對應的區域。

另外請記住,雖然您可以在編譯時將類型用作任何其他對象,但它們在運行時在Zig中并不存在。 因此,基本上我們在這里所做的就是創建帶有嵌套類型的結構。

讓我使用Loris Cro的示例之一進行更好的解釋。首先,他創建一個包含點的鏈表,并將其分配給僅在編譯時存在的名為PointList的變量:

  1. const PointList = LinkedList(Point); 

然后,我們可以使用此新創建的類型實例化一個空列表。

  1. var my_list = PointList{}; 

我們不需要為first,last和len指定任何初始值,因為它們具有默認值。

在這里,我們使用嵌套類型創建一個Node對象來保存我們的點數據:

  1. const p = Point.x = 0.y = 2.z = 8 }; 
  2. var node = PointList.Node{ .data = p }; 
  3. my_list.first = &node; 
  4. my_list.last = &node; 
  5. my_list.len = 1

在Zig中模擬接口

盡管Zig沒有類或面向對象語言之類的接口的關鍵字,但我們仍然可以構建自己的運行時多態系統,類似于C程序員多年來所做的那樣。

您只需使用函數指針定義結構即可。在Unix內核中,您看到了類似的操作,可以對任何文件描述符進行通用處理,無論它們是文件,套接字還是管道。

  1. typedef struct _File { 
  2. void (*write)(void *fd, char *data); 
  3. void (*read)(void *fd, char *buffer, int size); 
  4. void (*close)(void *fd); 
  5. File; 

這并不完全是它的定義方式。 我只是從內存中做到這一點。 這允許我們做的是為文件,套接字和管道提供不同的打開功能。 但是,由于它們都給了我們File結構,因此其他函數可以使用其包含的這些函數指針對此進行操作,從而抽象出底層結構的差異。

在Zig中,我們使用Nathan Michaels在此處更詳細描述的類似方法。 Zig比C提供了更好的功能,因此您會看到Zig在創建通用迭代器,分配器,讀取器,寫入器以及在Zig中進行更多操作時使用了更多功能。

有人可能會問,為什么不將這類內容納入語言呢?如果您曾經使用過Lua,那么您將了解一些優點,而不是給您構造塊以創建面向對象的系統,而不是對其進行硬接線。

使用Zig,您可以構建C ++風格的面向對象的系統,類似于Go甚至是類似于諸如Objective-C之類的更動態語言的面向對象編程。

這種自行開發的方法可能非常有效。我們已經看到LISP程序員使用它來在LISP中構建面向對象的編程系統,甚至創建類似于Julia的多調度系統。

 

責任編輯:趙寧寧 來源: 今日頭條
相關推薦

2021-11-09 09:00:00

Docker開發工具

2009-10-12 14:31:24

紅帽虛擬化

2020-12-04 09:41:36

C編程語言替換C

2021-11-16 14:21:02

React 開發 Beta

2022-02-08 11:45:03

PiniaVuex前端

2012-07-20 09:37:00

Oracle LinuCentOS

2023-07-11 18:36:20

CloudReady開源

2011-04-12 09:13:51

OpenIndianaSolaris替代品

2021-07-19 22:31:39

微信微信客服移動應用

2022-09-26 09:39:30

LinuxsystemdWSL

2022-08-02 10:45:29

AppFlowyNotion開源

2021-07-16 22:49:50

PiniaVuex替代品

2013-09-16 11:10:30

2020-08-23 12:15:38

技術研發指標

2013-10-30 16:40:45

2020-12-09 11:10:58

GitHub代碼開發者

2020-02-17 21:35:21

JoplinEvernote開源

2016-09-13 15:50:24

TurtlEvernote開源

2023-08-29 18:49:41

2013-11-19 14:36:38

UbuntuDebianPCLinuxOS
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久偷人| 久久精品av | 亚洲免费大片 | 欧美精品一区二区免费 | 日韩久久精品电影 | 影音先锋成人资源 | 精品久久久久久久 | 午夜精品一区二区三区免费视频 | 久久tv在线观看 | 亚洲综合日韩精品欧美综合区 | 精品一区二区三区中文字幕 | 国产视频91在线 | 日本午夜免费福利视频 | 日本免费视频 | 91国产在线视频在线 | 欧美黑人又粗大 | 亚洲高清久久 | 操皮视频| 日本精品一区二区三区四区 | 国产高清一区二区三区 | 久久精品亚洲欧美日韩精品中文字幕 | 久久久99精品免费观看 | www.久久久久久久久 | 国产精品久久久久久久久久 | 视频一区欧美 | 日韩欧美视频网站 | 久久福利电影 | 久久久免费观看视频 | 最新中文字幕在线 | 久久久久亚洲 | 在线免费观看黄视频 | 精品国产乱码久久久久久丨区2区 | 免费一区二区在线观看 | 亚洲日日 | 中文字幕亚洲一区二区三区 | 欧美激情综合网 | 亚洲一区二区三区在线 | 亚洲女优在线播放 | 欧美精产国品一二三区 | 成人精品一区二区户外勾搭野战 | 蜜桃视频在线观看免费视频网站www |