ส่วนของเว็บไซต์
ตัวเลือกของบรรณาธิการ:
- แฟลชไดรฟ์ USB ตัวใดที่น่าเชื่อถือและเร็วที่สุด?
- การเชื่อมต่อแล็ปท็อปเข้ากับทีวีผ่านสาย USB เพื่อเชื่อมต่อแล็ปท็อปเข้ากับทีวี VGA
- การเปลี่ยนอินเทอร์เฟซ Steam - จากรูปภาพธรรมดาไปจนถึงการนำเสนอทั้งหมดบนหน้าจอ การออกแบบไอน้ำใหม่
- วิธียกเลิกการสมัครสมาชิก Megogo บนทีวี: คำแนะนำโดยละเอียด วิธียกเลิกการสมัครสมาชิก Megogo
- วิธีแบ่งพาร์ติชันดิสก์โดยติดตั้ง Windows โดยไม่สูญเสียข้อมูล แบ่งพาร์ติชันดิสก์ 7
- เหตุใดผู้จัดพิมพ์จึงไม่สามารถแก้ไขทุกหน้าได้
- ไม่มีการบู๊ตจากแฟลชไดรฟ์ใน BIOS - จะกำหนดค่าได้อย่างไร?
- รหัสโปรโมชั่น Pandao สำหรับคะแนน
- ไวรัสแรนซัมแวร์ที่เป็นอันตรายกำลังแพร่กระจายอย่างหนาแน่นบนอินเทอร์เน็ต
- การติดตั้ง RAM เพิ่มเติม
การโฆษณา
ชื่อฟังก์ชั่นในการเขียนโปรแกรมคืออะไร ฟังก์ชั่นการเขียนโปรแกรม |
วัตถุประสงค์ของงาน: 1) ศึกษากฎเกณฑ์ในการอธิบายฟังก์ชัน 2) ฝึกฝนทักษะการใช้ฟังก์ชันเมื่อเขียนโปรแกรมด้วยภาษา C++ ข้อมูลทางทฤษฎีโมดูลหลักของโปรแกรมในภาษา C++ คือฟังก์ชัน การทำงาน- ส่วนของโปรแกรมที่มีชื่อได้รับการออกแบบมาอย่างสมเหตุสมผลและมีเหตุผล ฟังก์ชันต่างๆ ช่วยให้คุณสามารถแบ่งงานการคำนวณขนาดใหญ่ออกเป็นส่วนย่อยๆ ได้ โปรแกรม C++ ทุกโปรแกรมจำเป็นต้องมีฟังก์ชันที่เรียกว่า main ซึ่งเป็นส่วนเนื้อหาของโปรแกรม สำหรับฟังก์ชันอื่นๆ ทั้งหมด หากมีอยู่ในโปรแกรม ก็ควรประกาศต้นแบบ - สัญลักษณ์แผนผังที่บอกชื่อและรูปแบบของแต่ละฟังก์ชันในโปรแกรมให้คอมไพเลอร์ทราบ ไวยากรณ์สำหรับฟังก์ชันต้นแบบพร้อมพารามิเตอร์คือ: return_value_type function_name (พารามิเตอร์_list_with_type_indication); ฟังก์ชันใน C++ เป็นแบบมาตรฐาน (ไลบรารี) และผู้ใช้สามารถตั้งโปรแกรมได้ คุณสมบัติมาตรฐานคำอธิบายของฟังก์ชันมาตรฐานมีอยู่ในไฟล์ที่รวมอยู่ในโปรแกรมโดยใช้คำสั่ง #include ไฟล์ดังกล่าวเรียกว่าไฟล์ส่วนหัว พวกเขามีนามสกุล h การอ้างถึงชื่อฟังก์ชันในโปรแกรมหลักเรียกว่าการเรียกใช้ฟังก์ชัน การเรียกใช้ฟังก์ชันส่งผลให้เกิดการดำเนินการบางอย่างหรือการคำนวณค่าบางค่า ซึ่งจะนำไปใช้ในโปรแกรม y = บาป(x); //ฟังก์ชันการคำนวณไซน์ นิยามฟังก์ชันโดยทั่วไป ฟังก์ชันจะถูกกำหนดดังนี้: return_value_type function_name (พิมพ์ parameter_name,..., พิมพ์ parameter_name) body_function คุณสมบัติที่ตั้งโปรแกรมได้ฟังก์ชั่นที่โปรแกรมเมอร์สร้างขึ้นเองทำให้กระบวนการเขียนโปรแกรมง่ายขึ้นเนื่องจาก: ช่วยหลีกเลี่ยงการตั้งโปรแกรมซ้ำเนื่องจากสามารถใช้ฟังก์ชันเดียวกันในโปรแกรมต่างๆได้ เพิ่มระดับของโมดูลาร์ของโปรแกรมจึงทำให้อ่าน แก้ไข และแก้ไขข้อผิดพลาดได้ง่ายขึ้น ตัวอย่าง9 .1. มาสร้างฟังก์ชันที่พิมพ์อักขระ 65 "*" ติดต่อกันกัน เพื่อให้ฟังก์ชันนี้ทำงานได้ในบางบริบท ฟังก์ชันนี้จะรวมอยู่ในโปรแกรมการพิมพ์หัวจดหมาย โปรแกรมประกอบด้วยฟังก์ชัน: main() และ stars() //หัวจดหมาย #รวม const int ขีดจำกัด = 65; ดาวเป็นโมฆะ(เป็นโมฆะ); // ฟังก์ชั่นต้นแบบ stars() ศาล<<"Moscow Institute of
Electronic Engineering"< // คำจำกัดความของฟังก์ชัน stars() สำหรับ (นับ = 1; นับ<=Limit; count++) เราดูตัวอย่างฟังก์ชันธรรมดาที่ไม่มีอาร์กิวเมนต์และไม่ส่งคืนค่าใดๆ ลองดูตัวอย่างการใช้พารามิเตอร์ฟังก์ชัน ตัวอย่าง9.
2.
มาเขียนฟังก์ชันสเปซ() กัน
ซึ่งอาร์กิวเมนต์จะเป็นจำนวนช่องว่างที่ฟังก์ชันนี้ควรพิมพ์ #กำหนดที่อยู่ "เซเลโนกราด" #กำหนดชื่อ "สถาบันมอสโกวิศวกรรมอิเล็กทรอนิกส์" #กำหนดแผนก “สารสนเทศและการเขียนโปรแกรม” const int LIMIT=65; #รวม พื้นที่ว่าง (หมายเลข int); ศาล< ช่องว่าง=(จำกัด - strlen(ชื่อ))/2; //คำนวณจำนวนเท่าไหร่ //ต้องการช่องว่าง ศาล< space((LIMIT - strlen(แผนก))/2); // อาร์กิวเมนต์ - การแสดงออก ศาล< //คำจำกัดความของฟังก์ชัน stars() สำหรับ (นับ = 1; นับ<=LIMIT; count++) //คำจำกัดความของฟังก์ชันช่องว่าง() พื้นที่ว่าง (หมายเลข int) สำหรับ (นับ = 1; นับ<=number; count++) ตัวแปรตัวเลขเรียกว่าอาร์กิวเมนต์ที่เป็นทางการ ตัวแปรนี้รับค่าของอาร์กิวเมนต์จริงเมื่อมีการเรียกใช้ฟังก์ชัน กล่าวอีกนัยหนึ่ง ข้อโต้แย้งอย่างเป็นทางการเป็นตัวแปรในคำจำกัดความของรูทีนย่อยที่เรียกว่า และ อาร์กิวเมนต์ที่เกิดขึ้นจริงคือค่าเฉพาะที่กำหนดให้กับตัวแปรนี้โดยโปรแกรมที่เรียก หากฟังก์ชันต้องการมากกว่าหนึ่งอาร์กิวเมนต์ในการสื่อสารด้วย คุณสามารถระบุรายการอาร์กิวเมนต์ที่คั่นด้วยเครื่องหมายจุลภาคพร้อมกับชื่อฟังก์ชันได้: เป็นโมฆะ printnum (int i, int j) ( โต้แย้ง<<"Координаты
точек”<< i << j < ค่าอินพุตของฟังก์ชันสามารถประมวลผลได้เนื่องจากมีอยู่ การโต้แย้ง- ค่าเอาต์พุตจะถูกส่งกลับโดยใช้คีย์เวิร์ด return ผู้ใช้ที่อยู่ห่างไกลจากการเขียนโปรแกรมโดยหลักการมักไม่ค่อยพบกับแนวคิดของฟังก์ชันและขั้นตอนการทำงาน และเกี่ยวข้องกับบางสิ่งทางคณิตศาสตร์และทางราชการและการแพทย์ ในการเขียนโปรแกรม หลายภาษาดำเนินการตามแนวคิดเหล่านี้ อย่างไรก็ตาม บางครั้งแม้แต่ผู้เชี่ยวชาญก็ไม่สามารถเข้าใจความแตกต่างระหว่างฟังก์ชันและขั้นตอนได้อย่างชัดเจน เช่นเดียวกับโกเฟอร์ตัวนั้น มันอยู่ที่นั่นแต่ไม่มีใครเห็น มาดูกันว่าความแตกต่างนั้นมองไม่เห็นหรือไม่ ความแตกต่างที่สำคัญระหว่างฟังก์ชันและโพรซีเดอร์คือผลลัพธ์ที่ส่งคืน ในความเป็นจริง ทั้งฟังก์ชันและโพรซีเดอร์เป็นบล็อกที่แยกไม่ออกทางตรรกะซึ่งประกอบเป็นโค้ดโปรแกรม ฟังก์ชันส่งคืนค่า ขั้นตอนในภาษาการเขียนโปรแกรมส่วนใหญ่ไม่ส่งคืนค่าว่าง หรือ (เช่น ในภาษา C) ในกรณีหลัง (ในภาษา C) โพรซีเดอร์ถือเป็นเวอร์ชันรองของฟังก์ชัน ส่วนหัวของฟังก์ชันประกอบด้วยคำว่า "ฟังก์ชัน" ตัวระบุ (ชื่อที่ถูกต้องของฟังก์ชัน) หรือรายการพารามิเตอร์ (ไม่บังคับ) และประเภทของผลลัพธ์ เนื้อความของฟังก์ชันจะต้องมีตัวดำเนินการที่กำหนดค่าให้กับชื่อฟังก์ชัน ซึ่งจะถูกส่งกลับตามมา ส่วนหัวของขั้นตอนประกอบด้วยคำว่า "ขั้นตอน" ตัวระบุ (ชื่อขั้นตอน) และรายการพารามิเตอร์ (ไม่บังคับ) การเรียกใช้ฟังก์ชันจะดำเนินการโดยเป็นส่วนหนึ่งของนิพจน์ที่ใช้นิพจน์เหล่านี้ การเรียกใช้โพรซีเจอร์ต้องใช้คำสั่งแยกต่างหาก โพรซีเดอร์ถูกเรียกตามชื่อเท่านั้น ในขณะที่ชื่อของฟังก์ชันเชื่อมโยงกับค่าของมัน ในแผนภาพอัลกอริทึม การเรียกใช้ฟังก์ชันจะแสดงในบล็อกเอาต์พุตหรือในบล็อกกระบวนการ การเรียกขั้นตอนจะแสดงในบล็อก "กระบวนการที่กำหนดไว้ล่วงหน้า" พิเศษ พื้นฐานของโปรแกรมคอมพิวเตอร์คืออัลกอริธึมซึ่งแสดงเป็นคำสั่ง คนที่เขียนโค้ดบอกว่า เอาอันนี้ ทำนี่ อันนี้ และอันนั้นด้วย แล้วเอาท์พุทผลลัพธ์ตรงนั้นแล้วพัก ดังนั้น เพื่อให้คำสั่งในโปรแกรมไม่ผสานรวมเป็นระเบียบเดียวและสามารถโต้ตอบซึ่งกันและกันได้ จึงจัดกลุ่มออกเป็นฟังก์ชันและขั้นตอนที่เรียกว่า เราจะทำความคุ้นเคยกับแนวคิดเหล่านี้ มีการใช้ชื่อฟังก์ชัน: 1) เพื่อสร้างเอกสาร; 2) สำหรับ API นั่นคืออินเทอร์เฟซสำหรับเชื่อมต่อกับโปรแกรมหรือระบบปฏิบัติการทั้งหมดของแอปพลิเคชันใด ๆ ดังนั้นจึงสมเหตุสมผลที่จะเตือนอีกครั้งว่าควรตั้งชื่อเหล่านี้ให้เข้าใจง่ายและหากเป็นไปได้ควรให้เหมาะสมกับการดำเนินการที่กำลังดำเนินการอยู่ ดังนั้นฟังก์ชันจึงเป็นคอนเทนเนอร์ชนิดหนึ่งสำหรับการจัดกลุ่มอัลกอริธึม พวกเขา: จริง ๆ แล้วขั้นตอนเป็นฟังก์ชันเดียวกัน แม้ว่าจะ "ว่างเปล่า" และไม่ส่งคืนสิ่งใดเลย (นี่คือข้อแตกต่างหลัก) เครื่องมือเหล่านี้เป็นเครื่องมือเสริมที่ออกแบบมาเพื่อดำเนินการตามปกติ ตลอดจนประหยัดพื้นที่ ความพยายาม และเวลา สิ่งพิมพ์ก่อนหน้า: ไม่ใช่เพื่ออะไรที่ฉันเรียกบทความนี้ว่า "ฟังก์ชั่นที่เป็นส่วนสำคัญของการเขียนโปรแกรม" เพราะในความคิดของฉันหากไม่มีพวกเขาไม่มีภาษาใดมีสิทธิ์ดำรงอยู่ นี่คืออะไร? ฟังก์ชันเป็นองค์ประกอบหลักของโปรแกรมที่เขียนมาอย่างดี ไม่เพียงทำให้โค้ดอ่านง่ายขึ้น แต่ยังเปลี่ยนแนวคิดของการเขียนโปรแกรมแบบมีโครงสร้างอย่างรุนแรงอีกด้วย ด้วยความช่วยเหลือของฟังก์ชัน คุณสามารถนำแต่ละส่วนของโปรแกรมกลับมาใช้ใหม่ได้โดยส่งพารามิเตอร์ใดๆ ให้พวกเขา ไม่มีโปรแกรมที่จริงจังใดที่สามารถจินตนาการได้หากไม่มีองค์ประกอบการเขียนโปรแกรมที่น่าอัศจรรย์นี้ ฉันจะบอกคุณสั้น ๆ ว่ามันทำงานอย่างไร ฟังก์ชันคือชุดคำสั่งที่โปรแกรมของคุณสามารถเรียกใช้ได้ เมื่อเข้าถึงส่วนหัวของบล็อกนี้ (ชื่อฟังก์ชัน) มันจะถูกดำเนินการและดำเนินการบางอย่างที่ระบุโดยโปรแกรมเมอร์ หลังจากนั้นบล็อกนี้จะส่งคืนค่าที่ได้รับและส่งผ่านไปยังโปรแกรมหลัก ให้ฉันอธิบายในทางปฏิบัติ
ถ้าพูดคร่าวๆ ก็คงประมาณนี้ครับ ให้ฉันอธิบายสั้น ๆ เราสร้างตัวแปรบางตัวและกำหนดผลลัพธ์ของการดำเนินการฟังก์ชัน myfunc ซึ่งจะคำนวณค่าของการยกกำลังสองตัวเลข ฟังก์ชั่นจะไม่ถูกดำเนินการทันทีเมื่อโปรแกรมเริ่มทำงาน แต่จะถูกดำเนินการเมื่อมีการเรียกใช้เท่านั้น มันอาจจะสับสนนิดหน่อย แต่มันก็เป็นเช่นนั้น ในการเรียกใช้ฟังก์ชัน คุณต้องสร้างมันขึ้นมา แม้ว่าจะมีฟังก์ชั่นในตัวด้วย ตัวอย่างเช่น: cos, sin, md5, นับ, หน้าท้องและอื่น ๆ หากต้องการเรียกมัน คุณเพียงแค่ต้องกำหนดค่าที่ต้องการให้กับตัวแปร
อาร์กิวเมนต์ของฟังก์ชันคือค่าที่คุณส่งไปให้ฟังก์ชันนั้นเมื่อคุณเรียกใช้ อาร์กิวเมนต์ของฟังก์ชันจะอยู่ในวงเล็บ เมื่อสร้างฟังก์ชัน คุณจะต้องระบุชื่อที่มีเงื่อนไขสำหรับอาร์กิวเมนต์ จากนั้นชื่อเหล่านี้สามารถนำมาใช้ในเนื้อความของฟังก์ชันเป็นตัวแปรท้องถิ่นได้ กลับมาที่ฟังก์ชั่นที่ผู้ใช้สร้างขึ้นเอง ทำได้ง่ายมาก ขั้นแรก เนื้อหาของฟังก์ชันจะถูกสร้างขึ้น: ฟังก์ชั่น hello() ( echo "Hello, world!"; ) แล้วเราก็โทรหาเธอ ยิ่งกว่านั้น ถ้ามันไม่มีพารามิเตอร์ เราก็เพียงแค่ใส่วงเล็บ ในการเรียกใช้ฟังก์ชันนี้ เราใช้เพียงบรรทัด: สวัสดี();- ฟังก์ชันใดๆ ก็สามารถคืนค่าโดยใช้คำสงวนได้ กลับ- คำสั่งนี้จะหยุดการดำเนินการฟังก์ชันและส่งค่าส่งคืนไปยังโปรแกรมที่เรียก ฟังก์ชั่น sum($first, $second) ($r=$first + $second; return $r;) echo sum(2,5); ผลลัพธ์ของการทำงานของโปรแกรมจะเท่ากับ 7 ตัวแปรท้องถิ่นและระดับโลก เช่นเดียวกับในภาษาการเขียนโปรแกรมอื่นๆ มีตัวแปรที่มีเฉพาะภายในฟังก์ชันเท่านั้น และตัวแปรที่มีอยู่ในโค้ดของโปรแกรมเอง ตัวแปรดังกล่าวเรียกว่าท้องถิ่นและทั่วโลกตามลำดับ ภายในฟังก์ชัน คุณไม่สามารถเข้าถึงตัวแปรที่สร้างขึ้นภายนอกฟังก์ชันได้ง่ายๆ หากคุณพยายามทำเช่นนี้ คุณจะสร้างตัวแปรใหม่ที่มีชื่อเดียวกัน แต่อยู่ในฟังก์ชันนี้ $per="ดิมา"; ฟังก์ชั่นไพรเมอร์() // ดำเนินการ: แสดงตัวแปรท้องถิ่น ( echo "My name is ".$per; ) echo primer(); ในกรณีนี้ วลี “ฉันชื่อ” จะปรากฏบนหน้าจอ ซึ่งหมายความว่าตัวแปร $per ถูกสร้างขึ้นภายในฟังก์ชันไพรเมอร์ และกำหนดค่าเป็นศูนย์ตามค่าเริ่มต้น เพื่อหลีกเลี่ยงวงกบดังกล่าว คุณต้องใช้ตัวดำเนินการ ทั่วโลก- มาแก้ไขโค้ดด้านบนให้ถูกต้อง: $per="ดิมา"; ฟังก์ชั่นไพรเมอร์() // ดำเนินการ: แสดงตัวแปรโกลบอล ( global $per; echo "ฉันชื่อ ".$per; ) echo primer(); ตอนนี้ทุกอย่างควรจะเรียบร้อยดี - แก้ไขปัญหาแล้ว อย่าลืมว่าหากฟังก์ชันเปลี่ยนค่าของตัวแปรภายนอก การเปลี่ยนแปลงดังกล่าวจะส่งผลต่อโปรแกรมทั้งหมด ดังนั้นคุณจึงจำเป็นต้องใช้โอเปอเรเตอร์นี้อย่างระมัดระวัง! อาร์กิวเมนต์บางข้อที่ส่งไปยังฟังก์ชันสามารถกำหนดให้เป็นทางเลือกได้ ทำให้ฟังก์ชันมีความต้องการน้อยลง ตัวอย่างต่อไปนี้แสดงให้เห็นอย่างชัดเจน: … function font($text, $size=5) // Do: ขนาดฟอนต์เอาท์พุต ( echo " ".$ข้อความ"; ) แบบอักษร("สวัสดี ขนาดตัวอักษรคือ 5 หากเราละเว้นพารามิเตอร์ตัวที่สองของฟังก์ชัน มันจะเท่ากับค่านี้ ก่อนที่ฉันจะกล่าวคำอำลา ฉันอยากจะดึงความสนใจของคุณไปที่คำแนะนำสักข้อหนึ่ง ประกอบด้วยการรวมฟังก์ชันทั้งหมดที่คุณเขียนไว้ในไฟล์เดียว (เช่น function.php) จากนั้นในไฟล์ที่คุณต้องการเรียกใช้ฟังก์ชัน คุณเพียงแค่ต้องรวม function.php แล้วทุกอย่างก็จะพร้อมใช้งาน ซึ่งจะทำให้เข้าใจตรรกะในโปรแกรมของคุณได้ง่ายขึ้นมาก หากต้องการเชื่อมต่อ ให้ใช้: include_once("function.php"); need_once("function.php"); หากคุณเข้าใจสาระสำคัญของปัญหาที่กล่าวถึงในบทความนี้ ฉันมั่นใจว่าคุณสามารถใช้ฟังก์ชันต่างๆ ในโปรแกรมของคุณได้อย่างง่ายดาย นี่เป็นอีกครั้งหนึ่งที่ทำให้สามารถปรับเปลี่ยนและนำกลับมาใช้ใหม่ได้มากขึ้น นี่เป็นบทความที่สามในซีรีส์ “ทฤษฎีหมวดหมู่สำหรับโปรแกรมเมอร์” ด้วยภาษาเครื่อง การรวมกันของไบต์ใดๆ ที่สร้างโดยลิงจะได้รับการยอมรับและดำเนินการ แต่ในภาษาระดับสูง มีคุณค่าอย่างมากที่คอมไพเลอร์สามารถตรวจจับข้อผิดพลาดด้านคำศัพท์และไวยากรณ์ได้ หลายโปรแกรมจะถูกปฏิเสธ และลิงก็จะถูกทิ้งไว้โดยไม่มีกล้วย แต่ที่เหลือจะมีโอกาสที่ดีกว่าที่จะมีความหมาย การตรวจสอบประเภทเป็นอุปสรรคต่อโปรแกรมไร้สาระอีกประการหนึ่ง นอกจากนี้ ในขณะที่ประเภทภาษาที่พิมพ์แบบไดนามิกไม่ตรงกันจะถูกตรวจพบเฉพาะที่รันไทม์เท่านั้น แต่สำหรับประเภทภาษาที่มีการตรวจสอบแบบคงที่อย่างเข้มงวดจะถูกตรวจพบในเวลารวบรวม ซึ่งจะกำจัดโปรแกรมที่ไม่ถูกต้องจำนวนมากก่อนที่จะมีโอกาสที่จะดำเนินการ คำถามก็คือ เราอยากให้ลิงมีความสุขหรือสร้างโปรแกรมที่ถูกต้องขึ้นมา? โดยปกติแล้ว เป้าหมายของการทดลองคิดแบบลิงพิมพ์คือการสร้างผลงานที่สมบูรณ์ของเช็คสเปียร์ (หมายเหตุผู้แปล: หรือสงครามและสันติภาพของตอลสตอย)- การตรวจสอบการสะกดและไวยากรณ์แบบวนซ้ำจะช่วยเพิ่มโอกาสสำเร็จได้อย่างมาก การตรวจสอบประเภทแอนะล็อกมีการพัฒนาไปไกลกว่านั้น: หลังจากที่โรมิโอถูกประกาศว่าเป็นมนุษย์ การตรวจสอบประเภทจะทำให้แน่ใจได้ว่าโรมิโอจะไม่ทำให้ใบไม้เติบโต และจะไม่จับโฟตอนด้วยสนามโน้มถ่วงอันทรงพลังของเขา ข้อโต้แย้งที่ร้ายแรงข้อเดียวที่ฉันได้ยินเกี่ยวกับการพิมพ์คงที่ที่รุนแรงคืออาจปฏิเสธบางโปรแกรมที่มีความหมายถูกต้อง ในทางปฏิบัติสิ่งนี้เกิดขึ้นน้อยมาก (หมายเหตุผู้แปล: เพื่อหลีกเลี่ยงความสับสน ฉันทราบว่าผู้เขียนไม่ได้คำนึงถึงหรือไม่เห็นด้วยว่ามีหลายรูปแบบ และการพิมพ์แบบเป็ดซึ่งโปรแกรมเมอร์คุ้นเคยในภาษาสคริปต์ก็มีสิทธิ์ที่จะมีชีวิตเช่นกัน บน ในทางกลับกัน การพิมพ์เป็ดสามารถทำได้ในระบบการพิมพ์ที่เข้มงวดผ่านเทมเพลต ลักษณะ คลาสประเภท อินเทอร์เฟซ มีเทคโนโลยีมากมาย ดังนั้นความคิดเห็นของผู้เขียนจึงถือว่าไม่ถูกต้องอย่างยิ่ง)และไม่ว่าในกรณีใด ทุกภาษาจะมีประตูหลังบางประเภทเพื่อหลีกเลี่ยงระบบการพิมพ์เมื่อจำเป็นจริงๆ แม้แต่ Haskell ก็ยังมีการบังคับที่ไม่ปลอดภัย แต่การออกแบบดังกล่าวจะต้องใช้อย่างชาญฉลาด Gregor Samsa ตัวละครของ Franz Kafka ทำลายระบบการพิมพ์เมื่อเขากลายเป็นแมลงเต่าทองยักษ์ และเราทุกคนต่างก็รู้ว่ามันจะจบลงอย่างไร (หมายเหตุผู้แปล: ไม่ดี :). ข้อโต้แย้งอีกประการหนึ่งที่ฉันได้ยินบ่อยคือการพิมพ์ที่แข็งแกร่งทำให้โปรแกรมเมอร์มีภาระมากเกินไป ฉันเห็นอกเห็นใจกับปัญหานี้ โดยที่ได้เขียนการประกาศตัววนซ้ำหลายครั้งด้วยตัวเองในภาษา C++ ยกเว้นว่ามีเทคโนโลยี การอนุมานประเภท ที่ช่วยให้คอมไพเลอร์สามารถอนุมานประเภทส่วนใหญ่จากบริบทที่ใช้งาน ในภาษา C++ คุณสามารถประกาศตัวแปรได้ auto และคอมไพลเลอร์จะอนุมานประเภทให้กับคุณ ใน Haskell ยกเว้นในบางกรณีที่เกิดขึ้นไม่บ่อยนัก ประเภทคำอธิบายประกอบเป็นทางเลือก โปรแกรมเมอร์มักจะใช้พวกมันเพราะว่า Types สามารถบอกคุณได้มากมายเกี่ยวกับความหมายของโค้ดของคุณ และการประกาศประเภทจะช่วยให้คุณเข้าใจข้อผิดพลาดในการคอมไพล์ แนวทางปฏิบัติทั่วไปใน Haskell คือการเริ่มต้นโครงการโดยการพัฒนาประเภทต่างๆ ต่อมา พิมพ์คำอธิบายประกอบเป็นพื้นฐานของการใช้งานและกลายเป็นความคิดเห็นที่รับประกันโดยคอมไพเลอร์ การพิมพ์แบบคงที่ขั้นสูงมักถูกใช้เป็นข้ออ้างในการไม่ทดสอบโค้ด บางครั้งคุณจะได้ยินโปรแกรมเมอร์ของ Haskell พูดว่า "ถ้าโค้ดถูกสร้างขึ้น แสดงว่าถูกต้อง" แน่นอนว่าไม่มีการรับประกันว่าโปรแกรมที่พิมพ์ถูกต้องนั้นถูกต้องในแง่ของการสร้างผลลัพธ์ที่ถูกต้อง จากทัศนคตินี้ในการศึกษาจำนวนหนึ่ง Haskell ไม่ได้มีประสิทธิภาพเหนือกว่าภาษาอื่นอย่างมีนัยสำคัญในด้านคุณภาพโค้ดอย่างที่ใคร ๆ คาดหวัง ดูเหมือนว่าในเชิงพาณิชย์ ความจำเป็นในการแก้ไขข้อบกพร่องนั้นมีอยู่จนถึงระดับคุณภาพหนึ่งเท่านั้น ซึ่งส่วนใหญ่เกี่ยวข้องกับเศรษฐศาสตร์ของการพัฒนาซอฟต์แวร์และความอดทนของผู้ใช้ปลายทาง และมีส่วนเกี่ยวข้องกับภาษาการเขียนโปรแกรมหรือการพัฒนาเพียงเล็กน้อยเท่านั้น วิธีการ การวัดที่ดีกว่าคือการวัดจำนวนโครงการที่ล่าช้ากว่ากำหนดหรือส่งมอบโดยมีฟังก์ชันการทำงานลดลงอย่างมาก ตอนนี้เกี่ยวกับการอ้างว่าการทดสอบหน่วยสามารถแทนที่การพิมพ์ที่แข็งแกร่งได้ มาดูแนวทางปฏิบัติทั่วไปในการปรับโครงสร้างใหม่ในภาษาที่พิมพ์อย่างรุนแรง: การเปลี่ยนประเภทของอาร์กิวเมนต์เป็นฟังก์ชัน ในภาษาที่พิมพ์อย่างเข้มงวด การเปลี่ยนแปลงการประกาศของฟังก์ชันนี้ก็เพียงพอแล้ว จากนั้นแก้ไขข้อผิดพลาดของบิลด์ ในภาษาที่พิมพ์ไม่ชัดเจน ความจริงที่ว่าฟังก์ชันกำลังคาดหวังว่าข้อมูลอื่นจะไม่สามารถนำมาประกอบกับผู้โทรได้ การทดสอบหน่วยอาจตรวจพบความไม่สอดคล้องกันบางส่วน แต่การทดสอบมักจะเป็นไปตามความน่าจะเป็นมากกว่ากระบวนการที่กำหนด (หมายเหตุผู้แปล: บางทีอาจหมายถึงชุดการทดสอบ: คุณไม่ครอบคลุมอินพุตที่เป็นไปได้ทั้งหมด แต่ครอบคลุมตัวอย่างที่เป็นตัวแทนบางส่วน)การทดสอบเป็นสิ่งทดแทนการพิสูจน์ความถูกต้องได้ไม่ดี เซตสามารถมีขอบเขตหรือไม่มีที่สิ้นสุด ประเภทสตริง ซึ่งโดยพื้นฐานแล้วเป็นคำพ้องสำหรับรายการถ่าน เป็นตัวอย่างของเซตที่ไม่มีที่สิ้นสุด เมื่อเราประกาศ x เป็นจำนวนเต็ม: มีรายละเอียดปลีกย่อยบางประการที่ทำให้การจับคู่ประเภทกับเซตเป็นเรื่องยาก มีปัญหากับฟังก์ชันโพลีมอร์ฟิกที่มีคำจำกัดความแบบวนรอบ และข้อเท็จจริงที่ว่าคุณไม่สามารถมีเซตของเซตทั้งหมดได้ แต่อย่างที่ฉันสัญญาไว้ ฉันจะไม่เป็นนักคณิตศาสตร์ที่เข้มงวด สิ่งสำคัญคือมีหมวดหมู่ของเซ็ตที่เรียกว่า Set และเราจะดำเนินการกับมัน ชุดเป็นหมวดหมู่พิเศษเพราะเราสามารถมองเข้าไปในวัตถุได้ และสิ่งนี้จะช่วยให้เราเข้าใจได้อย่างสังหรณ์ใจมาก ตัวอย่างเช่น เรารู้ว่าเซตว่างไม่มีสมาชิก เรารู้ว่ามีชุดพิเศษขององค์ประกอบเดียว เรารู้ว่าฟังก์ชันองค์ประกอบแผนที่ของชุดหนึ่งเป็นองค์ประกอบของอีกชุดหนึ่ง พวกเขาสามารถแมปสององค์ประกอบให้เป็นหนึ่งเดียวได้ แต่ไม่ใช่องค์ประกอบเดียวให้เป็นสอง เรารู้ว่าฟังก์ชันเอกลักษณ์จับคู่แต่ละองค์ประกอบของเซตไว้ในตัวมันเอง และอื่นๆ ฉันวางแผนที่จะค่อยๆ ลืมข้อมูลทั้งหมดนี้ และแทนที่จะแสดงแนวคิดเหล่านี้ทั้งหมดในรูปแบบหมวดหมู่ล้วนๆ นั่นก็คือ ในแง่ของวัตถุและลูกศร ในโลกอุดมคติ เราสามารถพูดได้ว่าประเภทใน Haskell เป็นเซต และฟังก์ชันใน Haskell เป็นฟังก์ชันทางคณิตศาสตร์ที่อยู่ระหว่างนั้น มีปัญหาเล็กๆ น้อยๆ ประการหนึ่ง นั่นคือ ฟังก์ชันทางคณิตศาสตร์ไม่ได้ใช้โค้ดใดๆ แต่รู้เพียงคำตอบเท่านั้น ฟังก์ชันใน Haskell จะต้องคำนวณคำตอบ นี่ไม่ใช่ปัญหาหากสามารถหาคำตอบได้ในจำนวนขั้นตอนที่จำกัด ไม่ว่าจะมากเพียงใด แต่มีการคำนวณบางอย่างที่เกี่ยวข้องกับการเรียกซ้ำ และการคำนวณเหล่านั้นอาจไม่มีวันเสร็จสิ้น เราไม่สามารถยกเลิกการอนุญาตฟังก์ชันที่ไม่ยุติใน Haskell ได้ เนื่องจากการแยกแยะว่าฟังก์ชันยุติหรือไม่ (ปัญหาการหยุดอันโด่งดัง) นั้นไม่สามารถแก้ไขได้ นั่นเป็นสาเหตุที่นักวิทยาศาสตร์คอมพิวเตอร์เกิดแนวคิดที่ยอดเยี่ยม หรือการแฮ็กสกปรก ขึ้นอยู่กับมุมมองของคุณ เพื่อขยายแต่ละประเภทด้วยค่าพิเศษที่เรียกว่า ก้น (หมายเหตุผู้แปล: คำนี้ (ล่าง) ฟังดูงี่เง่าในภาษารัสเซีย ถ้าใครรู้ตัวเลือกที่ดีช่วยแนะนำด้วย)ซึ่งเขียนแทนด้วย _|_ หรือใน Unicode ⊥ "ค่า" นี้สอดคล้องกับการคำนวณที่ไม่สมบูรณ์ ดังนั้นฟังก์ชันจึงประกาศเป็น: สิ่งที่น่าสนใจคือ เมื่อคุณยอมรับ Bottom ลงในระบบประเภทแล้ว จะสะดวกที่จะถือว่าข้อผิดพลาดรันไทม์ทั้งหมดเป็นด้านล่าง และแม้แต่อนุญาตให้ฟังก์ชันส่งคืนด้านล่างอย่างชัดเจน อย่างหลังมักจะทำโดยใช้นิพจน์ที่ไม่ได้กำหนด: ฟังก์ชันที่สามารถคืนค่าด้านล่างเรียกว่าฟังก์ชันบางส่วน ซึ่งตรงข้ามกับฟังก์ชันปกติที่ส่งคืนผลลัพธ์ที่ถูกต้องสำหรับอาร์กิวเมนต์ที่เป็นไปได้ทั้งหมด เนื่องจากด้านล่าง หมวดหมู่ของประเภทและฟังก์ชันของ Haskell จึงเรียกว่า Hask ไม่ใช่ Set จากมุมมองทางทฤษฎี นี่เป็นสาเหตุของภาวะแทรกซ้อนที่ไม่มีที่สิ้นสุด ดังนั้น ณ จุดนี้ ฉันจะใช้มีดแล่เนื้อและเรียกมันว่าวันละครั้ง จากมุมมองเชิงปฏิบัติ คุณสามารถละเว้นฟังก์ชันที่ไม่สิ้นสุดและด้านล่าง และถือว่า Hask เป็นชุดที่เต็มเปี่ยม มีวิธีที่เป็นทางการในการอธิบายความหมายของภาษา แต่เนื่องจากความซับซ้อน จึงมักใช้กับภาษาวิชาการที่เรียบง่าย แทนที่จะเป็นโปรแกรมยักษ์ใหญ่ทางอุตสาหกรรม หนึ่งในเครื่องมือเหล่านี้เรียกว่าอรรถศาสตร์ในการดำเนินงานและอธิบายกลไกการทำงานของโปรแกรม มันกำหนดล่ามที่เป็นทางการและมีอุดมคติ ความหมายของภาษาอุตสาหกรรม เช่น C++ โดยทั่วไปจะอธิบายโดยใช้การให้เหตุผลแบบไม่เป็นทางการ มักอยู่ในรูปแบบของ "เครื่องจักรเชิงนามธรรม" ปัญหาคือมันเป็นเรื่องยากมากที่จะพิสูจน์อะไรเกี่ยวกับโปรแกรมที่ใช้ความหมายเชิงปฏิบัติการ ในการแสดงคุณสมบัติของโปรแกรม คุณจะต้อง "รันมัน" ผ่านล่ามในอุดมคติ ไม่สำคัญว่าโปรแกรมเมอร์จะไม่มีวันพิสูจน์ความถูกต้องอย่างเป็นทางการ เรามักจะ "คิด" เสมอว่าเรากำลังเขียนโปรแกรมที่ถูกต้อง ไม่มีใครนั่งที่คีย์บอร์ดและพูดว่า "โอ้ ฉันจะเขียนโค้ดสองสามบรรทัดแล้วดูว่าจะเกิดอะไรขึ้น" (หมายเหตุผู้แปล: โอ้ ถ้าเพียง...)เราเชื่อว่าโค้ดที่เราเขียนจะดำเนินการบางอย่างที่จะให้ผลลัพธ์ที่ต้องการ เรามักจะแปลกใจมากถ้าไม่เป็นเช่นนั้น ซึ่งหมายความว่าจริงๆ แล้วเราคิดถึงโปรแกรมที่เราเขียน และโดยทั่วไปเราจะทำเช่นนี้โดยใช้ล่ามในหัวของเรา เพียงแต่ การติดตามตัวแปรทั้งหมดเป็นเรื่องยากมาก คอมพิวเตอร์เก่งในการรันโปรแกรม แต่คนไม่เก่ง! ถ้าเป็นเรา เราก็ไม่ต้องการคอมพิวเตอร์ แต่มีทางเลือกอื่น มันถูกเรียกว่าความหมายเชิง denotational และขึ้นอยู่กับคณิตศาสตร์ ในความหมายเชิง denotational มีการอธิบายการตีความทางคณิตศาสตร์สำหรับโครงสร้างทางภาษาแต่ละรายการ ดังนั้น หากคุณต้องการพิสูจน์คุณสมบัติของโปรแกรม คุณก็แค่พิสูจน์ทฤษฎีบททางคณิตศาสตร์เท่านั้น คุณคิดว่าทฤษฎีบทการพิสูจน์เป็นเรื่องยาก แต่จริงๆ แล้ว มนุษย์อย่างเราสร้างวิธีการทางคณิตศาสตร์มาเป็นเวลาหลายพันปีแล้ว จึงมีองค์ความรู้มากมายที่สั่งสมมาสามารถนำมาใช้ได้ นอกจากนี้ เมื่อเปรียบเทียบกับทฤษฎีบทที่นักคณิตศาสตร์มืออาชีพพิสูจน์แล้ว ปัญหาที่เราพบในการเขียนโปรแกรมมักจะค่อนข้างง่ายหากไม่ใช่เรื่องเล็กน้อย (หมายเหตุผู้แปล: เพื่อเป็นการพิสูจน์ ผู้เขียนไม่ได้พยายามที่จะรุกรานโปรแกรมเมอร์) พิจารณาคำจำกัดความของฟังก์ชันแฟกทอเรียลใน Haskell ซึ่งเป็นภาษาที่ยืมตัวไปสู่ความหมายเชิง denotational ได้อย่างง่ายดาย: ข้อดีที่สำคัญอย่างหนึ่งของการมีแบบจำลองทางคณิตศาสตร์สำหรับการเขียนโปรแกรมคือความสามารถในการพิสูจน์ความถูกต้องของซอฟต์แวร์อย่างเป็นทางการ สิ่งนี้อาจดูไม่สำคัญนักเมื่อคุณเขียนซอฟต์แวร์สำหรับผู้บริโภค แต่ก็มีบางด้านของการเขียนโปรแกรมที่อาจทำให้ต้นทุนความล้มเหลวมีมหาศาล หรือชีวิตมนุษย์ตกอยู่ในความเสี่ยง แต่แม้กระทั่งเมื่อเขียนเว็บแอปพลิเคชันสำหรับระบบการดูแลสุขภาพ คุณก็สามารถชื่นชมแนวคิดที่ว่าฟังก์ชันและอัลกอริธึมจากไลบรารีมาตรฐาน Haskell มาพร้อมกับการพิสูจน์ความถูกต้อง เราสามารถใช้ฟังก์ชันทางคณิตศาสตร์ในภาษาการเขียนโปรแกรมได้ ฟังก์ชันดังกล่าวเมื่อได้รับค่าอินพุตจะคำนวณค่าเอาต์พุต ฟังก์ชันสำหรับยกกำลังสองตัวเลขอาจจะคูณค่าอินพุตด้วยตัวมันเอง โดยจะทำสิ่งนี้ทุกครั้งที่ถูกเรียก และรับประกันว่าจะให้ผลลัพธ์เดียวกันทุกครั้งที่ถูกเรียกด้วยอาร์กิวเมนต์เดียวกัน เลขยกกำลังสองไม่เปลี่ยนแปลงตามข้างขึ้นข้างแรม นอกจากนี้ การคำนวณกำลังสองของตัวเลขไม่ควรมีผลข้างเคียงในการให้ขนมสุนัขของคุณอร่อยๆ "ฟังก์ชัน" ที่ทำสิ่งนี้ไม่สามารถสร้างแบบจำลองด้วยฟังก์ชันทางคณิตศาสตร์ได้อย่างง่ายดาย ในภาษาโปรแกรม ฟังก์ชันที่ให้ผลลัพธ์เดียวกันบนอาร์กิวเมนต์เดียวกันเสมอและไม่มีผลข้างเคียงเรียกว่าบริสุทธิ์ ในภาษาเชิงฟังก์ชันล้วนๆ เช่น Haskell ฟังก์ชันทั้งหมดล้วนล้วนแต่ ทำให้ง่ายต่อการกำหนดความหมายเชิง denotational ของภาษาเหล่านี้และสร้างแบบจำลองโดยใช้ทฤษฎีหมวดหมู่ สำหรับภาษาอื่นๆ คุณสามารถจำกัดตัวเองให้อยู่ในกลุ่มย่อยล้วนๆ หรือคิดถึงผลข้างเคียงแยกกันได้ตลอดเวลา ต่อไปเราจะมาดูกันว่า monads อนุญาตให้เราสร้างโมเดลเอฟเฟกต์ทุกประเภทโดยใช้ฟังก์ชันล้วนๆ ได้อย่างไร ผลก็คือ เราไม่สูญเสียอะไรเลยจากการจำกัดตัวเองให้อยู่กับฟังก์ชันทางคณิตศาสตร์เท่านั้น (โปรดจำไว้ว่า a เป็นตัวแปรประเภท ซึ่งสามารถเป็นประเภทใดก็ได้) ชื่อนี้ไม่ใช่เรื่องบังเอิญ มีการตีความประเภทและฟังก์ชันที่ลึกซึ้งยิ่งขึ้นในแง่ของตรรกะที่เรียกว่า Curry-Howard isomorphism ประเภท Void แสดงถึงความไม่จริง และฟังก์ชันไร้สาระแสดงถึงการยืนยันว่าบางสิ่งตามมาจากความเท็จ ดังในภาษาละตินวลี "ex falso sequitur quodlibet" (หมายเหตุผู้แปล: สิ่งใดก็ตามที่ตามมาจากความเท็จ) ถัดมาเป็นประเภทที่สอดคล้องกับชุดซิงเกิลตัน นี่คือประเภทที่มีค่าที่เป็นไปได้เพียงค่าเดียว ความหมายนี้เป็นเพียง "มี" คุณอาจจำมันไม่ได้ในทันที แต่เป็นโมฆะในภาษา C ++ ลองนึกถึงฟังก์ชันจากและไปยังประเภทนี้ สามารถเรียกฟังก์ชัน void ได้เสมอ หากเป็นฟังก์ชันล้วนๆ ก็จะส่งกลับผลลัพธ์เดียวกันเสมอ นี่คือตัวอย่างของฟังก์ชันดังกล่าว: แล้วฟังก์ชันที่คืนค่าเป็นโมฆะหรือใน Haskell ให้ส่งคืนฟังก์ชันใด ในภาษา C++ ฟังก์ชันดังกล่าวใช้สำหรับผลข้างเคียง แต่เรารู้ว่าฟังก์ชันดังกล่าวไม่ใช่ฟังก์ชันจริงในความหมายทางคณิตศาสตร์ของคำ ฟังก์ชั่นแท้ที่ส่งกลับค่าหนึ่งจะไม่ทำอะไรเลย: มันจะละทิ้งอาร์กิวเมนต์ของมัน ในทางคณิตศาสตร์ ฟังก์ชันจากเซต A ถึงเซตเดี่ยวจะจับคู่แต่ละองค์ประกอบกับองค์ประกอบเดียวของเซตนั้น สำหรับ A แต่ละตัวจะมีฟังก์ชันดังกล่าวเพียงฟังก์ชันเดียวเท่านั้น นี่คือสำหรับจำนวนเต็ม: ฟังก์ชันที่สามารถกำหนดได้ด้วยสูตรเดียวกันสำหรับประเภทใดๆ เรียกว่า โพลิมอร์ฟิกแบบพาราเมตริก คุณสามารถใช้ฟังก์ชันดังกล่าวทั้งกลุ่มได้ด้วยสมการเดียว โดยใช้พารามิเตอร์แทนประเภทเฉพาะ จะเรียกใช้ฟังก์ชัน polymorphic จากชนิดใดชนิดหนึ่งไปได้อย่างไร? แน่นอน เราจะเรียกมันว่าหน่วย: ฟังก์ชัน Pure Bool เพียงเลือกค่าสองค่าจากประเภทเป้าหมาย หนึ่งค่าที่สอดคล้องกับ True และอีกค่าหนึ่งสอดคล้องกับค่าเท็จ ฟังก์ชันใน Bool เรียกว่าเพรดิเคต ตัวอย่างเช่น ไลบรารี Data.Char ใน Haskell มีเพรดิเคตจำนวนมาก เช่น IsAlpha หรือ isDigit มีไลบรารีที่คล้ายกันใน C ++ |
อ่าน: |
---|
เป็นที่นิยม:
ใหม่
- การเชื่อมต่อแล็ปท็อปเข้ากับทีวีผ่านสาย USB เพื่อเชื่อมต่อแล็ปท็อปเข้ากับทีวี VGA
- การเปลี่ยนอินเทอร์เฟซ Steam - จากรูปภาพธรรมดาไปจนถึงการนำเสนอทั้งหมดบนหน้าจอ การออกแบบไอน้ำใหม่
- วิธียกเลิกการสมัครสมาชิก Megogo บนทีวี: คำแนะนำโดยละเอียด วิธียกเลิกการสมัครสมาชิก Megogo
- วิธีแบ่งพาร์ติชันดิสก์โดยติดตั้ง Windows โดยไม่สูญเสียข้อมูล แบ่งพาร์ติชันดิสก์ 7
- เหตุใดผู้จัดพิมพ์จึงไม่สามารถแก้ไขทุกหน้าได้
- ไม่มีการบู๊ตจากแฟลชไดรฟ์ใน BIOS - จะกำหนดค่าได้อย่างไร?
- รหัสโปรโมชั่น Pandao สำหรับคะแนน
- ไวรัสแรนซัมแวร์ที่เป็นอันตรายกำลังแพร่กระจายอย่างหนาแน่นบนอินเทอร์เน็ต
- การติดตั้ง RAM เพิ่มเติม
- จะทำอย่างไรถ้าหูฟังไม่สร้างเสียงบนแล็ปท็อป