D 程式設計 - 函式



本章介紹了 D 程式設計中使用的函式。

D 中的函式定義

基本的函式定義包括函式頭和函式體。

語法

return_type function_name( parameter list ) { 
   body of the function 
}

以下是函式的所有部分:

  • 返回值型別 - 函式可以返回值。return_type 是函式返回值的資料型別。有些函式執行所需的運算而不返回值。在這種情況下,返回值型別是關鍵字void

  • 函式名 - 這是函式的實際名稱。函式名和引數列表一起構成函式簽名。

  • 引數 - 引數就像一個佔位符。當函式被呼叫時,您將值傳遞給引數。此值稱為實際引數或引數。引數列表指的是函式的引數的型別、順序和數量。引數是可選的;也就是說,函式可能不包含任何引數。

  • 函式體 - 函式體包含定義函式作用的一組語句。

呼叫函式

您可以按如下方式呼叫函式:

function_name(parameter_values)

D 中的函式型別

D 程式設計支援各種函式,如下所示。

  • 純函式
  • 無異常函式
  • 引用函式
  • 自動函式
  • 可變引數函式
  • 輸入輸出函式
  • 屬性函式

下面解釋了各種函式。

純函式

純函式是指無法訪問全域性或靜態、可變狀態(除非透過其引數)的函式。這可以啟用基於以下事實的最佳化:純函式保證不會修改未傳遞給它的任何內容,並且在編譯器可以保證純函式不會更改其引數的情況下,它可以啟用完全的函式純度,即保證該函式對於相同的引數始終返回相同的結果)。

import std.stdio; 

int x = 10; 
immutable int y = 30; 
const int* p;  

pure int purefunc(int i,const char* q,immutable int* s) { 
   //writeln("Simple print"); //cannot call impure function 'writeln'
   
   debug writeln("in foo()"); // ok, impure code allowed in debug statement 
   // x = i;  // error, modifying global state 
   // i = x;  // error, reading mutable global state 
   // i = *p; // error, reading const global state
   i = y;     // ok, reading immutable global state 
   auto myvar = new int;     // Can use the new expression: 
   return i; 
}

void main() { 
   writeln("Value returned from pure function : ",purefunc(x,null,null)); 
}

編譯並執行上述程式碼時,會產生以下結果:

Value returned from pure function : 30 

無異常函式

無異常函式不會丟擲任何從 Exception 類派生的異常。無異常函式與丟擲異常的函式是協變的。

無異常保證函式不會發出任何異常。

import std.stdio; 

int add(int a, int b) nothrow { 
   //writeln("adding"); This will fail because writeln may throw 
   int result; 
   
   try { 
      writeln("adding"); // compiles 
      result = a + b; 
   } catch (Exception error) { // catches all exceptions 
   }

   return result; 
} 
 
void main() { 
   writeln("Added value is ", add(10,20)); 
}

編譯並執行上述程式碼時,會產生以下結果:

adding 
Added value is 30 

引用函式

引用函式允許函式透過引用返回值。這類似於引用函式引數。

import std.stdio;

ref int greater(ref int first, ref int second) { 
   return (first > second) ? first : second; 
} 
 
void main() {
   int a = 1; 
   int b = 2;  
   
   greater(a, b) += 10;   
   writefln("a: %s, b: %s", a, b);   
}

編譯並執行上述程式碼時,會產生以下結果:

a: 1, b: 12

自動函式

自動函式可以返回任何型別的值。對要返回的型別沒有限制。下面給出了自動型別函式的一個簡單示例。

import std.stdio;

auto add(int first, double second) { 
   double result = first + second; 
   return result; 
} 

void main() { 
   int a = 1; 
   double b = 2.5; 
   
   writeln("add(a,b) = ", add(a, b)); 
}

編譯並執行上述程式碼時,會產生以下結果:

add(a,b) = 3.5

可變引數函式

可變引數函式是指函式的引數數量在執行時確定的函式。在 C 中,至少需要一個引數。但在 D 程式設計中,沒有這樣的限制。下面顯示了一個簡單的示例。

import std.stdio;
import core.vararg;

void printargs(int x, ...) {  
   for (int i = 0; i < _arguments.length; i++) {  
      write(_arguments[i]);  
   
      if (_arguments[i] == typeid(int)) { 
         int j = va_arg!(int)(_argptr); 
         writefln("\t%d", j); 
      } else if (_arguments[i] == typeid(long)) { 
         long j = va_arg!(long)(_argptr); 
         writefln("\t%d", j); 
      } else if (_arguments[i] == typeid(double)) { 
         double d = va_arg!(double)(_argptr); 
         writefln("\t%g", d); 
      } 
   } 
}
  
void main() { 
   printargs(1, 2, 3L, 4.5); 
}

編譯並執行上述程式碼時,會產生以下結果:

int 2 
long 3 
double 4.5

輸入輸出函式

inout 可用於函式的引數和返回值型別。它就像一個可變、常量和不可變的模板。可變性屬性是從引數推斷出來的。這意味著 inout 將推斷出的可變性屬性傳遞給返回值型別。下面顯示了一個簡單的示例,說明可變性是如何改變的。

import std.stdio;

inout(char)[] qoutedWord(inout(char)[] phrase) { 
   return '"' ~ phrase ~ '"';
}

void main() { 
   char[] a = "test a".dup; 

   a = qoutedWord(a); 
   writeln(typeof(qoutedWord(a)).stringof," ", a);  

   const(char)[] b = "test b"; 
   b = qoutedWord(b); 
   writeln(typeof(qoutedWord(b)).stringof," ", b); 

   immutable(char)[] c = "test c"; 
   c = qoutedWord(c); 
   writeln(typeof(qoutedWord(c)).stringof," ", c); 
} 

編譯並執行上述程式碼時,會產生以下結果:

char[] "test a" 
const(char)[] "test b" 
string "test c"

屬性函式

屬性允許像使用成員變數一樣使用成員函式。它使用 @property 關鍵字。屬性與相關的函式相關聯,這些函式根據需要返回值。下面給出了屬性的一個簡單示例。

import std.stdio;

struct Rectangle { 
   double width; 
   double height;  

   double area() const @property {  
      return width*height;  
   } 

   void area(double newArea) @property {  
      auto multiplier = newArea / area; 
      width *= multiplier; 
      writeln("Value set!");  
   } 
}

void main() { 
   auto rectangle = Rectangle(20,10); 
   writeln("The area is ", rectangle.area);  
   
   rectangle.area(300); 
   writeln("Modified width is ", rectangle.width); 
}

編譯並執行上述程式碼時,會產生以下結果:

The area is 200 
Value set! 
Modified width is 30
廣告