ทำไมสกาล่าจำเป็นต้องใช้ฟังก์ชั่นที่มีประเภทผลตอบแทนชัดเจน?


11

ฉันเพิ่งเริ่มเรียนรู้การเขียนโปรแกรมในสกาล่าและมันสนุกมาก ฉันชอบความสามารถในการประกาศฟังก์ชั่นภายในฟังก์ชั่นอื่นซึ่งดูเหมือนว่าจะใช้งานได้ง่าย

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

ข้อกำหนดของการประกาศชนิดส่งคืนอย่างชัดเจนในฟังก์ชันนี้ไม่รบกวนฉันสำหรับภาษาเช่น Java และ C ++ การเรียกซ้ำใน Java และ C ++ เมื่อเกิดขึ้นมักจะถูกจัดการด้วยฟังก์ชันสูงสุด 2 ถึง 3 ฟังก์ชัน ไม่เคยมีฟังก์ชั่นหลายอย่างเชื่อมโยงเข้าด้วยกันเหมือน Scala

ดังนั้นฉันเดาฉันสงสัยว่ามีเหตุผลที่ดีว่าทำไมสกาล่าควรมีความต้องการของฟังก์ชั่นที่มีประเภทผลตอบแทนที่ชัดเจน?


5
มันไม่ได้ - และฉันล้มเหลวที่จะดูว่าทำไมมันจะมีปัญหาถ้ามันทำ
Keith Thompson

1
ฉันคิดว่ามันทำ มีกรณีใน Scala ที่ประเภทคืนสำหรับฟังก์ชั่นที่ไม่ชัดเจนจริงหรือไม่?
เก็บขยะ

คำตอบ:


15

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

ซึ่งหมายความว่าฟังก์ชั่นเช่นนี้:

def fortuneCookieJoke(message: String) = message + " in bed."

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

ในทางกลับกันฟังก์ชั่นเช่นนี้:

def mapInts(f: (Int) => Int, l: List[Int]) = l match {
  case Nil => Nil
  case x :: xs => f(x) :: mapInts(f, xs)
}

จะทำให้เกิดข้อผิดพลาดในการคอมไพล์เวลาเนื่องจากคอมไพเลอร์ Scala ไม่สามารถมองเห็นได้โดยไม่ต้องใช้ lookahead หรือตัวแปรเชิงตรรกะอย่างแน่นอนว่าเป็นประเภทmapIntsใด สิ่งที่สามารถพูดได้มากที่สุดถ้ามันฉลาดพอก็คือรูปแบบการส่งคืนนั้นเป็นประเภท supertype List[Nothing]เนื่องจากNilเป็นประเภทนั้น mapIntsที่ไม่ให้มันได้ทุกที่ใกล้ข้อมูลเพียงพอที่จะถูกต้องกำหนดประเภทการกลับมาของ

โปรดทราบว่านี่เป็นลักษณะเฉพาะของ Scala และมีภาษาที่พิมพ์แบบคงที่อื่น ๆ (ส่วนใหญ่ของ Miranda / Haskell / ตระกูล Clean, ตระกูล ML ส่วนใหญ่และกลุ่มอื่น ๆ กระจัดกระจาย) ที่ใช้อัลกอริธึมการอนุมานประเภทที่ครอบคลุมและมีความสามารถมากขึ้น กว่าที่สกาล่าใช้ นอกจากนี้โปรดทราบว่านี่ไม่ใช่ความผิดของ Scala ทั้งหมด subtyping และการอนุมานแบบโมดูลทั้งหมดนั้นมีความขัดแย้งกันโดยพื้นฐานและผู้ออกแบบของ Scala เลือกที่จะให้ความช่วยเหลือแก่อดีตมากกว่าหลังเพื่อความเข้ากันได้ของ Java ในขณะที่ "purer" เป็นภาษาที่ใช้งานได้ ทางเลือกที่ตรงกันข้ามในใจ


4
ที่จริงแล้วปัญหาไม่ได้เกิดจากการหาอัลกอริธึมการอนุมานประเภทที่ครอบคลุมมากขึ้น มันกำลังหาอัลกอริธึมการอนุมานประเภทที่ครอบคลุมมากขึ้นในขณะที่รักษาข้อความแสดงข้อผิดพลาดคุณภาพสูงในคอมไพเลอร์ Scala ปัจจุบัน
Jörg W Mittag

1
ผลตอบแทนที่ถูกต้องสำหรับcase Nilจริงจะว่างเปล่าList[Int]()หรือไม่? ซึ่งในกรณีนี้คอมไพเลอร์สมาร์ทอย่างเพียงพอสามารถคิดออก นั่นคือทั้งหมดที่เล่น Devil's Advocate แต่ฉันคิดว่า
KChaloux
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.