| ジグ | |
|---|---|
| パラダイム | マルチパラダイム:命令型、並行型、手続き型、関数型 |
| デザイン : | アンドリュー・ケリー |
| 初 登場 | 2016年2月8日 (2016-02-08)[ 1 ] |
| 安定放出 | |
| タイピングの規律 | 静的、強力、推論、名目、一般的 |
| メモリ管理 | マニュアル |
| 実装言語 | ジグ |
| プラットフォーム | x86-64、ARM64、WebAssembly Tier 2: ARM、IA-32、RISC-V、MIPS64、POWERPC64、SPARC64 、一部のTier-2プラットフォームはスタンドアロンプログラムに対してTier-1のサポートを提供します |
| OS | クロスプラットフォーム:Linux、macOS、FreeBSD、Windows |
| ライセンス | MIT |
| ファイル名拡張子 | .zig、.zir、.zigr、.zon |
| Webサイト | ziglang.org |
| 影響を受けた | |
| C、C++、LLVM IR、Go、Rust [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 10 ] | |
Zigは、 C言語を汎用的に改良したシステムプログラミング言語です。[ 11 ]これは無料のオープンソースソフトウェアであり、ソースコード共有プラットフォームであるCodebergでMITライセンスの下でリリースされています。[ 12 ]
C との違いは、制御フロー、関数呼び出し、ライブラリのインポート、変数宣言、およびUnicodeサポートに関するものです。この言語はマクロやプリプロセッサ命令を使用しません。現代の言語から採用された機能には、コンパイル時の汎用プログラミングデータ型の追加があり、これにより関数がさまざまなデータに対して動作できるようになり、また、リフレクションを使用してこれらの型に関する情報にアクセスできるようにする新しいコンパイラディレクティブの小さなセットが追加されています。[ 13 ] Zig では手動でのメモリ管理が必要です。[ 13 ]低レベル プログラミングの機能には、パックされた構造体、任意の幅の整数[ 14 ]、および複数のポインタ型[ 15 ]が含まれます。
ZigはAndrew Kelleyによって設計され、2016年に初めて発表されました。[ 1 ]開発は、企業スポンサーシップと個人からの寄付を受けているZig Software Foundation(ZSF)によって資金提供されています。[ 16 ] [ 17 ]
Zig の主な目標は、現在 C 言語で解決されているようなタスクに対して、より優れたソリューションを提供することです。その点における主な懸念事項は可読性です。Zig は可能な限り既存の概念と構文を使用し、類似の概念に対して異なる構文を追加することを避けています。さらに、その目標は「堅牢性、最適性、保守性」のために設計された言語であることです。小さくてシンプルな構文は保守の重要な部分であり、保守担当者が馴染みのない言語の複雑さを学ぶことなくコードをデバッグできるようにすることが、この言語の目標です。[ 18 ]これらの変更があっても、Zig は既存の C コードにコンパイルしたり、既存の C コードに対してコンパイルしたりできます。C ヘッダーを Zig プロジェクトに含めてその関数を呼び出すことができ、コンパイラが作成したヘッダーを含めることで Zig コードを C プロジェクトにリンクできます。[ 19 ]
catchエラー処理はエラー型によって行われ、またはを使用して処理できます。ジェネリクスはコンパイル時のコード生成と、ディレクティブによるダックタイピングtryの形式への対応によって実現されます。comptime
Zig標準ライブラリにおけるメモリ割り当ては、libcstructのメモリ管理関数を呼び出すのではなく、アクションを記述するsを介して割り当てを処理するという慣例に従います。たとえば、C言語で、別の文字列の複数のコピーを含む文字列を作成する関数を記述する場合、その関数は次のようになります。
const char * repeat ( const char * original , size_t times );コードでは、関数はサイズを調べてoriginalから、構築する文字列のためにメモリを確保するためにその長さをmallocでtimes割り当てます。このmallocは呼び出し元の関数からは見えません。呼び出し元の関数が後でメモリを解放しなかった場合、メモリリークが発生します。Zigでは、次のような関数を使用してこれを処理できます。
const Allocator = std.mem.Allocator ;fn repeat ( allocator : Allocator , original : [] const u8 , times : usize ) Allocator . Error ! [] const u8 ;このコードでは、allocator変数には割り当てを実行するコードを示す構造体が渡され、repeat関数は結果の文字列を返すか、またはで示されるオプションの型を使用して!Allocator.Error を返します。アロケータを入力として直接表現することで、メモリ割り当ては他の関数内に「隠蔽」されることはなく、最終的にメモリ割り当てを呼び出す関数によって常に API に公開されます。Zig の標準ライブラリ内では割り当ては実行されません。さらに、構造体は任意のものを指すことができるため、プログラム内で記述されたものも含め、代替のアロケータを使用できます。これにより、たとえば、通常はメモリ ページ全体を割り当てるオペレーティングシステムの関数を使用しない小さなオブジェクトのアロケータが可能になります。[ 20 ]
オプション型は、シンプルかつ汎用的でありながら一般的な機能を提供する言語機能の一例です。ヌルポインタの問題を解決するために使用する必要はありません。また、「値なし」が適切な答えとなるあらゆる型の値にも役立ちます。countTheNumberOfUsers整数を返す関数と、theCountedUsersその結果を保持する整数型の変数を考えてみましょう。多くの言語では、まだ呼び出されていないことを示すためにマジックナンバーが置かれますが、多くの実装では単にゼロに設定されます。Zigでは、これは変数を明確な「まだ呼び出されていない」値に設定するとして実装できます。 [ 20 ]theCountedUserscountTheNumberOfUsersvartheCountedUsers:?i32=null
deferZigのメモリ問題の管理に役立つもう一つの一般的な機能は、スコープの最後に実行されるコードをマークする概念です。実行時エラーの可能性も含め、何があっても実行されます。特定の関数がメモリを割り当て、操作が完了したときにそれを解放する場合、free何があっても確実に解放されるように、を遅延させる行を追加できます。[ 20 ]
Zig標準ライブラリは隠れた割り当てを回避します。割り当ては言語内で直接管理されません。代わりに、ヒープアクセスは標準ライブラリを介して明示的に行われます。[ 21 ]
Zigは、新しいZigコードと既存のCコードを組み合わせることで、移植性を段階的に向上させるアプローチを採用しています。そのため、既存のCライブラリとの連携を可能な限りシームレスにすることを目指しています。Zigは@import、通常次のようなディレクティブを使用して独自のライブラリをインポートします。
const std = @import ( "std" );そのファイル内のZigコードは、例えばstd内の関数を呼び出すことができるようになりました。
std.debug.print ( "Hello , world! \n" , . { } ) ;Cコードを扱うには、単に@importを に置き換えるだけです@cImport。
const c = @cImport ( @cInclude ( "soundio/soundio.h" ));Zig コードは、まるでネイティブの Zig コードであるかのように soundio ライブラリの関数を呼び出すことができるようになりました。Zig は、C のより汎用的な型や型とは異なり、明示的に定義された新しいデータ型を使用するため、intC型と Zig 型の間でデータを移動するために、やをfloat含む少数のディレクティブが使用されます。[ 20 ]@intCast@ptrCast
Zig 0.16.0 は非推奨になりました@cImport。今後は、@cImport言語組み込み関数を使用する代わりに、ビルド システムを介して C 翻訳が処理されます。組み込み関数は言語から「削除」されました。さらに、このリリースではstd.Build.Step.TranslateC 、公式の translate-c パッケージの明示的なパッケージ依存関係を使用するように変更されました。これは、追加の構成オプションを備えた以前のビルド ステップ バージョンと同じ実装です。[ 22 ]
その結果、変更前のZigリリースで使用されていたCコードの組み込み例を移行する必要があります。Cヘッダーファイルはビルドシステムを使用してインポートする必要があります。以前の例を移行するには、例えば標準Cインクルード行を追加したシンプルなヘッダーファイルを作成する必要があります。
#include <soundio/soundio.h>build.zigこのヘッダーファイルは、プロジェクトで使用されるファイル内で次のように参照する必要があります(この例では、ファイルはディレクトリc.h内で命名されていますsrc):[ 22 ]
const Translator = @import ( "translate_c " ). Translator ;const translate_c = b.dependency ( " translate_c" , .{}) ;const translator : Translator = .init ( translate_c , .{ .c_source_file = b.path ( " src /ch" ), .target = target , .optimize = optimize , } ) ; translator.linkSystemLibrary( " soundio " , . { } ) ;const exe = b.addExecutable (.{ .name = " hello - sound" , .root_module = b.createModule (.{ .root_source_file = b.path ( " src / main.zig" ) , .optimize = optimize , .target = target , .imports = & . { . { .name = " c " , .module = translator.mod , } , } , } ), } ) ;soundioライブラリの関数を呼び出すように変更した後、ネイティブのZigコードでは以下の変更が必要になります。
const c = @import ( "c" );キーワードを使用することでcomptime、プログラマは実行時ではなくコンパイル時にコードのセクションを明示的にZigに評価させることができます。コンパイル時にコードを実行できることで、Zigは別のプリプロセッサ言語を必要とせずにマクロと条件付きコンパイルの機能を実現できます。[ 23 ]
コンパイル時には、型は第一級オブジェクトになります。これによりコンパイル時のダックタイピングが可能になり、Zig がジェネリック型を実装する方法となります。[ 15 ]
例えば、Zigでは、汎用的なリンクリスト型は次のような関数を使って実装されるかもしれません。
fn LinkedList ( comptime T : type ) type ;この関数は、ある型を受け取りT、structそのデータ型でリンクされたリストを定義するカスタムオブジェクトを返します。
ZigにはCおよびC++コンパイラも含まれており、コマンドとを利用することで、どちらか一方または両方の言語で使用できますzig cc。zig c++[ 24 ]は、さまざまなプラットフォーム向けにC標準ライブラリ(libc)やC++標準ライブラリ(libcxx)などの多くのヘッダーを提供します。これにより、Zigのccサブc++コマンドは、すぐにクロスコンパイラとして機能します( Clangと同様)。[ 25 ] [ 26 ]
Zig はクロスコンパイルを言語の第一級のユースケースとして扱います。[ 13 ]これは、どの Zig コンパイラでも、数十種類あるターゲット プラットフォームのいずれに対しても実行可能なバイナリをコンパイルできることを意味します。これには、ARMやx86-64のような広く使われている最新のシステムだけでなく、PowerPC、SPARC、MIPS、RISC-V、LoongArch64、さらには IBM z/Architectures (S390) も含まれます。ツールチェーンは、追加のソフトウェアをインストールすることなく、これらのターゲットのいずれに対してもコンパイルできます。必要なサポートはすべて基本システムにあります。[ 20 ]また、AMD や Nvidia GPU、PlayStation 4 や 5 (サポートの程度は様々) など、あまり知られていないプラットフォームに対しても実験的なサポートが提供されています。
クロスコンパイルは、様々なオペレーティングシステム(主にデスクトップOS)向けに提供されています。一般的なUNIX系OSとWindowsは公式にサポートされ、ドキュメントも用意されていますが、Android(Android NDKを使用)やiOS向けにも(最小限の)アプリケーションが作成されており、実際に開発されています。
Zigは最適化のバックエンドとしてLLVM(C++で記述)を使用しています。バージョン0.10以降、ZigコンパイラはZigプログラミング言語で記述されており、自己ホスト型コンパイラとなっています。自己ホスト型リンカは、自己ホスト型コンパイラと密接に結合しています。
LLVMバックエンドは、 SPIR-Vおよびx86-64 [ 27 ]を除くほとんどのターゲットのデフォルトです(ただし、これは現在デバッグモードのみです)。Zig は、を使用して有効にできる独自のホスト型バックエンドもサポートしています。-fno-llvm
ケリーはデジタルオーディオワークステーションの開発を始めたが、[ 28 ]「GoとCライブラリの相互運用が難しく、ガベージコレクタがオーディオの遅延を引き起こすことがわかった。C++を試したが、小さなミスがメモリ破損バグにつながり、修正に数週間かかることがわかった。Rustを試したが、「Rustのルールを満たすコードを書くのに本当に苦労した」し、フォントレンダリングを機能させるために1か月を費やした。」[ 29 ]
ジグという名前は、文字zで始まる文字のランダムな組み合わせを生成するスクリプトを使用して選ばれました。[ 30 ]
以前のブートストラップコンパイラは、バックエンドとしてLLVMを使用してZigとC++で記述されており、 [ 31 ] [ 32 ]多くのネイティブターゲットをサポートしていましたが、[ 33 ]バージョン0.11で削除されました。新しいバージョンのZigは、ZigのプリビルドWebAssemblyバージョンを使用して自身をブートストラップします。
2025年11月26日、Zigの開発はGitHubからCodebergに移行した。主な理由としてGitHubの信頼性の低下が挙げられている。[ 34 ]
バージョン0.11.0には実験的なパッケージマネージャが同梱されていますが、公式のパッケージリポジトリは提供されていません。パッケージは、圧縮ファイルまたはGitリポジトリを指すURLです。各パッケージには、標準build.zigファイル(Zigコンパイラが慣例的にソースコードのコンパイルに使用するファイル)と、build.zig.zonパッケージの名前とバージョンを含むメタデータファイルが含まれているのが理想的です。
const std = @import ( "std" ); const File = std . Io . File ;pub fn main ( init : std . process . Init ) ! void { _ = try File . stdout (). writeStreamingAll ( init . io , "Hello, World! \n " ); }const std = @import ( "std" ); const FormatOptions = std . fmt . FormatOptions ; const stdout = std . io . getStdOut (). writer ();fn LinkedList ( comptime T : type ) type { return struct { const Self = @This ();pub const Node = struct { next : ?* Node = null , data : T , };最初: ?*ノード= null 、pub fn prepend ( list : * Self , new_node : * Node , ) void { new_node . next = list . first ; list . first = new_node ; }pub fn format ( list : Self , comptime fmt : [] const u8 , options : FormatOptions , out_stream : anytype , ) ! void { try out_stream . writeAll ( "( " );var it = list.first ; while ( it ) | node | : ( it = node.next ) { try std.fmt.formatType ( node.data , fmt , options , out_stream , 1 , ) ;try out_stream.writeAll ( " " ) ; }try out_stream.writeAll ( " )" ); } } ; }pub fn main () ! void { const ListU32 = LinkedList ( u32 );var list = ListU32 {}; var node1 = ListU32 。ノード{ .データ= 1 }; varノード 2 = ListU32 。ノード{ .データ= 2 }; varノード 3 = ListU32 。ノード{ .データ= 3 };list.prepend ( & node1 ) ; list.prepend ( & node2 ) ; list.prepend ( & node3 ) ;try stdout.print ( "{} \n " , .{ list }); try stdout.print ( " {b} \n " , . { list } ) ; }出力:
( 3 2 1 ) ( 11 10 1 )const std = @import ( "std" ); const ArenaAllocator = std . heap . ArenaAllocator ; const Allocator = std . mem . Allocator ;fn repeat ( allocator : Allocator , original : [] const u8 , times : usize , ) Allocator . Error ! [] u8 { const buffer = try allocator . alloc ( u8 , original . len * times , );for ( 0 .. times ) | i | { std.mem.copyForwards ( u8 , buffer [ ( original.len * i ) .. ] , original , ) ; }return buffer ; }pub fn main () ! void { var arena = ArenaAllocator . init ( std . heap . page_allocator , ); defer arena . deinit ();const allocator = arena.allocator ( ) ;const original = "Hello " ; const repeated = try repeat ( allocator , original , 3 , );std.debug.print ( "{s} \ n " , . { repeated } ) ; }出力:
こんにちは、こんにちは、こんにちはZigを使用している(または過去に使用していた)プロジェクトには、以下のようなものがあります。
{{cite web}}: CS1 maint: url-status (リンク)