ตัวอย่างของความต่อเนื่องที่ไม่ได้นำไปใช้เป็นขั้นตอนคืออะไร?


15

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

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

เพื่อช่วยในการทำความเข้าใจฉันสามารถให้ตัวอย่างเป็นภาษาที่ใช้งานได้ซึ่งความต่อเนื่องถูกแสดงออกในรูปแบบที่เป็นนามธรรมมากกว่าฟังก์ชั่นหรือไม่? ฉันรู้ว่า Scheme ช่วยให้คุณสามารถคว้าความต่อเนื่องในปัจจุบันในรูปแบบของคลาส (call / cc) แต่ถึงกระนั้นดูเหมือนว่าขั้นตอนการโต้แย้งหนึ่งที่ส่งผ่านไปยัง call / cc นั้นจะได้รับความต่อเนื่องในปัจจุบันในรูปแบบของอีกแบบหนึ่ง ขั้นตอนการโต้แย้งที่ฟังก์ชั่นการโทร / cc'd สามารถใช้ผลของมัน


บางทีการตัดกันของความต่อเนื่องและการปรับสภาพการทำงานในขณะที่: ความต่อเนื่องสามารถถูกแปลงเป็นโครงสร้างข้อมูลผ่านการทำหน้าที่ อาจเป็นพื้นที่ที่น่าสนใจที่จะดู
Dan D.

@DanD คุณมีคำแนะนำสำหรับวรรณคดีที่น่าสนใจที่ฉันสามารถอ่านได้หรือไม่? หัวข้อนั้นฟังดูมีประโยชน์
David Cowden

ตัวอย่างเช่น: การรีไซเคิลต่อเนื่อง (Sobel, Friedman)
Dan D.

คำตอบ:


11

TL; DR; ประเภทเป็นนามธรรมที่ครอบคลุมมากกว่าความต่อเนื่อง


ความต่อเนื่องคือชนิดของอินพุตและเอาต์พุต

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

คุณสามารถแค็ปซูลปิดในประเภทเช่นContประเภทใน Haskell ที่คุณได้รับสิ่งที่เป็นนามธรรม monad เป็น "abstraction ระดับที่สูงขึ้น" และมีรูปแบบอื่น ๆ ของสิ่งที่เป็นนามธรรมเหนือสิ่งที่คุณได้รับเมื่อคุณมองความต่อเนื่องเป็นประเภทแทน เพียงขั้นตอนตัวอย่างเช่น

  • คุณสามารถดำเนินการสองอย่างและทำทางเลือกระหว่างพวกเขาหากประเภทเป็นไปตามกฎหมายว่าเป็นเรื่องไร้สาระ
  • คุณสามารถนามธรรมมากกว่าประเภทที่จะเปลี่ยน input หรือ output ประเภทของความต่อเนื่องถ้าคุณแค็ปซูลปิดในประเภทนั้นปฏิบัติตามกฎหมายของ a functor
  • คุณสามารถใช้หรือประดับตกแต่งความต่อเนื่องของคุณโดยพลการและบางอย่างเช่นการตรวจสอบอินพุตหรือการแปลงอินพุตหากคุณใส่แค็ปซูเลชั่นปิดในรูปแบบที่เป็นไปตามกฎหมายของfunctor ที่ใช้งาน

การปิดกิจการ

ในตอนท้ายของวันคุณถูกต้องโดยทั่วไป; ความต่อเนื่องเป็น "ขั้นตอน" แม้ว่าฉันอยากจะเรียกมันว่าเป็นการปิด บ่อยครั้งที่การแสดงผลต่อเนื่องที่ดีที่สุดเป็นการปิดคลาสที่ล้อมรอบสภาพแวดล้อมที่ถูกผูกไว้ ในภาษาที่ใช้งานได้จริงคุณอาจพูดว่านี่ไม่สมเหตุสมผลโดยเฉพาะเพราะคุณไม่มีการอ้างอิง สิ่งนี้เป็นจริง แต่คุณสามารถใส่ค่าและการมอบหมายเดี่ยวทำให้การใส่ค่ากับการอ้างอิงเป็นสิ่งเดียวกัน สิ่งนี้ก่อให้เกิดใน Haskell:

(\x -> \y -> insideYIcanAccess x (and y))

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

ดังนั้นฉันจะบอกว่าถูกต้องมากขึ้นในการอธิบายความต่อเนื่องว่า: การปิดการใช้งานในรูปแบบเฉพาะ


ข้อสรุป

สำหรับคำถามของ"ความต่อเนื่องสามารถนำไปใช้ในทางอื่นนอกเหนือจากกระบวนการได้หรือไม่" ไม่ถ้าคุณไม่มีฟังก์ชั่นเฟิร์สคลาสคุณไม่สามารถดำเนินการต่อเนื่องได้เช่นกัน (ใช่ตัวชี้ฟังก์ชั่นนับเป็นฟังก์ชั่นเฟิร์สคลาส

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


1
สิ่งนี้สรุปไว้ที่ "ความต่อเนื่องสามารถเป็นอะไรก็ได้ที่ให้คุณได้ผลลัพธ์ของโปรแกรมที่เหลือ" เนื่องจากสิ่งนี้ปกติจะมีรหัส (ส่วนที่เหลือของโปรแกรม) ภาษาส่วนใหญ่ใช้ฟังก์ชั่น ในทางทฤษฎีคุณสามารถสร้างความต่อเนื่องจากอะไรก็ได้ ระหว่างการแปลงความต่อเนื่องในคอมไพเลอร์ฉันใช้ต้นไม้ที่เติมเต็มบางส่วน
Daniel Gratzer

1
@jozefg ต้นไม้ที่ถูกเติมเต็มบางส่วนนั้นเป็นตัวแทนของการคำนวณที่เหมาะสมในการแสดงออก แต่ในตอนท้ายของวันรหัสที่แท้จริงที่ถูกเขียนคือการแสดงออกของประเภทที่ไม่สามารถแตกต่างจากกระบวนการเช่นฉันเข้าใจ นอกเหนือจากนั้นต้นไม้ที่ถูกเติมเต็มบางส่วนเป็นตัวแทนของคอมไพเลอร์; การเป็นตัวแทนนักพัฒนาคาดว่าจะเป็นบรรทัดฐานการแสดงออกของการคำนวณด้วยไวยากรณ์และความหมายของภาษาซึ่งจะปรากฏว่า 99% ของนักพัฒนาเป็น "ขั้นตอน", "ฟังก์ชั่น" หรืออื่น ๆ คุณกำลังความคิดจากนักพัฒนาคอมไพเลอร์ของหึมุมมอง
จิมมี่ฮอฟฟา

2

ตัวอย่างหนึ่งที่คุณอาจชอบคือ coroutines ตัวอย่างเช่น Coroutines จาก Lua หรือ iterators / generators จาก Python หรือ C # มีความคล้ายคลึงกันในการใช้พลังงานกับการถ่ายภาพต่อเนื่องแบบ one-shot (การทำต่อเนื่องที่คุณได้รับอนุญาตให้โทรครั้งเดียวเท่านั้น) แต่การทำต่อเนื่องนั้นไม่ชัดเจน คุณมีวิธีที่จะทำให้ coroutine เลื่อนไปจนถึงคำสั่ง "ยอม" ต่อไป

ตัวอย่างเช่นพิจารณาโปรแกรม Python ต่อไปนี้:

def my_iterator():
   yield 1
   yield 2
   yield 3

def main():
   it = my_iterator()
   x = it.next()
   y = it.next()
   z = it.next()
   print x + y + z

มีลักษณะคล้ายกับโปรแกรม Javascript ต่อไปนี้พร้อมด้วยการเรียกกลับที่ชัดเจน:

function my_iterator()
  return function(cb1){
    cb1(1, function(cb2){
      cb2(2, function(cb3){
        cb3(3, function(cb4){
          throw "stop iteration";
        });
      });
    });
  });
}

function main(){
   var getNext1 = my_iterator();
   getNext1(function(x, getNext2){
      getNext2(function(y, getNext3){
         getNext3(function(z, getNext4){
            console.log(x + y + z);
         });
      });
   });
}

ตัวอย่าง Javascript เป็นชนิดที่มีเสียงดังเพราะแต่ละขั้นตอนจำเป็นต้องส่งคืนความต่อเนื่องต่อไปนอกเหนือจากการคืนค่าที่ได้รับ (ใน Python จะติดตามความต่อเนื่องภายใน ite

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