การจับ / การโยนข้อยกเว้นทำให้วิธีการที่บริสุทธิ์นั้นไม่บริสุทธิ์หรือไม่?


27

ตัวอย่างโค้ดต่อไปนี้ให้บริบทกับคำถามของฉัน

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

public sealed class Room
{
    private readonly Func<Room> north;

    public Room(Func<Room> north)
    {
        this.north = north;
    }

    public Room North
    {
        get
        {
            return this.north();
        }
    }

    public static void Main(string[] args)
    {
        Func<Room> evilDelegate = () => { throw new Exception(); };

        var kitchen = new Room(north: evilDelegate);

        var room = kitchen.North; //<----this will throw

    }
}

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

public sealed class Room
{
    private readonly Func<Room> north;

    private Room(Func<Room> north)
    {
        this.north = north;
    }

    public Room North
    {
        get
        {
            return this.north();
        }
    }

    public static Room Create(Func<Room> north)
    {
        try
        {
            north?.Invoke();
        }
        catch (Exception e)
        {
            throw new Exception(
              message: "Initialized with an evil delegate!", innerException: e);
        }

        return new Room(north);
    }

    public static void Main(string[] args)
    {
        Func<Room> evilDelegate = () => { throw new Exception(); };

        var kitchen = Room.Create(north: evilDelegate); //<----this will throw

        var room = kitchen.North;
    }
}

บล็อก try-catch แสดงวิธีสร้าง () ไม่บริสุทธิ์หรือไม่


1
ประโยชน์ของฟังก์ชั่นการสร้างห้องพักคืออะไร; หากคุณใช้ผู้ร่วมประชุมทำไมต้องโทรหาก่อนที่ลูกค้าจะโทร 'North'
SH-

1
@SH หากผู้รับมอบสิทธิ์โยนข้อยกเว้นฉันต้องการค้นหาการสร้างวัตถุของห้อง ฉันไม่ต้องการให้ลูกค้าค้นหาข้อยกเว้นเมื่อมีการใช้ แต่เป็นการสร้าง วิธีการสร้างเป็นสถานที่ที่สมบูรณ์แบบในการเปิดเผยผู้ได้รับมอบหมายที่ชั่วร้าย
Rock Anthony Johnson

3
@RockAnthonyJohnson ใช่ สิ่งใดที่คุณดำเนินการเมื่อผู้รับมอบสิทธิ์อาจทำงานในครั้งแรกเท่านั้นหรือกลับห้องที่แตกต่างกันในการโทรครั้งที่สอง? การเรียกผู้แทนสามารถพิจารณา / ทำให้เกิดผลข้างเคียงได้หรือไม่?
SH-

4
ฟังก์ชั่นที่เรียกฟังก์ชั่นที่ไม่บริสุทธิ์เป็นฟังก์ชั่นที่ไม่บริสุทธิ์ดังนั้นหากผู้ร่วมประชุมไม่บริสุทธิ์Createก็ไม่บริสุทธิ์เช่นกันเพราะมันเรียกว่า
Idan Arye

2
Createฟังก์ชั่นของคุณไม่ได้ป้องกันคุณจากการได้รับข้อยกเว้นเมื่อได้รับทรัพย์สิน หากตัวแทนของคุณโยนในชีวิตจริงมีโอกาสมากที่มันจะถูกโยนภายใต้เงื่อนไขบางอย่างเท่านั้น โอกาสที่เงื่อนไขสำหรับการขว้างปาจะไม่ปรากฏในระหว่างการก่อสร้าง แต่จะปรากฏเมื่อรับทรัพย์สิน
Bart van Ingen Schenau

คำตอบ:


26

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

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


16
โปรดจำไว้ว่า "บริสุทธิ์" เป็นเพียงคำจำกัดความ หากคุณต้องการฟังก์ชั่นที่พ่น แต่ในทุก ๆ ด้านมันมีความโปร่งใสในการอ้างอิงนั่นคือสิ่งที่คุณเขียน
Robert Harvey

1
ใน Haskell อย่างน้อยฟังก์ชั่นใด ๆ ที่สามารถโยน แต่คุณต้องอยู่ใน IO จะจับฟังก์ชั่นบริสุทธิ์ที่บางครั้งพ่นปกติจะเรียกว่าบางส่วน
JK

4
ฉันมีความศักดิ์สิทธิ์เพราะความคิดเห็นของคุณ ในขณะที่ฉันมีความสนใจในเรื่องสติปัญญาอย่างชาญฉลาดสิ่งที่ฉันต้องการในการปฏิบัติจริงคือความมุ่งมั่นและความโปร่งใสที่น่านับถือ หากฉันบรรลุความบริสุทธิ์นั่นเป็นเพียงโบนัสเพิ่ม ขอขอบคุณ. FYI สิ่งที่ผลักดันฉันลงเส้นทางนี้คือความจริงที่ว่า Microsoft IntelliTest นั้นมีประสิทธิภาพเฉพาะกับรหัสที่กำหนดไว้เท่านั้น
Rock Anthony Johnson

4
@RockAnthonyJohnson: ดีรหัสทั้งหมดควรกำหนดขึ้น หรืออย่างน้อยที่สุดกำหนดขึ้น ความโปร่งใสอ้างอิงเป็นเพียงวิธีหนึ่งที่จะได้รับระดับที่ เทคนิคบางอย่างเช่นเธรดมีแนวโน้มที่จะทำงานกับระดับนั้นดังนั้นจึงมีเทคนิคอื่น ๆ เช่นงานที่ปรับปรุงแนวโน้มของแบบจำลองที่ไม่กำหนดขึ้น สิ่งต่าง ๆ เช่นเครื่องกำเนิดเลขสุ่มและเครื่องจำลอง Monte-Carlo นั้นก็กำหนดไว้เช่นกัน แต่ในทางที่แตกต่างกันขึ้นอยู่กับความน่าจะเป็น
Robert Harvey

3
@zzzzBov: ฉันไม่ได้พิจารณาความหมายที่แท้จริงและเคร่งครัดของ "บริสุทธิ์" ทุกอย่างที่สำคัญ ดูความคิดเห็นที่สองข้างต้น
Robert Harvey

12

ใช่แล้ว ... และไม่ใช่

ฟังก์ชั่นที่บริสุทธิ์จะต้องมีReferential Transparency - นั่นคือคุณควรจะสามารถแทนที่การเรียกไปยังฟังก์ชั่นที่บริสุทธิ์ด้วยค่าที่ส่งกลับโดยไม่เปลี่ยนพฤติกรรมของโปรแกรม *ฟังก์ชั่นของคุณมีการประกันเพื่อเสมอโยนข้อโต้แย้งบางอย่างดังนั้นจึงไม่มีค่าตอบแทนที่จะเปลี่ยนฟังก์ชั่นการโทรด้วยดังนั้นแทนที่จะขอไม่สนใจมัน พิจารณารหัสนี้:

{
    var ignoreThis = func(arg);
}

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

แต่ถ้าfunc(arg)เกิดขึ้นกับโยนคำสั่งนี้จะทำอะไรบางอย่าง - มันโยนข้อยกเว้น! ดังนั้นเครื่องมือเพิ่มประสิทธิภาพจึงไม่สามารถลบได้ - มันจะสำคัญถ้าฟังก์ชั่นถูกเรียกใช้หรือไม่

แต่...

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

ที่ถูกกล่าวว่า ...

อย่าโยนข้อยกเว้นจากฟังก์ชั่นที่บริสุทธิ์ด้วยความตั้งใจว่าจะถูกจับได้ - มีเหตุผลที่ดีที่ภาษาการใช้งานต้องการใช้ monads แทนที่จะเป็น stack-unwinding-exceptions

ถ้า C # มีErrorระดับเช่น Java (และภาษาอื่น ๆ อีกมากมาย) ผมจะได้แนะนำให้โยนแทนError Exceptionมันบ่งชี้ว่าผู้ใช้ฟังก์ชั่นทำอะไรผิดพลาด (ผ่านฟังก์ชั่นที่ส่งออก) และอนุญาตให้ทำสิ่งเหล่านี้ในฟังก์ชั่นบริสุทธิ์ แต่ C # ไม่ได้มีระดับและข้อยกเว้นข้อผิดพลาดการใช้งานดูเหมือนจะเป็นผลมาจากError Exceptionข้อเสนอแนะของฉันคือการโยนArgumentExceptionทำให้ชัดเจนว่าฟังก์ชั่นถูกเรียกด้วยข้อโต้แย้งที่ไม่ดี


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


1
+1 สำหรับการใช้งาน ArgumentException ที่แนะนำของคุณและสำหรับคำแนะนำของคุณที่จะไม่ "โยนข้อยกเว้นจากฟังก์ชั่นที่บริสุทธิ์ด้วยความตั้งใจว่าพวกเขาจะถูกจับได้"
Rock Anthony Johnson

อาร์กิวเมนต์แรกของคุณ (จนกระทั่ง "แต่ ... ") ดูเหมือนไม่เหมาะสำหรับฉัน ข้อยกเว้นเป็นส่วนหนึ่งของสัญญาของฟังก์ชัน คุณสามารถเขียนฟังก์ชั่นใด ๆ ที่เป็น(value, exception) = func(arg)และลบความเป็นไปได้ของการโยนข้อยกเว้น (ในบางภาษาและสำหรับข้อยกเว้นบางประเภทคุณต้องแสดงรายการด้วยคำจำกัดความเช่นเดียวกับอาร์กิวเมนต์หรือค่าส่งคืน) ตอนนี้ก็จะเป็นเช่นเดียวกับที่บริสุทธิ์เป็นมาก่อน (ให้มันมักจะส่งกลับ aka พ่นยกเว้นได้รับอาร์กิวเมนต์เดียวกัน) การโยนข้อยกเว้นไม่ใช่ผลข้างเคียงหากคุณใช้การตีความนี้
AnoE

@AnoE หากคุณจะเขียนfuncแบบนั้นบล็อกที่ฉันให้ไว้อาจได้รับการปรับปรุงให้ดีขึ้นเพราะแทนที่จะปล่อยให้กองคลี่คลายข้อยกเว้นที่ส่งออกมาจะถูกเข้ารหัสignoreThisซึ่งเราไม่สนใจ แตกต่างจากข้อยกเว้นที่คลายสแต็กข้อยกเว้นที่เข้ารหัสในประเภทส่งคืนไม่ละเมิดความบริสุทธิ์ - และนั่นเป็นสาเหตุที่ภาษาการใช้งานจำนวนมากต้องการใช้งาน
Idan Arye

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

1
@AnoE แต่รหัสที่ฉันเขียนจะไม่สนใจข้อยกเว้นสำหรับการแปลงที่จินตนาการนี้ func(arg)จะคืนค่า tuple (<junk>, TheException())และเช่นนั้นignoreThisจะมี tuple (<junk>, TheException())แต่เนื่องจากเราไม่เคยใช้ignoreThisข้อยกเว้นจะไม่มีผลกับสิ่งใด
Idan Arye

1

สิ่งหนึ่งที่ควรพิจารณาคือบล็อก try-catch ไม่ใช่ปัญหา (ขึ้นอยู่กับความคิดเห็นของฉันกับคำถามข้างต้น)

ปัญหาหลักคือการที่นอร์ทเป็น I / O โทร

ณ จุดนั้นในการเรียกใช้โค้ดโปรแกรมจำเป็นต้องตรวจสอบ I / O ที่ได้จากรหัสลูกค้า (มันจะไม่เกี่ยวข้องว่าข้อมูลที่อยู่ในรูปแบบของผู้ได้รับมอบหมายหรือว่าการป้อนข้อมูลในนามในนามผ่านไปแล้ว)

เมื่อคุณสูญเสียการควบคุมอินพุตคุณไม่สามารถมั่นใจได้ว่าฟังก์ชั่นนั้นบริสุทธิ์ (โดยเฉพาะถ้าฟังก์ชั่นสามารถโยนได้)


ฉันไม่ชัดเจนว่าทำไมคุณไม่ต้องการตรวจสอบการโทรเพื่อย้าย [ตรวจสอบ] ห้อง? ตามความคิดเห็นของฉันกับคำถาม:

ใช่. สิ่งใดที่คุณดำเนินการเมื่อผู้รับมอบสิทธิ์อาจทำงานในครั้งแรกเท่านั้นหรือกลับห้องที่แตกต่างกันในการโทรครั้งที่สอง? การเรียกผู้แทนสามารถพิจารณา / ทำให้เกิดผลข้างเคียงได้หรือไม่?

ดังที่ Bart van Ingen Schenau กล่าวไว้ข้างต้น

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

โดยทั่วไปการโหลดแบบสันหลังยาว ใด ๆโดยปริยาย defersข้อผิดพลาดจนกว่าจะถึงจุดนั้น


ฉันขอแนะนำให้ใช้วิธีการย้าย [ตรวจสอบ] ห้อง สิ่งนี้จะช่วยให้คุณสามารถแยกแง่มุม I / O ที่ไม่บริสุทธิ์ออกเป็นที่เดียว

คล้ายกับคำตอบของ Robert Harvey :

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

มันจะขึ้นอยู่กับการเขียนรหัสเพื่อกำหนดวิธีจัดการข้อยกเว้น (เป็นไปได้) จากอินพุต จากนั้นวิธีการสามารถส่งคืนวัตถุห้องหรือวัตถุห้อง Null หรืออาจทำให้เกิดข้อยกเว้น

ตอนนี้มันขึ้นอยู่กับ:

  • โดเมน Room ปฏิบัติต่อข้อยกเว้นของห้องพักว่าเป็นโมฆะหรือบางสิ่งบางอย่างเลวร้ายยิ่งขึ้นหรือไม่
  • วิธีแจ้งรหัสลูกค้าที่โทรไปยัง North บนห้อง Null / Exception (การประกันตัว / สถานะตัวแปร / รัฐทั่วโลก / คืน Monad / อะไร; บางอย่างบริสุทธิ์มากขึ้นแล้วอื่น ๆ :))

-1

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

เนื่องจากฟังก์ชั่นถูกส่งผ่านโดยผู้บริโภคซึ่งสามารถเขียนโดยคุณหรือโดยบุคคลอื่น

จะเกิดอะไรขึ้นถ้าฟังก์ชั่นการส่งผ่านไม่สามารถทำงานได้ในเวลาที่วัตถุห้องถูกสร้างขึ้น

จากรหัสฉันไม่แน่ใจว่าสิ่งที่นอร์ทกำลังทำอยู่

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

ถ้ามันเป็นฟังก์ชั่นที่ใช้งานได้นาน คุณจะไม่ต้องการปิดกั้นโปรแกรมของคุณในขณะที่สร้างวัตถุห้องถ้าคุณจำเป็นต้องสร้างวัตถุ 1,000 ห้อง?

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

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

อีกสิ่งหนึ่งคือไม่ใช่สิ่งที่ดีเสมอไปที่จะสร้างข้อยกเว้นใหม่ เหตุผลที่เป็นอยู่มันจะไม่มีข้อมูลของข้อยกเว้นดั้งเดิม คุณรู้ว่าคุณได้รับข้อผิดพลาด (mesaage ที่เป็นมิตรสำหรับข้อยกเว้นทั่วไป) แต่คุณจะไม่ทราบว่าข้อผิดพลาดคืออะไร (การอ้างอิง Null, ดัชนีไม่อยู่ในขอบเขต, แบ่งตามศูนย์ ฯลฯ ) ข้อมูลนี้มีความสำคัญมากเมื่อเราต้องทำการตรวจสอบ

คุณควรจัดการข้อยกเว้นเฉพาะเมื่อคุณรู้ว่าจะต้องจัดการอะไรและอย่างไร

ฉันคิดว่ารหัสดั้งเดิมของคุณดีพอสิ่งเดียวคือคุณอาจต้องการจัดการกับข้อยกเว้นใน "หลัก" (หรือเลเยอร์ใด ๆ ที่รู้วิธีจัดการ)


1
ดูอีกตัวอย่างรหัส 2; ฉันเริ่มต้นข้อยกเว้นใหม่ด้วยข้อยกเว้นที่ต่ำกว่า การติดตามสแต็กทั้งหมดถูกเก็บรักษาไว้
Rock Anthony Johnson

อุ่ย ความผิดพลาดของฉัน.
user251630

-1

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

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


1
ความจริงที่ว่าคุณสามารถเขียนสิ่งที่ไม่บริสุทธิ์ออกไปไม่ได้ทำให้ฟังก์ชั่นนั้นบริสุทธิ์ Haskell เป็นข้อพิสูจน์ว่าการใช้งานฟังก์ชั่นไม่บริสุทธิ์สามารถเขียนใหม่ด้วยฟังก์ชั่นบริสุทธิ์ - มันใช้พระในการเข้ารหัสพฤติกรรมที่ไม่บริสุทธิ์ใด ๆ ในการกลับมาฟังก์ชั่นบริสุทธิ์บริสุทธิ์ การมีอยู่ของ IO monads ไม่ได้บอกเป็นนัยว่า IO ปกตินั้นบริสุทธิ์ - ทำไมการมีอยู่ของ monads นั้นจึงมีความหมายว่าการยกเว้นปกตินั้นบริสุทธิ์
Idan Arye

@IdanArye: ฉันเถียงว่าไม่มีสิ่งเจือปนในตอนแรก ตัวอย่างการเขียนใหม่เป็นเพียงเพื่อแสดงให้เห็นว่า IO ปกติไม่บริสุทธิ์เนื่องจากทำให้เกิดผลข้างเคียงที่สังเกตได้หรืออาจส่งคืนค่าที่แตกต่างกันด้วยอินพุตเดียวกันเนื่องจากอินพุตภายนอกบางอย่าง การโยนข้อยกเว้นไม่ได้ทำสิ่งเหล่านั้น
JacquesB

รหัสฟรีผลข้างเคียงไม่เพียงพอ Referential Transparencyยังเป็นข้อกำหนดสำหรับความบริสุทธิ์ของฟังก์ชั่น
Idan Arye

1
การกำหนดไม่เพียงพอสำหรับความโปร่งใสในการอ้างอิง - ผลข้างเคียงสามารถกำหนดได้เช่นกัน Referential transparent หมายความว่าสามารถแทนที่นิพจน์ด้วยผลลัพธ์ของมันได้ดังนั้นไม่ว่าคุณจะประเมินนิพจน์โปร่งใสที่อ้างอิงได้ในลำดับใดและคุณประเมินค่านิพจน์ทั้งหมดหรือไม่ก็ตามไม่ว่ากี่ครั้งก็ตาม หากมีข้อยกเว้นเกิดขึ้นจากการโยนทิ้งเราจะดีกับเกณฑ์ "ไม่ว่ากี่ครั้ง" แต่ไม่ใช่กับข้อยกเว้นอื่น ๆ ฉันได้โต้แย้งเกี่ยวกับเกณฑ์ "หรือไม่" ในคำตอบของฉันเอง (ต่อ ... )
Idan Arye

1
( ... ต่อ) และสำหรับการ "ในสิ่งที่สั่งซื้อ" - ถ้าfและgมีทั้งฟังก์ชั่นที่บริสุทธิ์แล้วf(x) + g(x)ควรจะมีผลเหมือนกันโดยไม่คำนึงถึงคำสั่งที่คุณประเมินและf(x) g(x)แต่ถ้าf(x)พ่นFและg(x)พ่นGแล้วยกเว้นโยนลงมาจากการแสดงออกนี้จะเป็นFถ้าf(x)ได้รับการประเมินครั้งแรกและGถ้าg(x)ได้รับการประเมินครั้งแรก - นี้ไม่ได้เป็นวิธีที่บริสุทธิ์ฟังก์ชั่นควรประพฤติ! เมื่อข้อยกเว้นถูกเข้ารหัสในประเภทส่งคืนผลลัพธ์นั้นจะกลายเป็นสิ่งที่คล้ายError(F) + Error(G)กับลำดับการประเมินอิสระ
Idan Arye
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.