มีอะไรผิดพลาดในบริบทของการเขียนโปรแกรมการทำงานถ้าวัตถุของฉันไม่แน่นอน?


9

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

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

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

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

OO ช่วยในการจัดการการพึ่งพาและเขียนโปรแกรมที่ง่ายขึ้นและบำรุงรักษาด้วยความช่วยเหลือของเครื่องมือเช่น encapsulation, polymorphism เป็นต้น

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


1
@Ruben ฉันต้องการกล่าวว่าภาษาที่ทำงานส่วนใหญ่ไม่อนุญาตให้ตัวแปรที่ไม่แน่นอน แต่ทำให้มันแตกต่างกันจะใช้พวกเขาเช่นตัวแปรที่ไม่แน่นอนมีประเภทที่แตกต่างกัน
JK

1
ฉันคิดว่าคุณอาจสับสนและเปลี่ยนแปลงไม่ได้ในย่อหน้าแรกของคุณ?
jk

1
@jk. เขาทำอย่างแน่นอน แก้ไขให้ถูกต้องแล้ว
David Arno

6
@ Ruben การเขียนโปรแกรมฟังก์ชั่นเป็นกระบวนทัศน์ ดังนั้นจึงไม่จำเป็นต้องมีภาษาโปรแกรมที่ใช้งานได้ และบางภาษา fp เช่น F # มีคุณสมบัตินี้
Christophe

1
@ Ruben ไม่เฉพาะฉันคิด Mvars ใน haskell hackage.haskell.org/package/base-4.9.1.0/docs/…ภาษาที่แตกต่างกันมีวิธีแก้ปัญหาที่แตกต่างกันแน่นอนหรือ IORefs hackage.haskell.org/package/base-4.11.1.0 /docs/Data-IORef.htmlถึงแม้ว่าคุณจะใช้ทั้งจาก monads
jk

คำตอบ:


7

ฉันคิดว่าความสำคัญนั้นแสดงให้เห็นได้ดีที่สุดเมื่อเปรียบเทียบกับวิธีการของ OO

เช่นว่าเรามีวัตถุ

Order
{
    string Status {get;set;}
    Purchase()
    {
        this.Status = "Purchased";
    }
}

ในกระบวนทัศน์ OO วิธีการที่แนบมากับข้อมูลและมันทำให้รู้สึกสำหรับข้อมูลที่จะกลายพันธุ์โดยวิธีการ

var order = new Order();
order.Purchase();
Console.WriteLine(order.Status); // "Purchased"

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

var order = new Order(); //this is a 'new order'
var purchasedOrder = purchase(order); // this is a 'purchased order'
Console.WriteLine(order.Status); // "New" order is still a 'new order'

คุณคาดหวังคำสั่งซื้อสถานะ == "ซื้อแล้ว" หรือไม่

นอกจากนี้ยังแสดงว่าหน้าที่ของเรานั้นเป็น idempotent กล่าวคือ การรันสองครั้งควรให้ผลลัพธ์เหมือนกันทุกครั้ง

var order = new Order(); //new order
var purchasedOrder = purchase(order); //purchased order
var purchasedOrder2 = purchase(order); //another purchased order
var purchasedOrder = purchase(purchasedOrder); //error! cant purchase an order twice

หากมีการเปลี่ยนแปลงคำสั่งซื้อโดยฟังก์ชั่นการซื้อที่ซื้อ Order2 จะล้มเหลว

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

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

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

หากฟังก์ชั่นเปลี่ยนแปลงการป้อนข้อมูลของเราจะต้องระมัดระวังมากขึ้นเกี่ยวกับสิ่งดังกล่าว


ขอบคุณ !! มีประโยชน์มาก ดังนั้นการดำเนินการซื้อใหม่จะมีลักษณะเช่นนี้Order Purchase() { return new Order(Status = "Purchased") } เพื่อให้สถานะเป็นฟิลด์อ่านอย่างเดียว ? ทำไมการฝึกนี้จึงมีความเกี่ยวข้องมากขึ้นในบริบทของกระบวนทัศน์การเขียนโปรแกรมฟังก์ชั่น? ประโยชน์ที่คุณกล่าวถึงสามารถเห็นได้ในการเขียนโปรแกรม OO เช่นกันใช่ไหม?
rahulaga_dev

ใน OO คุณจะคาดหวัง object.Purchase () เพื่อแก้ไขวัตถุ คุณสามารถทำให้มันไม่เปลี่ยนรูป แต่ทำไมไม่เปลี่ยนเป็นกระบวนทัศน์การทำงานเต็มรูปแบบ
Ewan

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

3
คุณสามารถเขียน functional c # เปลี่ยน object ของคุณเป็น struct, ทำให้มันไม่เปลี่ยนรูปและเขียน Func <Order, Order> Purchase
Ewan

12

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

สิ่งสำคัญที่ต้องถามคือสิ่งที่เป็นประโยชน์ของการเปลี่ยนแปลงไม่ได้? คำตอบคือมันหลีกเลี่ยงความซับซ้อน บอกว่าเรามีสองตัวแปรและx ทั้งสองเริ่มต้นด้วยค่าของy แม้ว่าจะเพิ่มเป็นสองเท่าทุกๆ 13 วินาที มูลค่าของแต่ละคนจะเป็นอย่างไรในเวลา 20 วัน? จะเป็น ง่ายมาก มันต้องใช้ความพยายามมากกว่าที่จะคิดออกมาเพราะมันซับซ้อนมากขึ้น เวลากี่วันใน 20 วัน? ฉันต้องคำนึงถึงการบันทึกเวลากลางวันหรือไม่? ความซับซ้อนของเมื่อเทียบกับเป็นเพียงมากขึ้น1yx1yyx

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

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


4
"หนึ่งในวิธีที่ง่ายที่สุดในการลดความซับซ้อนคือการทำให้สิ่งที่เปลี่ยนไม่ได้โดยค่าเริ่มต้นและทำให้ไม่แน่นอนเมื่อจำเป็น": สรุปที่ดีและกระชับ
Giorgio

2
@DavidArno ความซับซ้อนที่คุณอธิบายทำให้รหัสยากที่จะเข้าใจ คุณสัมผัสกับสิ่งนี้เมื่อคุณพูดว่า "รหัสนี้ยากที่จะเขียนยากที่จะอ่านยากที่จะดีบั๊ก ... " ฉันชอบออบเจ็กต์ที่ไม่เปลี่ยนรูปเพราะพวกเขาทำให้โค้ดง่ายขึ้นมากที่จะให้เหตุผลไม่ใช่แค่ด้วยตัวเอง แต่เป็นผู้สังเกตการณ์ที่ดูโดยไม่ทราบว่าโครงการทั้งหมด
แยกชิ้นส่วน -5

1
@RahulAgarwal " แต่ทำไมปัญหานี้จึงเด่นกว่าในบริบทของการเขียนโปรแกรมการทำงาน " มันไม่ได้ ฉันคิดว่าบางทีฉันอาจสับสนในสิ่งที่คุณถามเนื่องจากปัญหานั้นโดดเด่นน้อยกว่าใน FP เพราะ FP กระตุ้นให้ไม่สามารถเคลื่อนไหวได้ดังนั้นจึงหลีกเลี่ยงปัญหา
David Arno

1
@djechlin " ตัวอย่าง 13 วินาทีของคุณจะวิเคราะห์ได้ง่ายขึ้นด้วยรหัสที่เปลี่ยนรูปไม่ได้อย่างไร " ไม่สามารถ: yต้องกลายพันธุ์; นั่นเป็นข้อกำหนด บางครั้งเราต้องมีรหัสที่ซับซ้อนเพื่อตอบสนองความต้องการที่ซับซ้อน ประเด็นที่ฉันพยายามทำก็คือควรหลีกเลี่ยงความซับซ้อนที่ไม่จำเป็น ค่าการกลายพันธุ์มีความซับซ้อนมากกว่าค่าคงที่โดยเนื้อแท้ดังนั้น - เพื่อหลีกเลี่ยงความซับซ้อนที่ไม่จำเป็น - กลายพันธุ์ค่าเมื่อคุณต้อง
David Arno

3
ความไม่แน่นอนก่อให้เกิดวิกฤตเอกลักษณ์ ตัวแปรของคุณไม่มีตัวตนเดียวอีกต่อไป แต่ตอนนี้ตัวตนของมันขึ้นอยู่กับเวลา ดังนั้นในเชิงสัญลักษณ์แทนที่จะเป็น x เดี่ยวตอนนี้เรามีครอบครัว x_t รหัสใด ๆ ที่ใช้ตัวแปรนั้นจะต้องกังวลเกี่ยวกับเวลาเช่นกันทำให้เกิดความซับซ้อนเพิ่มขึ้นในคำตอบ
อเล็กซ์ Vong

8

สิ่งที่ผิดพลาดในบริบทของการเขียนโปรแกรมการทำงาน

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

IMHO ความแตกต่างที่แท้จริงเพียงอย่างเดียวระหว่างการเขียนโปรแกรมเชิงฟังก์ชั่นและที่ไม่ใช่ฟังก์ชั่นคือในโค้ดที่ไม่ใช้งานได้คุณมักจะคาดหวังผลข้างเคียงจากการเขียนโปรแกรมเชิงฟังก์ชั่น

โดยทั่วไปถ้ามันไม่ดีก็ไม่ดีโดยไม่คำนึงถึง OO หรือกระบวนทัศน์การเขียนโปรแกรมการทำงานใช่ไหม

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


4

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

for (elem <- rows map (row => s3 map row)) {
  val elem_str = elem.map(_.toString)

  logger.info("verifying the S3 bucket passed from the ctrl table for each App")
  logger.info(s"Checking on App Code: ${elem head}")

  listS3Buckets(elem_str(1), elem_str(2)) match {

    case Some(allBktsInfo) =>
      logger.info(s"App: ${elem_str head} provided the bucket name as: ${elem_str(3)}")
      if (allBktsInfo.exists(x => x.getName == elem_str(3))) {
        logger.info(s"Provided S3 bucket: ${elem_str(3)} exists")
        println(s"s3 ${elem_str(3)} bucket exists")
      } else {
        logger.info(s"WARNING: Provided S3 bucket ${elem_str(3)} doesn't exists")
        logger.info(s"WARNING: Dropping the App: ${elem_str.head} from backup schedule")
        excludeList += elem_str.head // If the bucket is invalid then we exclude from backup
        println(s"s3 bucket ${elem_str(3)} doesn't exists")
    }

    case None =>
      logger.info(s"WARNING: Provided S3 bucket ${elem_str(3)} doesn't exists")
      logger.info(s"WARNING: Dropping the App: ${elem_str.head} from backup schedule")
      excludeList += elem_str.head // If the bucket is invalid then we exclude from backup
}

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

val (exists, missing) = rows partition bucketExists
missing foreach {row =>
  logger.info(s"WARNING: Provided S3 bucket ${row("s3_primary_bkt_name")} doesn't exist")
  logger.info(s"WARNING: Dropping the App: ${row("app")} from backup schedule")
}

3

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

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

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

  1. วัตถุที่ไม่สามารถเปลี่ยนแปลงสิ่งใด ๆ ไม่ได้แม้จะมีการอ้างอิง วัตถุดังกล่าวและการอ้างอิงถึงพวกเขาประพฤติตนเป็นค่านิยมและสามารถแบ่งปันได้อย่างอิสระ

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

  3. วัตถุที่จะเปลี่ยนแปลง วัตถุเหล่านี้จะดูดีที่สุดเป็นภาชนะบรรจุและการอ้างอิงถึงพวกเขาเป็นตัวบ่งชี้

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

(*) ในรหัสแบบมัลติเธรดอาจจำเป็นต้องใช้ "memory barrier" เพื่อให้แน่ใจว่าก่อนที่ thread ใด ๆ อาจเห็นการอ้างอิงใด ๆ ถึง wrapper ผลกระทบของการกระทำทั้งหมดในคอนเทนเนอร์จะสามารถมองเห็นได้ในเธรดนั้น แต่ เป็นกรณีพิเศษที่กล่าวถึงที่นี่เพื่อความสมบูรณ์เท่านั้น


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

@RahulAgarwal: เป็นไปได้ที่จะมีการอ้างอิงไปยังวัตถุห่อหุ้มคุณค่าที่ความหมายไม่ได้รับผลกระทบจากการมีอยู่ของการอ้างอิงอื่น ๆ ไปยังวัตถุเดียวกันมีตัวตนที่จะเชื่อมโยงพวกเขากับการอ้างอิงอื่น ๆ ไปยังวัตถุเดียวกันหรือไม่ หากการเปลี่ยนแปลงสถานะคำพูดจริงแล้วค่าหรือตัวตนของวัตถุที่เกี่ยวข้องกับสถานะนั้นอาจจะคงที่ แต่ไม่ทั้งสอง - หนึ่งจะต้องมีการเปลี่ยนแปลง $ 50,000 คือสิ่งที่ควรทำ
supercat

1

ดังที่ได้กล่าวไปแล้วปัญหาเกี่ยวกับสถานะที่ไม่แน่นอนนั้นโดยทั่วไปแล้วเป็น subclass ของปัญหาใหญ่ของผลข้างเคียงโดยที่ return-type ของฟังก์ชั่นนั้นไม่ได้อธิบายอย่างถูกต้องว่าฟังก์ชั่นนี้ทำอะไรเพราะในกรณีนี้ ปัญหานี้ได้รับการแก้ไขโดยภาษาการวิจัยใหม่บางภาษาเช่น F * ( http://www.fstar-lang.org/tutorial/ ) ภาษานี้สร้างระบบเอฟเฟกต์ที่คล้ายกับระบบพิมพ์โดยที่ฟังก์ชั่นไม่เพียง แต่ประกาศแบบคงที่เท่านั้น แต่ยังมีผลกระทบด้วย ด้วยวิธีนี้ผู้โทรของฟังก์ชั่นจะทราบว่าการกลายพันธุ์ของรัฐอาจเกิดขึ้นเมื่อมีการเรียกใช้ฟังก์ชั่นและผลกระทบนั้นจะแพร่กระจายไปยังผู้โทร

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