ภาษาโปรแกรมสำหรับการใช้งานฟังก์ชั่นล้วนจัดการโดยไม่มีคำสั่งมอบหมายได้อย่างไร


26

เมื่ออ่าน SICP ที่มีชื่อเสียงฉันพบว่าผู้เขียนค่อนข้างลังเลที่จะแนะนำคำสั่งมอบหมายให้ Scheme ในบทที่ 3 ฉันอ่านข้อความและเข้าใจว่าทำไมพวกเขาถึงรู้สึกเช่นนั้น

เนื่องจาก Scheme เป็นภาษาโปรแกรมภาษาแรกที่ใช้งานได้ฉันรู้อะไรบางอย่างฉันรู้สึกประหลาดใจที่มีภาษาโปรแกรมบางฟังก์ชั่น (ไม่ใช่แบบแผนของหลักสูตร) ​​สามารถทำได้โดยไม่ได้รับมอบหมาย

ขอใช้ตัวอย่างข้อเสนอจากหนังสือbank accountตัวอย่าง หากไม่มีคำแถลงการมอบหมายสิ่งนี้สามารถทำได้อย่างไรจะเปลี่ยนแปลงbalanceตัวแปรได้อย่างไร? ฉันถามเพราะฉันรู้ว่ามีบางภาษาที่เรียกว่าบริสุทธิ์ฟังก์ชั่นออกมีและตามทฤษฎีทัวริงที่สมบูรณ์ก็ต้องทำเช่นนี้

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

ตัวอย่างดังกล่าวข้างต้นอยู่ที่นี่:

(define (make-withdraw balance)
    (lambda (amount)
        (if (>= balance amount)
            (begin (set! balance (- balance amount))
                balance)
            "Insufficient funds")))

นี้มีการเปลี่ยนแปลงโดยbalance สำหรับผมแล้วมันดูมากเช่นวิธีการเรียนการเปลี่ยนแปลงสมาชิกในชั้นเรียนset!balance

ดังที่ฉันพูดฉันไม่คุ้นเคยกับภาษาโปรแกรมที่ใช้งานได้ดังนั้นหากฉันพูดอะไรผิดเกี่ยวกับพวกเขารู้สึกอิสระที่จะชี้ให้เห็น


1
เกี่ยวกับการเรียนรู้ภาษาที่ใช้งานได้อย่างหมดจด: ฉันไม่แนะนำให้ทำแบบนั้นในทันที ถ้าคุณเรียนรู้ Haskell นอกเหนือจากการเรียนรู้วิธีการเขียนโปรแกรมโดยไม่มีตัวแปรที่ไม่แน่นอนคุณจะต้องเรียนรู้เกี่ยวกับความเกียจคร้านและวิธีการของ Haskell ในการทำ IO นั่นอาจจะเป็นเพียงเล็กน้อยในครั้งเดียว หากคุณต้องการที่จะเรียนรู้การเขียนโปรแกรมโดยไม่ต้องรัฐไม่แน่นอนวิธีที่ง่ายที่สุดอาจจะเป็นเพียงแค่การเขียนพวงของโปรแกรมโครงการโดยไม่ต้องใช้set!หรือฟังก์ชั่นอื่น ๆ !ที่จบลงด้วยการ เมื่อคุณพอใจกับสิ่งนั้นแล้วการเปลี่ยนไปใช้ FP บริสุทธิ์ควรง่ายขึ้น
sepp2k

คำตอบ:


21

หากไม่มีคำสั่งการมอบหมายสามารถทำสิ่งนี้ได้อย่างไรจะเปลี่ยนแปลงตัวแปรสมดุลได้อย่างไร?

คุณไม่สามารถเปลี่ยนตัวแปรได้หากไม่มีตัวดำเนินการกำหนดประเภท

ฉันถามเพราะฉันรู้ว่ามีบางภาษาที่เรียกว่าบริสุทธิ์ฟังก์ชั่นออกมีและตามทฤษฎีทัวริงที่สมบูรณ์ก็ต้องทำเช่นนี้

ไม่มาก หากภาษาทัวริงสมบูรณ์นั่นหมายความว่าสามารถคำนวณสิ่งใดก็ได้ที่ภาษาทัวริงสมบูรณ์อื่น ๆ สามารถคำนวณได้ ไม่ได้หมายความว่าจะต้องมีคุณสมบัติทุกภาษาอื่น ๆ

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

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


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

account = make-withdraw(0)
ask for input until the user enters "quit"
    if the user entered "withdraw $x"
        account(x)
    if the user entered "deposit $x"
        account(-x)
    if the user entered "query"
        print("The balance of the account is " + account(0))

ต่อไปนี้เป็นวิธีการเขียนโปรแกรมเดียวกันโดยไม่ใช้ตัวแปรผันแปรได้ (ฉันไม่รำคาญกับ IO ที่โปร่งใสแบบอ้างอิงได้เนื่องจากคำถามไม่ได้เกี่ยวกับเรื่องนั้น):

function IO_loop(balance):
    ask for input
    if the user entered "withdraw $x"
        IO_loop(balance - x)
    if the user entered "deposit $x"
        IO_loop(balance + x)
    if the user entered "query"
        print("The balance of the account is " + balance)
        IO_loop(balance)
    if the user entered "quit"
        do nothing

 IO_loop(0)

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


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

@Gnijuohz มันขึ้นอยู่กับว่าคุณกำลังพยายามแก้ไขปัญหาอะไรอยู่เสมอ ตัวอย่างเช่นหากคุณมียอดเงินเริ่มต้นและรายการถอนเงินและเงินฝากและคุณต้องการทราบยอดคงเหลือหลังจากถอนเงินและฝากเงินคุณสามารถคำนวณยอดรวมของเงินฝากลบด้วยจำนวนเงินที่ถอนและเพิ่มยอดเงินเริ่มต้น . newBalance = startingBalance + sum(deposits) - sum(withdrawals)ดังนั้นในรหัสที่จะเป็น
sepp2k

1
@Gnijuohz ฉันได้เพิ่มโปรแกรมตัวอย่างในคำตอบของฉัน
sepp2k

ขอบคุณสำหรับเวลาและความพยายามที่คุณเขียนและเขียนคำตอบใหม่! :)
Gnijuohz

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

11

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

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

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


ฉันสนใจคำตอบของเราและตัวอย่างของ Haskell แต่เนื่องจากขาดความรู้เกี่ยวกับเรื่องนี้ฉันไม่สามารถเข้าใจส่วนสุดท้ายของคำตอบของคุณได้ (เช่นกันส่วนที่สอง :()
Gnijuohz

3
@Gnijuohz ย่อหน้าสุดท้ายจะบอกว่าแทนที่จะb = makeWithdraw(42); b(1); b(2); b(3); print(b(4))คุณก็สามารถทำb = 42; b1 = withdraw(b1, 1); b2 = withdraw(b1, 2); b3 = withdraw(b2, 3); print(withdraw(b3, 4));ที่ถูกกำหนดให้เป็นเพียงwithdraw withdraw(balance, amount) = balance - amount
sepp2k

3

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

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

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

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


"ในที่สุดภาษาใด ๆ ที่ใช้งานได้จริงจะต้องหยุดด้วยวิธีการทำงานที่หมดจดในบางครั้ง - โปรแกรมที่มีประโยชน์ส่วนใหญ่จะมีผลข้างเคียง" จริงอยู่ แต่จากนั้นคุณกำลังพูดถึงการทำ IO และเช่นนั้น โปรแกรมที่มีประโยชน์มากมายสามารถเขียนได้โดยไม่มีตัวแปรที่ไม่แน่นอน
sepp2k

1
... และด้วย "ส่วนใหญ่" ของโปรแกรมที่มีประโยชน์คุณหมายถึง "ทั้งหมด" ใช่ไหม ฉันมีปัญหาแม้จินตนาการถึงความเป็นไปได้ของการมีอยู่ของโปรแกรมใด ๆ ที่อาจเรียกได้ว่า "มีประโยชน์" ซึ่งไม่ได้ทำ I / O ซึ่งเป็นการกระทำที่ต้องใช้ผลข้างเคียงในทั้งสองทิศทาง
Mason Wheeler

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

1
@MasonWheeler: ตัวอย่างง่ายๆแบบง่ายๆ: การคำนวณnดิจิตของ pi ไม่จำเป็นต้องใช้ I / O ใด ๆ มันเป็นคณิตศาสตร์และตัวแปร "เท่านั้น" อินพุตที่จำเป็นเท่านั้นคือnและค่าส่งคืนคือ Pi (ถึงnหลัก)
Joachim Sauer

1
@Joachim Sauer ในที่สุดคุณจะต้องการพิมพ์ผลลัพธ์ไปที่หน้าจอหรือรายงานให้ผู้ใช้ทราบ และเริ่มแรกคุณจะต้องการโหลดค่าคงที่บางส่วนลงในโปรแกรมจากที่อื่น ดังนั้นถ้าคุณต้องการที่จะอวดความสนใจทุกโปรแกรมที่มีประโยชน์ต้องทำ IO ในบางจุดแม้ว่ามันจะเป็นกรณีเล็ก ๆ น้อย ๆ ที่แฝงตัวและซ่อนอยู่เสมอจากโปรแกรมเมอร์โดยสภาพแวดล้อม
blueberryfields

3

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

รุ่นที่ซับซ้อนมากขึ้นของกระบวนทัศน์นี้จะเรียกว่า "การเขียนโปรแกรมปฏิกิริยาการทำงาน" กล่าวถึงที่นี่ใน StackOverflow

วิธีที่ไร้เดียงสาในการทำหม้อแปลงกระแสมีปัญหาบางอย่าง เป็นไปได้ (อันที่จริงแล้วค่อนข้างง่าย) ในการเขียนโปรแกรมบั๊กกี้ที่เก็บคำขอเก่าทั้งหมดไว้รอบ ๆ ทำให้สิ้นเปลืองพื้นที่ อย่างจริงจังมากขึ้นเป็นไปได้ที่จะตอบสนองต่อคำขอปัจจุบันขึ้นอยู่กับคำขอในอนาคต การแก้ไขปัญหาเหล่านี้กำลังดำเนินการอยู่ Neel Krishnaswamiเป็นพลังที่อยู่เบื้องหลังพวกเขา

คำเตือน : ฉันไม่ได้อยู่ในคริสตจักรของการเขียนโปรแกรมการทำงานบริสุทธิ์ ที่จริงแล้วฉันไม่ได้เป็นของคริสตจักรใด :-)


ฉันเดาว่าคุณอยู่ในพระวิหารบ้างไหม? :-P
Gnijuohz

1
วัดแห่งความคิดอิสระ ไม่มีนักเทศน์อยู่ที่นั่น
Uday Reddy

2

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

(define +no-founds+ "Insufficient funds")

;; functional withdraw
(define (make-withdraw balance amount)
    (if (>= balance amount)
        (- balance amount)
        +no-founds+))

;; functional atm loop
(define (atm balance thunk)
  (let* ((amount (thunk balance)) 
         (new-balance (make-withdraw balance amount)))
    (if (eqv? new-balance +no-founds+)
        (cons +no-founds+ '())
        (cons (list 'withdraw amount 'balance new-balance) (atm new-balance thunk)))))

;; functional balance-line -> string 
(define (balance->string x)
  (if (eqv? x +no-founds+)
      (string-append +no-founds+ "\n")
      (if (null? x)
          "\n"
          (let ((first-token (car x)))
            (string-append
             (cond ((symbol? first-token) (symbol->string first-token))
                   (else (number->string first-token)))
             " "
             (balance->string (cdr x)))))))

;; functional thunk to test  
(define (input-10 x) 10) ;; define a purly functional input-method

;; since all procedures involved are functional 
;; we expect the same result every time.
;; we use this to test atm and make-withdraw
(apply string-append (map balance->string (atm 100 input-10)))

;; no program can be purly functional in any language.
;; From here on there are imperative dirty procedures!

;; A procedure to get input from user is needed. 
;; Side effects makes it imperative
(define (user-input balance)
  (display "You have $")
  (display balance)
  (display " founds. How much to withdraw? ")
  (read))

;; We need a procedure to print stuff to the console 
;; as well. Side effects makes it imperative
(define (pretty-print-result x)
  (for-each (lambda (x) (display (balance->string x))) x))

;; use imperative procedure with atm.
(pretty-print-result (atm 100 user-input))

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


+1 สำหรับตัวอย่างที่กว้างขวางและคำอธิบายที่สมจริงเกี่ยวกับชิ้นส่วนที่ใช้งานได้และชิ้นส่วนที่ใช้งานได้ไม่บริสุทธิ์ของโปรแกรมและกล่าวถึงสาเหตุที่ FP มีความสำคัญ
Zelphir Kaltstahl

1

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

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

ดูเหมือนจะไม่ได้ตอบคำถาม คุณตั้งโปรแกรมวัตถุบัญชีธนาคารในภาษาที่ใช้งานได้จริงได้อย่างไร
Uday Reddy

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

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