ทำความเข้าใจกับฟังก์ชัน Scheme

มีคำถามต่อไปนี้ให้ไว้ในข้อสอบฝึกหัดภาษาการเขียนโปรแกรม และฉันประสบปัญหาในการอธิบายวิธีการทำงานนี้ ใครช่วยบอกฉันหน่อยได้ไหมว่าการไหลของโค้ดคืออะไร? ฉันเคยวิ่งด้วยแร็กเกตและรู้ว่าคำตอบคืออะไร ดูเหมือนว่าฟังก์ชันแลมบ์ดาแรกกำลังรับฟังก์ชันอีกสองฟังก์ชันเป็นอาร์กิวเมนต์ แต่แล้วอินพุต (lambda (x) 2) และ (lambda (y) 3) ถูกส่งไปที่ใด

(((lambda (x y) (x y)) (lambda (y) (lambda (y x) (x (x y)))) (lambda (x) (lambda (x y) (x (y x))))) (lambda (x) 2) (lambda (y) 3))

คำตอบของคำถามคือ 3.


person danny    schedule 17.09.2016    source แหล่งที่มา


คำตอบ (3)


มนุษย์เราชอบตั้งชื่อสิ่งต่างๆ สัญกรณ์ที่กระชับด้วยชื่อสั้นทำให้ง่ายต่อการจัดการโค้ดทางจิตใจ เนื่องจากความสามารถทางจิตของเรามากมายเชื่อมโยงกับระบบการจดจำภาพคู่ขนานขนาดใหญ่ของเรา:

(((lambda (x y) (x y))
  (lambda (y) (lambda (y x) (x (x y))))
  (lambda (x) (lambda (x y) (x (y x)))))
 (lambda (x) 2)
 (lambda (y) 3)) =>

((u               where u = (lambda (x y) (x y))
  f                     f = (lambda (y) (lambda (y x) (x (x y))))
  g)                    g = (lambda (x) (lambda (x y) (x (y x))))
 (lambda (x) 2)
 (lambda (y) 3)) =>

((u               where (u x y) = (x y)
  f                     (f y)   = \(y x) -> (x (x y))     ; (*)
  g)                    (g x)   = \(x y) -> (x (y x))
 (lambda (x) 2)
 (lambda (y) 3)) =>

((f               where (f g)   = \(y x) -> (x (x y))
  g)                    (g x)   = \(x y) -> (x (y x))
 (lambda (x) 2)
 (lambda (y) 3)) =>

(h                where h       = \(y x) -> (x (x y))
 p                      p       = \(x) -> 2
 q) =>                  q       = \(y) -> 3

(h                where (h y x) = (x (x y))
 p                      (p x)   = 2
 q) =>                  (q y)   = 3

(q (q p))         where (p x)   = 2
                        (q y)   = 3
    => 

(q 3)             where (q y)   = 3
    => 

3

คำจำกัดความ (*) มีตัวแปรทั้งหมด ผูกมัด ในนิพจน์แลมบ์ดา (lambda (y x) (x (x y))) -- ทั้ง x และ y อาร์กิวเมนต์ y ใน (f y) จึงถูกละเว้น มันอาจถูกอ้างอิงโดยตัวแปร free y ในนิพจน์แลมบ์ดา แต่ไม่มีเลย

person Will Ness    schedule 18.09.2016
comment
ขอบคุณสำหรับการตอบกลับ. สิ่งนี้มีประโยชน์มาก ในตอนแรกฉันไม่เข้าใจมันหลังจากลองเข้ากูเกิ้ลไปสักพักและอ่านว่าการลดอัลฟ่า เบต้า และเอตามีอะไรบ้าง ฉันสามารถเข้าใจสิ่งนี้ได้ ขอบคุณอีกครั้ง :) - person danny; 19.09.2016
comment
@danny ยินดีต้อนรับครับ คุณควรจะบอกว่าคุณไม่มั่นใจเกี่ยวกับกฎพื้นฐาน ฉันจะอธิบายเล็กน้อยเกี่ยวกับเรื่องนั้น - person Will Ness; 20.09.2016

นี่คืองานสำหรับสเต็ปเปอร์พีชคณิต!

ป้อนสิ่งนี้ (ไม่มีบรรทัด #lang) ในหน้าต่างโต้ตอบของ DrRacket ที่มุมล่างซ้ายให้เปลี่ยนภาษาเป็น "Intermediate Student with Lambda" ตอนนี้คลิกปุ่ม "เรียกใช้" สุดท้ายคลิกปุ่ม "Stepper" (ปุ่มซ้ายสุดทางด้านซ้ายของปุ่ม run

ตอนนี้คุณสามารถผ่านขั้นตอนเดียวของโปรแกรมได้ (และย้อนกลับ!)

(((lambda (x y) (x y))
  (lambda (y) (lambda (y x) (x (x y))))
  (lambda (x) (lambda (x y) (x (y x)))))
 (lambda (x) 2)
 (lambda (y) 3))

ป้อนคำอธิบายรูปภาพที่นี่

person soegaard    schedule 17.09.2016
comment
โอเค สิ่งนี้มีประโยชน์จริงๆ ขอบคุณ! ดังนั้นฟังก์ชันแรกจะใช้เป็นอาร์กิวเมนต์อีกสองฟังก์ชันและอินพุต (lambda (x) 2) และ (lambda (y) 3) จะถูกส่งผ่านไป แต่สิ่งที่ฉันไม่เข้าใจก็คือสคีมนั้นไม่ได้ประเมินฟังก์ชัน (lambda (x) (lambda (x y) (x (y x)))) และส่งคืนเฉพาะค่า 3 จากค่าแรกเท่านั้น ฉันเดาว่านี่คือจุดที่ฉันทำผิดพลาดเมื่อฉันใช้งานโค้ดแบบแห้ง ฉันกำลังประเมินฟังก์ชันที่ 2 เช่นกัน คำถามของฉันตอนนี้คือเหตุใดจึงไม่ประเมินฟังก์ชันที่ 2 ขอบคุณอีกครั้ง. - person danny; 17.09.2016
comment
@danny (lambda (x) (lambda (x y) (x (y x)))) นิพจน์เดียวในร่างกายของแลมบ์ดาคือรูปแบบแลมบ์ดา ดังนั้นเมื่อคุณใช้มัน คุณสามารถอธิบายเพื่อกลับขั้นตอนที่รับสองข้อโต้แย้งได้ - person Sylwester; 17.09.2016

แต่แล้วอินพุต (lambda (x) 2) และ (lambda (y) 3) ถูกส่งไปที่ใด?

สำหรับสิ่งนี้ การเพิ่มคำสั่ง println สามารถช่วยได้:

(((lambda (x y)
    (println "In Lxy fn")
    (x y))
  (lambda (y)
    (println "In Ly fn")
    (lambda (y x)
      (println "In Lyxi fn")
      (x (x y))))
  (lambda (x)
    (println "In Lx fn")
    (lambda (x y)
      (println "In Lxyi fn")
      (x (y x)))))
 (lambda (x) 2)
 (lambda (y) 3))

เอาท์พุท:

"In Lxy fn"
"In Ly fn"
"In Lyxi fn"
3

ส่วนหนึ่งของฟังก์ชันนี้ซ้ำซ้อนและสามารถลบออกได้โดยไม่มีผลกระทบต่อเอาต์พุต ต่อไปนี้ สามารถใส่ค่าใดก็ได้แทนส่วนที่ถอดออก:

(((lambda (x y)
    (println "In Lxy fn")
    (x y))
  (lambda (y)
    (println "In Ly fn")
    (lambda (y x)
      (println "In Lyxi fn")
      (x (x y))))
  ;(lambda (x)
  ;  (println "In Lx fn")
  ;  (lambda (x y)
  ;    (println "In Lxyi fn")
  ;    (x (y x))))
  "any value"
  )
 (lambda (x) 2)
 (lambda (y) 3)) 

ในรูปแบบของคุณเอง ต่อไปนี้จะสร้างผลลัพธ์เหมือนเดิม:

(((lambda (x y) (x y))
  (lambda (y) (lambda (y x) (x (x y))))
  ;(lambda (x) (lambda (x y) (x (y x))))
  "any value"
  )
 (lambda (x) 2)
 (lambda (y) 3))
person rnso    schedule 21.09.2016
comment
แก้ไขฉันถ้าฉันผิด ตามความเข้าใจของฉัน หลังจากลดขนาดลงทั้งหมดแล้ว อินพุต (lambda (x) 2) และ (lambda (y) 3) จะถูกส่งผ่านไปยัง fn (lambda (y x) (x (x y)) - person danny; 23.09.2016