อะไรทำให้ภาษาโปรแกรมเชิงฟังก์ชั่นมีความหมายต่างกับความจำเป็น?


17

ในหลาย ๆ บทความที่อธิบายถึงประโยชน์ของการเขียนโปรแกรมเชิงปฏิบัติฉันได้เห็นภาษาโปรแกรมที่ใช้งานได้เช่น Haskell, ML, Scala หรือ Clojure เรียกว่า "ภาษาที่ประกาศ" ซึ่งแตกต่างจากภาษาที่จำเป็นเช่น C / C ++ / C # / Java คำถามของฉันคือสิ่งที่ทำให้ภาษาโปรแกรมการทำงานประกาศเมื่อเทียบกับความจำเป็น

คำอธิบายที่พบบ่อยซึ่งอธิบายถึงความแตกต่างระหว่างการเขียนโปรแกรมเชิงประกาศและเชิงบังคับคือในการเขียนโปรแกรมเชิงบังคับคุณต้องบอกคอมพิวเตอร์ว่า "ทำอย่างไร" ซึ่งต่างจาก "สิ่งที่ต้องทำ" ในภาษาที่ประกาศ ปัญหาที่ฉันมีกับคำอธิบายนี้คือคุณกำลังทำทั้งสองอย่างในภาษาการเขียนโปรแกรมทั้งหมด แม้ว่าคุณจะลงไปที่แอสเซมบลีระดับต่ำสุดที่คุณยังบอกคอมพิวเตอร์ว่า "สิ่งที่ต้องทำ" คุณบอกซีพียูเพื่อเพิ่มตัวเลขสองตัวคุณไม่ได้บอกวิธีการเพิ่ม ถ้าเราไปที่ปลายอีกด้านหนึ่งของภาษาที่มีฟังก์ชั่นบริสุทธิ์ระดับสูงอย่าง Haskell คุณกำลังบอกคอมพิวเตอร์ว่าจะทำภารกิจเฉพาะอย่างได้อย่างไร นั่นคือสิ่งที่โปรแกรมของคุณเป็นลำดับของคำแนะนำเพื่อให้ได้งานเฉพาะซึ่งคอมพิวเตอร์ไม่ทราบว่าจะบรรลุผลได้อย่างไร ฉันเข้าใจว่าภาษาเช่น Haskell, Clojure ฯลฯ มีระดับที่สูงกว่า C / C ++ / C # / Java อย่างเห็นได้ชัดและมีคุณสมบัติเช่นการประเมินแบบขี้เกียจโครงสร้างข้อมูลที่ไม่เปลี่ยนรูปแบบฟังก์ชันที่ไม่ระบุชื่อการปิดบังโครงสร้างข้อมูลถาวร ฟังก์ชั่นการเขียนโปรแกรมเป็นไปได้และมีประสิทธิภาพ แต่ฉันจะไม่แยกพวกเขาเป็นภาษาที่เปิดเผย

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

ปรับปรุง:

ฉันได้เล่นกับ Prolog เมื่อเร็ว ๆ นี้และสำหรับฉันแล้ว Prolog เป็นภาษาการเขียนโปรแกรมที่ใกล้เคียงที่สุดกับภาษาที่ประกาศอย่างเต็มที่ (อย่างน้อยก็ในความคิดของฉัน) ถ้าไม่ใช่ภาษาการเขียนโปรแกรมแบบเต็ม ในการทำรายการอย่างละเอียดใน Prolog จะทำโดยการประกาศซึ่งรัฐทั้งข้อเท็จจริง (ฟังก์ชั่นกริยาซึ่งส่งกลับจริงสำหรับอินพุตที่เฉพาะเจาะจง) หรือกฎ (ฟังก์ชั่นกริยาซึ่งส่งกลับจริงสำหรับเงื่อนไข / รูปแบบที่กำหนดขึ้นอยู่กับอินพุต) กฎ ถูกกำหนดโดยใช้เทคนิคการจับคู่รูปแบบ เมื่อต้องการทำสิ่งใดในอารัมภบทคุณค้นหาฐานความรู้โดยการแทนที่อินพุตหนึ่งรายการหรือมากกว่าของเพรดิเคตด้วยตัวแปรและโปรล็อกพยายามค้นหาค่าสำหรับตัวแปรที่เพรดิเคตสำเร็จ

ประเด็นของฉันอยู่ในอารัมภบทไม่มีคำสั่งที่จำเป็นคุณบอก (คอมพิวเตอร์) สิ่งที่รู้แล้วถาม (สอบถาม) เกี่ยวกับความรู้ ในภาษาโปรแกรมที่ใช้งานได้คุณยังคงให้คำแนะนำเช่นรับค่า, เรียกใช้ฟังก์ชัน X และเพิ่ม 1 เข้าไป, ฯลฯ แม้ว่าคุณจะไม่ได้จัดการตำแหน่งหน่วยความจำโดยตรงหรือเขียนขั้นตอนการคำนวณทีละขั้นตอน ฉันจะไม่พูดว่าการเขียนโปรแกรมใน Haskell, ML, Scala หรือ Clojure เป็นการประกาศในแง่นี้แม้ว่าฉันอาจจะผิด เหมาะสมถูกต้องจริงและบริสุทธิ์การทำงานของโปรแกรมประกาศในแง่ที่ฉันอธิบายไว้ข้างต้น


@JimmyHoffa อยู่ที่ไหนเมื่อคุณต้องการเขา

2
1. C # และC ++ สมัยใหม่เป็นภาษาที่ใช้งานได้ดีมาก 2. นึกถึงความแตกต่างของการเขียน SQL และ Java เพื่อให้บรรลุวัตถุประสงค์ที่คล้ายกัน (อาจเป็นบางคำถามที่ซับซ้อนด้วยการรวม) คุณยังสามารถคิดวิธีการที่ LINQ ใน C # แตกต่างจากการเขียนลูป foreach ง่าย ...
AK_

ความแตกต่างนั้นเป็นเรื่องของสไตล์มากกว่าสิ่งที่กำหนดไว้อย่างชัดเจน ... เว้นแต่คุณกำลังใช้การเปิดฉาก ...
AK_

1
หนึ่งในกุญแจที่จะตระหนักถึงความแตกต่างกันคือเมื่อคุณกำลังใช้การกำหนดผู้ประกอบการกับผู้ประกอบการความหมาย / ประกาศ - ใน Haskell เช่นมีไม่มีผู้ประกอบการที่ได้รับมอบหมาย พฤติกรรมของผู้ให้บริการสองรายนี้แตกต่างกันมากและบังคับให้คุณออกแบบรหัสของคุณแตกต่างกัน
Jimmy Hoffa

1
น่าเสียดายที่ไม่มีผู้ดำเนินการที่ได้รับมอบหมายฉันสามารถทำได้(let [x 1] (let [x (+ x 2)] (let [x (* x x)] x)))(หวังว่าคุณจะเข้าใจอย่างนั้น Clojure) คำถามเดิมของฉันคือสิ่งที่ทำให้สิ่งนี้แตกต่างจาก int นี้x = 1; x += 2; x *= x; return x;ในความเห็นของฉันส่วนใหญ่เหมือนกัน
ALXGTV

คำตอบ:


16

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

คำถามคือมุมมองดังกล่าวสมเหตุสมผลหรือไม่และลำดับของคำแนะนำนั้นมีความคล้ายคลึงกับการประกาศผลการคำนวณอย่างไร สำหรับ CSS มุมมองที่เปิดเผยมีประโยชน์มากกว่าอย่างชัดเจน สำหรับ C มุมมองที่จำเป็นนั้นเด่นชัด สำหรับภาษา Haskell ก็ดี ...

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

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

sum_of_fac n = sum [product [1..i] | i <- ..n]

คุณสามารถ desugar สิ่งนี้และอ่านมันเป็นลำดับของการดำเนินงานของ STG แต่ยิ่งกว่านั้นคือการอ่านมันเป็นคำอธิบายของผลลัพธ์ (ซึ่งก็คือฉันคิดว่าคำจำกัดความที่เป็นประโยชน์ของการเขียนโปรแกรมเชิงประกาศมากกว่า "สิ่งที่ต้องคำนวณ"): ผลลัพธ์คือผลรวมของผลิตภัณฑ์[1..i]สำหรับทั้งหมดi= 0, …, n และนั่นคือการประกาศมากกว่าโปรแกรมหรือฟังก์ชั่น C เกือบทั้งหมด


1
เหตุผลที่ฉันถามคำถามนี้คือผู้คนจำนวนมากพยายามที่จะส่งเสริมการเขียนโปรแกรมใช้งานได้เนื่องจากกระบวนทัศน์ใหม่ที่แตกต่างบางอย่างแยกออกจากกระบวนทัศน์ของ C / C ++ / C # / Java หรือแม้แต่ Python เมื่อในความเป็นจริง การเขียนโปรแกรมที่จำเป็น
ALXGTV

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

6
@ALXGTV การเขียนโปรแกรมฟังก์ชั่นเป็นกระบวนทัศน์ที่แตกต่างกันมากแม้ว่าคุณจะยืนกรานเกี่ยวกับการอ่านมันเป็นสิ่งจำเป็น (มันเป็นหมวดหมู่ที่กว้างมากมีมากขึ้นในกระบวนทัศน์การเขียนโปรแกรมกว่านั้น) และรหัสอื่น ๆ ที่สร้างขึ้นบนรหัสนี้อาจจะอ่าน declaratively เกินไป: map (sum_of_fac . read) (lines fileContent)ยกตัวอย่างเช่น แน่นอนว่าในบางจุด I / O จะเข้าสู่การเล่น แต่อย่างที่ฉันพูดมันเป็นความต่อเนื่อง บางส่วนของโปรแกรม Haskell มีความจำเป็นมากขึ้นเช่นเดียวกับ C มีไวยากรณ์การแสดงออกของ sorta-declarative ( x + yไม่ใช่load x; load y; add;)

1
@ALXGTV สัญชาตญาณของคุณถูกต้อง: การเขียนโปรแกรมที่ประกาศ "เพียง" ให้ระดับที่สูงกว่าของนามธรรมมากกว่ารายละเอียดที่จำเป็นบางอย่าง ฉันจะเถียงว่านี่เป็นเรื่องใหญ่!
Andres F.

1
@Brendan ฉันไม่คิดว่าการเขียนโปรแกรมการทำงานเป็นส่วนหนึ่งของการเขียนโปรแกรมจำเป็น (หรือไม่สามารถเปลี่ยนเป็นลักษณะบังคับของ FP) มันอาจจะเป็นที่ถกเถียงกันอยู่ว่าในกรณีที่บริสุทธิ์พิมพ์แบบสแตติกมันเป็นชุดของการเขียนโปรแกรมที่จำเป็นที่ชัดเจนในลักษณะพิเศษประเภท คุณจะรู้ว่าการพูดจาอย่างมั่นใจแก้มที่ Haskell เป็น "ภาษาที่จำเป็นที่สุดในโลก";)
Andres F.

21

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

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

ภาษาที่มีความหมายมีการแสดงออก แต่วิธีการหลักของพวกเขาในการทำสิ่งต่าง ๆ คือข้อความ ในทำนองเดียวกันภาษาที่ประกาศมีการแสดงออกบางอย่างที่มีความหมายคล้ายกับคำสั่งเช่นลำดับ monad ในdoสัญกรณ์ของ Haskell แต่ที่หลักของพวกเขาพวกเขาเป็นหนึ่งในการแสดงออกที่ใหญ่ วิธีนี้จะช่วยให้ผู้เริ่มต้นเขียนโค้ดที่มีลักษณะที่จำเป็นมาก แต่พลังที่แท้จริงของภาษามาเมื่อคุณหลบหนีกระบวนทัศน์นั้น


1
นี่จะเป็นคำตอบที่สมบูรณ์แบบถ้ามันมีตัวอย่าง ตัวอย่างที่ดีที่สุดที่ฉันรู้ที่จะแสดงให้เห็นถึงความจำเป็นที่เปิดเผยกับเป็น Linq foreachเทียบกับ
Robert Harvey

7

ลักษณะการกำหนดจริงที่แยกการประกาศจากการเขียนโปรแกรมที่จำเป็นอยู่ในรูปแบบการประกาศคุณไม่ได้ให้คำแนะนำตามลำดับ; ที่ระดับต่ำกว่าใช่ซีพียูทำงานในลักษณะนี้ แต่นั่นเป็นข้อกังวลของคอมไพเลอร์

คุณแนะนำ CSS เป็น "ภาษาที่ประกาศ" ฉันจะไม่เรียกมันว่าภาษาเลย มันเป็นรูปแบบโครงสร้างข้อมูลเช่น JSON, XML, CSV หรือ INI เพียงรูปแบบสำหรับการกำหนดข้อมูลที่เป็นล่ามในบางลักษณะ

ผลข้างเคียงที่น่าสนใจบางอย่างเกิดขึ้นเมื่อคุณถอดตัวดำเนินการกำหนดค่าออกจากภาษาและนี่คือสาเหตุที่แท้จริงสำหรับการสูญเสียคำแนะนำที่จำเป็นทั้งหมดในขั้นตอนที่ 1-step2-step3

คุณจะทำอย่างไรกับผู้ประกอบการที่ได้รับมอบหมายในฟังก์ชั่น? คุณสร้างขั้นตอนกลาง นั่นคือปมของมันผู้ประกอบการที่ได้รับมอบหมายจะใช้ในการเปลี่ยนแปลงข้อมูลในแบบทีละขั้นตอน ทันทีที่คุณไม่สามารถแก้ไขข้อมูลได้อีกต่อไปคุณจะสูญเสียขั้นตอนเหล่านั้นทั้งหมดและจบลงด้วย:

ทุกฟังก์ชั่นมีเพียงหนึ่งคำสั่งคำสั่งนี้เป็นการประกาศเดียว

ตอนนี้มีหลายวิธีที่จะทำให้คำสั่งเดียวดูเหมือนคำสั่งมากมาย แต่นั่นเป็นเพียงเล่ห์เหลี่ยมเช่น: 1 + 3 + (2*4) + 8 - (7 / (8*3))นี่เป็นคำสั่งเดียวที่ชัดเจน แต่ถ้าคุณเขียนมันเป็น ...

1 +
3 +
(
  2*4
) +
8 - 
(
  7 / (8*3)
)

มันอาจใช้เวลาในการปรากฏตัวของลำดับของการดำเนินการซึ่งจะง่ายขึ้นสำหรับสมองที่จะรับรู้การสลายตัวที่ต้องการที่ผู้เขียนตั้งใจ ฉันมักจะทำสิ่งนี้ใน C # ด้วยรหัสเช่น ..

people
  .Where(person => person.MiddleName != null)
  .Select(person => person.MiddleName)
  .Distinct();

นี่เป็นคำสั่งเดียว แต่แสดงให้เห็นถึงลักษณะของการถูกย่อยสลายเป็นหลาย ๆ - สังเกตเห็นว่าไม่มีการกำหนด

โปรดทราบว่าในทั้งสองวิธีข้างต้น - วิธีการใช้งานรหัสจริงไม่ได้อยู่ในลำดับที่คุณอ่านทันที เพราะรหัสนี้กล่าวว่าสิ่งที่ต้องทำ แต่มันไม่ได้กำหนดวิธีการ โปรดสังเกตว่าการคำนวณทางคณิตศาสตร์อย่างง่าย ๆ ข้างต้นนั้นจะไม่ถูกดำเนินการตามลำดับที่เขียนจากซ้ายไปขวาและในตัวอย่าง C # ด้านบนทั้ง 3 วิธีนั้นจริง ๆ แล้วผู้เข้าร่วมใหม่ทั้งหมดและไม่ได้ดำเนินการจนเสร็จตามลำดับ ที่จะทำสิ่งที่คำสั่งนั้นต้องการแต่ไม่จำเป็นว่าคุณจะคิดอย่างไร

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

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

sum xs = (head xs) + sum (tail xs)

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


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

1 + 3 + (2 * 4) + 8 - (7 / (8 * 3)) จริง ๆ แล้วมันเป็นหลายประโยค / นิพจน์แน่นอนมันขึ้นอยู่กับสิ่งที่คุณมองว่าเป็นนิพจน์เดียว เพื่อสรุปผลการเขียนโปรแกรมการทำงานนั้นเป็นโปรแกรมที่ไม่มีอัฒภาค
ALXGTV

1
@ALXGTV ความแตกต่างระหว่างการประกาศนั้นและรูปแบบที่จำเป็นคือถ้าการแสดงออกทางคณิตศาสตร์นั้นเป็นข้อความมันจะจำเป็นที่จะต้องดำเนินการตามที่เขียนไว้ อย่างไรก็ตามเนื่องจากมันไม่ใช่ลำดับของประโยคที่จำเป็น แต่เป็นการแสดงออกที่กำหนดสิ่งที่คุณต้องการเพราะมันไม่ได้บอกว่ามันไม่จำเป็นที่จะต้องดำเนินการตามที่เขียนไว้ ดังนั้นการรวบรวมสามารถลดการแสดงออกหรือแม้กระทั่งการจดจำมันเป็นตัวอักษร ภาษาที่มีความจำเป็นต้องทำเช่นกัน แต่เมื่อคุณใส่ไว้ในคำสั่งเดียว การประกาศ
Jimmy Hoffa

@ALXGTV การประกาศกำหนดความสัมพันธ์ความสัมพันธ์มีความอ่อนไหว; ถ้าx = 1 + 2แล้วและx = 3 x = 4 - 1คำสั่งที่เรียงตามลำดับจะกำหนดคำแนะนำดังนั้นเมื่อx = (y = 1; z = 2 + y; return z;)คุณไม่ได้มีบางสิ่งบางอย่างที่ไม่ถูกต้องสิ่งที่คอมไพเลอร์สามารถทำได้หลายวิธี - แต่มันเป็นสิ่งจำเป็นที่คอมไพเลอร์ทำสิ่งที่คุณได้รับคำสั่งเพราะคอมไพเลอร์ไม่ทราบผลข้างเคียง ไม่เปลี่ยนแปลงพวกเขา
Jimmy Hoffa

คุณมีประเด็นที่ยุติธรรม
ALXGTV

6

ฉันรู้ว่าฉันมางานปาร์ตี้ช้า แต่ฉันมีวันศักดิ์สิทธิ์ดังนั้นเมื่อวานนี้มันจึงไป ...

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

ลองใช้โค้ดอย่างง่ายa = b + cเป็นพื้นฐานและดูคำสั่งในภาษาต่างๆสองสามภาษาเพื่อรับแนวคิด:

เมื่อเราเขียนa = b + cในภาษาที่จำเป็นเช่น C เราจะกำหนดค่าปัจจุบันของb + cให้กับตัวแปรaและไม่มีอะไรเพิ่มเติม เราไม่ได้สร้างข้อความพื้นฐานเกี่ยวกับสิ่งที่aเป็น แต่เราเพียงแค่ดำเนินการขั้นตอนในกระบวนการ

เมื่อเราเขียนa = b + cในภาษาที่เปิดเผยเช่น Microsoft Excel, (ใช่, Excel เป็นภาษาโปรแกรมและน่าจะเป็นที่เปิดเผยมากที่สุดของพวกเขาทั้งหมด) เราจะเข้าไปยุ่งเกี่ยวกับความสัมพันธ์ระหว่างa, bและcเช่นนั้นมันก็มักจะเป็นกรณีที่aเป็นผลรวมของ อีกสองคน มันไม่ใช่ขั้นตอนในกระบวนการมันเป็นค่าคงที่การรับประกันการประกาศความจริง

ฟังก์ชั่นภาษามีการประกาศเช่นกัน แต่เกือบโดยไม่ได้ตั้งใจ ใน Haskel ยกตัวอย่างเช่นa = b + cยังยืนยันความสัมพันธ์คงที่ แต่เพียงเพราะbและcไม่เปลี่ยนรูป

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


0

คุณมีสิทธิที่ไม่มีความแตกต่างที่ชัดเจนระหว่างคอมพิวเตอร์บอกสิ่งที่ต้องทำและวิธีการที่จะทำมัน

อย่างไรก็ตามในอีกด้านหนึ่งของสเปกตรัมคุณคิดเกี่ยวกับวิธีจัดการหน่วยความจำโดยเฉพาะ นั่นคือเพื่อแก้ปัญหาคุณนำเสนอมันไปยังคอมพิวเตอร์ในรูปแบบเช่น "ตั้งค่าตำแหน่งหน่วยความจำนี้เป็น x จากนั้นตั้งค่าตำแหน่งหน่วยความจำนั้นเป็น y, ข้ามไปยังตำแหน่งหน่วยความจำ z ... " จากนั้นคุณก็จบลงด้วย ผลลัพธ์ในตำแหน่งหน่วยความจำอื่น

ในภาษาที่มีการจัดการเช่น Java, C # และอื่น ๆ คุณไม่สามารถเข้าถึงหน่วยความจำฮาร์ดแวร์ได้โดยตรง ตอนนี้โปรแกรมเมอร์ที่มีความจำเป็นต้องเกี่ยวข้องกับตัวแปรแบบคงที่การอ้างอิงหรือฟิลด์ของอินสแตนซ์ของคลาสซึ่งทั้งหมดจะใช้ในระดับหนึ่งสำหรับตำแหน่งหน่วยความจำ

ใน langugaes เช่น Haskell, OTOH หน่วยความจำจะหายไปอย่างสมบูรณ์ มันไม่ใช่กรณีที่มา

f a b = let y = sum [a..b] in y*y

จะต้องมีเซลล์หน่วยความจำสองเซลล์ที่เก็บ arguents a และ b และอีกเซลล์หนึ่งที่เก็บผลลัพธ์ระดับกลาง y เพื่อให้แน่ใจว่าแบ็กเอนด์ของคอมไพเลอร์สามารถเปล่งรหัสสุดท้ายที่ทำงานในลักษณะนี้ (และในบางกรณีมันต้องทำเช่นนั้นตราบใดที่สถาปัตยกรรมเป้าหมายคือเครื่อง v. Neumann)

แต่ประเด็นก็คือเราไม่จำเป็นต้องทำให้ภายในสถาปัตยกรรม v. Neumann เพื่อทำความเข้าใจกับฟังก์ชันข้างต้น เราไม่จำเป็นต้องใช้คอมพิวเตอร์ร่วมสมัยเพื่อใช้งาน มันจะง่ายต่อการแปลโปรแกรมในภาษา FP บริสุทธิ์ไปยังเครื่องสมมุติที่ทำงานบนฐานของแคลคูลัส SKI เป็นต้น ทีนี้ลองโปรแกรมเดียวกันกับ C!

ภาษาที่ประกาศบริสุทธิ์สำหรับฉันจะเป็นภาษาที่มีการประกาศทั้งหมดเท่านั้น

สิ่งนี้ไม่แรงพอ IMHO แม้แต่โปรแกรม C ก็เป็นเพียงลำดับของการประกาศ ฉันรู้สึกว่าเราจะต้องมีคุณสมบัติประกาศต่อไป ยกตัวอย่างเช่นที่พวกเขาบอกเราว่าสิ่งที่บางสิ่งบางอย่างคือ (เปิดเผย) หรือสิ่งที่มันไม่ (จำเป็น)


ฉันไม่ได้ระบุว่าการเขียนโปรแกรมการทำงานไม่แตกต่างจากการเขียนโปรแกรมใน C จริง ๆ แล้วฉันพูดว่าภาษาเช่น Haskell อยู่ในระดับที่สูงกว่า C มากและให้นามธรรมที่มากกว่า
ALXGTV
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.