การเขียนโปรแกรม D - ฟังก์ชั่น

บทนี้อธิบายถึงฟังก์ชันที่ใช้ในการเขียนโปรแกรม D

นิยามฟังก์ชันใน D

นิยามฟังก์ชันพื้นฐานประกอบด้วยส่วนหัวของฟังก์ชันและเนื้อหาของฟังก์ชัน

ไวยากรณ์

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

นี่คือส่วนทั้งหมดของฟังก์ชัน -

  • Return Type- ฟังก์ชันอาจส่งคืนค่า return_typeคือชนิดข้อมูลของค่าที่ฟังก์ชันส่งกลับ บางฟังก์ชันดำเนินการตามที่ต้องการโดยไม่ส่งคืนค่า ในกรณีนี้ return_type คือคีย์เวิร์ดvoid.

  • Function Name- นี่คือชื่อจริงของฟังก์ชัน ชื่อฟังก์ชันและรายการพารามิเตอร์ประกอบกันเป็นลายเซ็นฟังก์ชัน

  • Parameters- พารามิเตอร์เปรียบเสมือนตัวยึด เมื่อเรียกใช้ฟังก์ชันคุณจะส่งค่าไปยังพารามิเตอร์ ค่านี้เรียกว่าพารามิเตอร์หรืออาร์กิวเมนต์จริง รายการพารามิเตอร์หมายถึงประเภทลำดับและจำนวนของพารามิเตอร์ของฟังก์ชัน พารามิเตอร์เป็นทางเลือก นั่นคือฟังก์ชันอาจไม่มีพารามิเตอร์

  • Function Body - เนื้อความของฟังก์ชันประกอบด้วยชุดของคำสั่งที่กำหนดสิ่งที่ฟังก์ชันทำ

เรียกใช้ฟังก์ชัน

คุณสามารถเรียกใช้ฟังก์ชันได้ดังนี้ -

function_name(parameter_values)

ประเภทฟังก์ชันใน D

การเขียนโปรแกรม D รองรับฟังก์ชันที่หลากหลายและแสดงไว้ด้านล่าง

  • ฟังก์ชั่นที่แท้จริง
  • ฟังก์ชัน Nothrow
  • ฟังก์ชั่นอ้างอิง
  • ฟังก์ชั่นอัตโนมัติ
  • ฟังก์ชัน Variadic
  • ฟังก์ชัน Inout
  • ฟังก์ชั่นคุณสมบัติ

ฟังก์ชั่นต่างๆได้อธิบายไว้ด้านล่าง

ฟังก์ชั่นที่แท้จริง

ฟังก์ชั่นบริสุทธิ์คือฟังก์ชันที่ไม่สามารถเข้าถึงโกลบอลหรือสแตติกสถานะที่เปลี่ยนแปลงไม่ได้บันทึกผ่านอาร์กิวเมนต์ สิ่งนี้สามารถเปิดใช้งานการเพิ่มประสิทธิภาพตามข้อเท็จจริงที่ว่าฟังก์ชันบริสุทธิ์ได้รับการรับรองว่าจะไม่มีการกลายพันธุ์สิ่งใดที่ไม่ได้ส่งผ่านไปและในกรณีที่คอมไพเลอร์สามารถรับประกันได้ว่าฟังก์ชันบริสุทธิ์ไม่สามารถเปลี่ยนแปลงอาร์กิวเมนต์ได้ก็สามารถเปิดใช้งานความบริสุทธิ์ที่สมบูรณ์และใช้งานได้ คือการรับประกันว่าฟังก์ชันจะส่งคืนผลลัพธ์เดียวกันสำหรับอาร์กิวเมนต์เดียวกันเสมอ)

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

ฟังก์ชัน Nothrow

ฟังก์ชัน Nothrow ไม่ทิ้งข้อยกเว้นใด ๆ ที่ได้มาจาก class Exception ฟังก์ชั่น Nothrow นั้นเป็นมิตรกับคนขว้างปา

Nothrow รับประกันว่าฟังก์ชันจะไม่มีข้อยกเว้นใด ๆ

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

ฟังก์ชั่นอ้างอิง

ฟังก์ชัน Ref อนุญาตให้ฟังก์ชันส่งคืนโดยการอ้างอิง สิ่งนี้คล้ายคลึงกับพารามิเตอร์ฟังก์ชัน ref

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

ฟังก์ชัน Variadic

ฟังก์ชัน Variadiac คือฟังก์ชันที่กำหนดจำนวนพารามิเตอร์สำหรับฟังก์ชันในรันไทม์ ใน 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 สามารถใช้ได้ทั้งสำหรับพารามิเตอร์และชนิดของฟังก์ชันที่ส่งคืน มันเป็นเหมือนเทมเพลตสำหรับ mutable, const และไม่เปลี่ยนรูป แอตทริบิวต์ความผันแปรถูกอนุมานจากพารามิเตอร์ หมายความว่า 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