man!(Go => D).basics

既にGoで十分にプレイし、コピーペースト、型の手動ジャグリングにうんざりしていて、Pythonに戻ることを考えている場合、または、神に許されてPHPをお持ちの場合は、D言語を試してみてください。また、動的な類型化のある言語よりも表現力のあるコードを書くことができます。 そして、移行がそれほど苦痛ではなかったように、 Dの同等のコードと簡単な説明でTour of the Goの翻訳に注意を促します。



パート1 基本。



ハローワールド



行く



package main import "fmt" func main() { fmt.Println("Hello, 世界") }
      
      





D



 module main; import std.stdio; void main() { // stdout.writeln( "Hello, 世界" ); writeln( "Hello, 世界" ); }
      
      





Dで異なるモジュールからインポートされた名前の競合がない場合、名前空間を省略できることを除いて、違いは重要ではありません。 また、行末にセミコロンがある必須期間に注意を払う価値があります-Dでは、残念ながら義務です。



パッケージ



行く



 package main import ( "fmt" "math/rand" ) func main() { fmt.Println("My favorite number is", rand.Intn(10)) }
      
      





D



 module main; import std.stdio; import std.random; void main() { writeln( "My favorite number is ", uniform( 0 , 10 ) ); }
      
      





ここでも、インポート時、モジュールへのパスがGo中に示され、Dで「module」ディレクティブで指定されたモジュール名が使用されるか、このディレクティブが指定されていない場合はファイルパスから自動的に表示されることを除いて、すべて同じです。



輸入品



Goでは、インポートを1つのディレクティブにグループ化することをお勧めします。



 package main import ( "fmt" "math" ) func main() { fmt.Printf("Now you have %g problems.", math.Sqrt(7)) }
      
      





Dでは、これも可能ですが、構文機能はこれを優先しません。



 module main; import std.stdio, std.math; void main() { writefln( "Now you have %f problems.", 7f.sqrt ); }
      
      





さらに、Dでは、ファイルの先頭だけでなく、任意のブロックでインポートを指定できます。



 module main; void main() { import std.stdio; { import std.math; writefln( "Now you have %f problems.", 7f.sqrt ); } writefln( "Now you have %f problems.", 7f.sqrt ); // Error: no property 'sqrt' for type 'float' }
      
      





エクスポートされた名前



Goでは、モジュールは大文字で始まるもののみをエクスポートします。



 package main import ( "fmt" "math" ) func main() { fmt.Println(math.pi) // cannot refer to unexported name math.pi }
      
      





Dでは、モジュールのパブリックセクションで宣言されているもの(デフォルト)またはパブリックアクセス修飾子でマークされているもののみがDにエクスポートされます。



 module math; import std.math; auto PI = std.math.PI; private: public auto pip = std.math.PI; auto pi = std.math.PI;
      
      





 module main; import std.stdio; import math; void main() { writeln( PI ); writeln( pi ); // Error: module main variable math.pi is private writeln( pip ); }
      
      





モジュラーシステムDの詳細をご覧ください。



機能



行く



 package main import "fmt" // func add(x int, y int) int { func add(x, y int) int { return x + y } func main() { fmt.Println(add(42, 13)) }
      
      





D



 module main; import std.stdio; int add( int x , int y ) { return x + y; } void main() { // writeln( add( 42 , 13 ) ); writeln( 42.add( 13 ) ); }
      
      





Goでは通常、最後にタイプが続き、Dではより伝統的に-最初にタイプが続きます。 さらに、Dの関数はメソッドとして呼び出すことができます。これにより、サードパーティの型をエレガントに拡張できます。 Goでは、同じタイプのパラメーターを次から次へと繰り返さないようにすることができます。 また、Goにはない一般化されたプログラミングについて言及する価値があります。これにより、適切なタイプの関数をすぐに実装できます



 module main; import std.stdio; auto add( X , Y )( X x , Y y ) { return x + y; // Error: incompatible types for ((x) + (y)): 'int' and 'string' } void main() { // writeln( 42.add!( int , float )( 13.3 ) ); writeln( 42.add( 13.3 ) ); // 55.3 writeln( 42.add( "WTF?" ) ); // Error: template instance main.add!(int, string) error instantiating }
      
      





Dでは、任意の関数に対して、追加の括弧コンパイル時パラメーターを指定できます 。ここで、明示的に型を渡すか、コンパイラーが引数型から自動的に推測できます。



複数の結果



行く



 package main import "fmt" func swap(x, y string) (string, string) { return y, x } func main() { a, b := swap("hello", "world") fmt.Println(a, b) }
      
      





Dでは、関数からいくつかの個別の値を返す方法はありませんが、タプルを返すことができます。



 module main; import std.stdio; import std.typecons; auto swap( Item )( Item[2] arg... ) { return tuple( arg[1] , arg[0] ); } void main() { auto res = swap( "hello" , "world" ); writeln( res[0] , res[1] ); // worldhello }
      
      





また、必要に応じて、返されたタプルを既存の変数にアンパックすることもできます。



 module main; import std.stdio; import std.meta; import std.typecons; auto swap( Item )( Item[2] arg... ) { return tuple( arg[1] , arg[0] ); } void main() { string a , b; AliasSeq!( a , b ) = swap( "hello" , "world" ); writeln( a , b ); // worldhello }
      
      





名前付き戻り値



行く



 package main import "fmt" func split(sum int) (x, y int) { x = sum * 4 / 9 y = sum - x return } func main() { fmt.Println(split(17)) }
      
      





かなり疑わしい構文糖。 Dはこの種のものをサポートしていないため、名前付き要素を含む構造体またはタプルを返します。



 module main; import std.stdio; import std.typecons; auto split( int sum ) { auto x = sum * 4 / 9; auto y = sum - x; return tuple!( "x" , "y" )( x , y ); } void main() { // auto res = split( 17 ); writeln( res.x , res.y ); // writeln( split( 17 )[] ); writeln( 17.split[] ); // 710 }
      
      





演算子[]は、いわゆる「スライス」、つまり要素の配列を返します。



Dのタプルの詳細



変数



行く



 package main import "fmt" var c, python, java bool func main() { var i int fmt.Println(i, c, python, java) }
      
      





D



 module main; import std.stdio; // bool c , python , java; bool c; bool python; bool java; void main() { int i; writeln( i , c , python , java ); // 0falsefalsefalse }
      
      





一般に、Go構文が多少冗長であることを除いて、変数宣言は非常に似ています。



短い変数宣言



行く



 package main import "fmt" func main() { var i, j int = 1, 2 k := 3 c, python, java := true, false, "no!" fmt.Println(i, j, k, c, python, java) }
      
      





D



 module main; import std.stdio; void main() { int i = 1 , j = 2; auto k = 3; auto c = true , python = false , java = "no!"; writeln( i , j , k , c , python , java ); // 123truefalseno! }
      
      





どちらの言語も、初期化式から変数のタイプを推測できます。 ただし、変数宣言を名前のリストと値のリストに分割するGoアプローチはかなり曖昧で、エラーを引き起こします。



基本タイプ



タイプマッチングテーブル:



 Go D --------------------- void bool bool string string int int byte byte int8 byte int16 short int32 int int64 long uint unint uint8 ubyte uint16 ushort uint32 uint uint64 ulong uintptr size_t ptrdiff_t float32 float float64 double real ifloat idouble ireal complex64 cfloat complex128 cdouble creal char wchar rune dchar
      
      





大きな違いは、Goのintとuintのサイズはプラットフォームに依存しているのに対し、Dでは独立していることです。 また、Dは、虚数が実数と混同されないように制御します。 さらに、Dを使用すると、より大きなサイズ(80ビット)の実数と、より小さな(8ビットおよび16ビット)文字を操作できます。 Dの型の詳細



行く



 package main import ( "fmt" "math/cmplx" ) var ( ToBe bool = false MaxInt uint64 = 1<<64 - 1 z complex128 = cmplx.Sqrt(-5 + 12i) ) func main() { const f = "%T(%v)\n" fmt.Printf(f, ToBe, ToBe) fmt.Printf(f, MaxInt, MaxInt) fmt.Printf(f, z, z) }
      
      





D



 module main; import std.stdio; import std.math; bool ToBe = false; ulong MaxInt = ulong.max; cdouble z = sqrt( -5 + 12i ); void main() { enum f = "%s(%s)"; writefln( f , typeid( ToBe ) , ToBe ); // bool(false) writefln ( f , typeid( MaxInt ) , MaxInt ); // ulong(18446744073709551615) writefln( f , typeid( z ) , z ); // cdouble(2+3i) }
      
      





Dでは、各型には、基本的な型関連の定数を取得できるプロパティがあります。 D では 、「enum」キーワードを使用してコンパイル時定数が作成されることに注意してください-それらの値は使用場所にインラインで配置されます。 しかし、「const」キーワードの意味は少し異なります-これは変数の値を変更することを禁止するアクセス修飾子です(ただし、プログラム内の別の場所では編集アクセスが可能です)。



ゼロ値



行く



 package main import "fmt" func main() { var i int var f float64 var b bool var s string fmt.Printf("%v %v %v %q\n", i, f, b, s) // 0 0 false "" }
      
      





D



 module main; import std.stdio; void main() { writefln( "%s %s %s \"%s\"" , int.init , double.init , bool.init , string.init ); // 0 nan false "" }
      
      





Dでは、各タイプにはこのタイプのデフォルト値を格納する特別な「init」フィールドがあります。



型変換



Goでは、あるタイプから別のタイプに値を手動で変換する必要があります。



 package main import ( "fmt" "math" ) func main() { var x int = 3 var y uint = 4 var f float64 = math.Sqrt(float64(uint(x*x) + y*y)) var z uint = uint(f) fmt.Println(x, y, z) // 345 }
      
      





Dは、データの損失につながる可能性がある場合にのみ、手動の型変換を必要とするほどスマートです。



 module main; import std.stdio; import std.conv; void main() { int x = 3; uint y = 4; double f = ( x^^2 + y^^2 )^^0.5; uint z = f.to!uint; writeln( x , y , z ); // 345 }
      
      





数値定数



Goの数値定数を使用すると、実行時に損失なく使用できない数値を指定できます。



 package main import "fmt" const ( // Create a huge number by shifting a 1 bit left 100 places. // In other words, the binary number that is 1 followed by 100 zeroes. Big = 1 << 100 // Shift it right again 99 places, so we end up with 1<<1, or 2. Small = Big >> 99 ) func needInt(x int) int { return x*10 + 1 } func needFloat(x float64) float64 { return x * 0.1 } func main() { fmt.Println(needInt(Small)) // 21 fmt.Println(needInt(Big)) // constant 1267650600228229401496703205376 overflows int fmt.Println(needFloat(Small)) // 0.2 fmt.Println(needFloat(Big)) // 1.2676506002282295e+29 }
      
      





Dでは、コンパイルは実行時と同じ型を使用するため、定数値には同じ制限があります。



 module main; import std.stdio; enum Big = 1L << 100; // Error: shift by 100 is outside the range 0..63 enum Small = Big >> 99;
      
      






All Articles