ขออภัยสำหรับชื่อวาฟเฟิล - ถ้าฉันสามารถสร้างชื่อที่กระชับได้ฉันไม่ต้องถามคำถาม
สมมติว่าฉันมีประเภทรายการที่ไม่เปลี่ยนรูป มันมีการดำเนินงานFoo(x)
ที่ส่งกลับรายการที่ไม่เปลี่ยนรูปใหม่ที่มีข้อโต้แย้งที่ระบุว่าเป็นองค์ประกอบพิเศษในตอนท้าย ดังนั้นเพื่อสร้างรายการของสตริงที่มีค่า "Hello", "immutable", "world" คุณสามารถเขียน:
var empty = new ImmutableList<string>();
var list1 = empty.Foo("Hello");
var list2 = list1.Foo("immutable");
var list3 = list2.Foo("word");
(นี่คือรหัส C # และฉันสนใจคำแนะนำ C # มากที่สุดหากคุณรู้สึกว่าภาษามีความสำคัญไม่ใช่คำถามทางภาษา แต่พื้นฐานของภาษาอาจมีความสำคัญ)
สิ่งสำคัญคือรายการที่มีอยู่จะไม่เปลี่ยนแปลงโดยFoo
ดังนั้นempty.Count
จะยังคงกลับ 0
อีกวิธีหนึ่ง (สำนวนมากขึ้น) ของการบรรลุผลจะเป็น:
var list = new ImmutableList<string>().Foo("Hello")
.Foo("immutable")
.Foo("word");
คำถามของฉันคืออะไรชื่อที่ดีที่สุดสำหรับ Foo คืออะไร?
แก้ไข 3 : เมื่อฉันเปิดเผยในภายหลังชื่อของประเภทอาจไม่เป็นจริงImmutableList<T>
ซึ่งทำให้ตำแหน่งชัดเจน ลองนึกภาพว่ามันเป็นแบบนั้นTestSuite
และมันไม่เปลี่ยนรูปเพราะทั้งเฟรมมันเป็นส่วนหนึ่งของมันไม่เปลี่ยนรูป ...
(สิ้นสุดการแก้ไข 3)
ตัวเลือกฉันมาด้วยจนถึงตอนนี้:
Add
: ทั่วไปใน. NET แต่หมายถึงการกลายพันธุ์ของรายการเดิมCons
: ฉันเชื่อว่านี่เป็นชื่อปกติในภาษาที่ใช้งานได้ แต่ไม่มีความหมายสำหรับผู้ที่ไม่มีประสบการณ์ในภาษาดังกล่าวPlus
: ที่ชื่นชอบเพื่อให้ห่างไกลก็ไม่ได้หมายความถึงการกลายพันธุ์ให้ฉัน เห็นได้ชัดว่าสิ่งนี้ยังใช้ใน Haskellแต่ด้วยความคาดหวังที่แตกต่างกันเล็กน้อย (โปรแกรมเมอร์ Haskell อาจคาดหวังว่าจะเพิ่มสองรายการด้วยกันแทนที่จะเพิ่มค่าเดียวในรายการอื่น)With
: สอดคล้องกับอนุสัญญาที่ไม่เปลี่ยนรูปแบบอื่น ๆ แต่ไม่มี "การเพิ่ม" ที่เหมือนกันกับ IMOAnd
: ไม่สื่อความหมายมาก- ตัวดำเนินการโอเวอร์โหลดสำหรับ +: ฉันไม่ชอบสิ่งนี้มากนัก ฉันคิดว่าผู้ประกอบการควรใช้กับประเภทระดับล่างเท่านั้น ฉันยินดีที่จะโน้มน้าวใจ!
เกณฑ์ที่ฉันใช้ในการเลือกคือ:
- ให้การแสดงผลที่ถูกต้องของผลลัพธ์ของการเรียกเมธอด (นั่นคือเป็นรายการดั้งเดิมพร้อมองค์ประกอบเพิ่มเติม)
- ทำให้ชัดเจนที่สุดเท่าที่จะเป็นไปได้ซึ่งจะไม่ทำให้เกิดการเปลี่ยนแปลงรายการที่มีอยู่
- ฟังดูสมเหตุสมผลเมื่อถูกล่ามโซ่ไว้ด้วยกันตามตัวอย่างที่สองด้านบน
โปรดสอบถามรายละเอียดเพิ่มเติมหากฉันไม่ทำให้ตัวเองชัดเจน ...
แก้ไข 1:นี่คือเหตุผลของฉันสำหรับการเลือกที่จะPlus
Add
พิจารณาโค้ดสองบรรทัดนี้:
list.Add(foo);
list.Plus(foo);
ในมุมมองของฉัน (และนี่เป็นเรื่องส่วนตัว) สิ่งหลังนี้มีความชัดเจนมาก - มันเหมือนกับการเขียน "x + 5;" เป็นคำสั่งในตัวของมันเอง บรรทัดแรกดูเหมือนจะไม่เป็นไรจนกว่าคุณจะจำได้ว่ามันไม่เปลี่ยนรูป ในความเป็นจริงวิธีการที่ตัวดำเนินการบวกด้วยตัวของมันเองไม่ได้กลายเป็นตัวถูกดำเนินการของมันก็เป็นอีกสาเหตุหนึ่งที่Plus
ฉันชอบ หากไม่มีความยุ่งเหยิงเล็กน้อยของโอเปอเรเตอร์การบรรทุกเกินพิกัดก็ยังคงให้ความหมายที่เหมือนกันซึ่งรวมถึง (สำหรับฉัน) ที่ไม่กลายพันธุ์ตัวถูกดำเนินการ (หรือเป้าหมายของวิธีการในกรณีนี้)
แก้ไข 2:เหตุผลที่ไม่ชอบเพิ่ม
คำตอบที่หลากหลายนั้นมีประสิทธิภาพ: "ไปกับเพิ่มนั่นคือสิ่งที่DateTime
ทำและString
มีReplace
วิธีการอื่น ๆ ที่ไม่ทำให้การเปลี่ยนแปลงไม่ได้ชัดเจน" ฉันเห็นด้วย - มีความสำคัญที่นี่ แต่ผมเคยเห็นคนจำนวนมากโทรDateTime.Add
หรือString.Replace
และคาดหวังว่าการกลายพันธุ์ มีคำถามกลุ่มข่าวสารมากมาย (และอาจเป็นคำถามที่ถ้าฉันขุด) ซึ่งตอบโดย "คุณไม่สนใจค่าส่งคืนของString.Replace
; สตริงไม่เปลี่ยนรูป, สตริงใหม่จะได้รับคืน"
ตอนนี้ฉันควรเปิดเผยความละเอียดของคำถาม - ประเภทอาจไม่เป็นรายการที่ไม่เปลี่ยนรูป แต่เป็นประเภทที่ไม่เปลี่ยนรูปแบบอื่น โดยเฉพาะอย่างยิ่งฉันกำลังทำงานกับเฟรมเวิร์กการเปรียบเทียบซึ่งคุณเพิ่มการทดสอบลงในชุดและสร้างชุดใหม่ อาจเป็นที่ชัดเจนว่า:
var list = new ImmutableList<string>();
list.Add("foo");
จะไม่ประสบความสำเร็จอะไรเลย แต่มันจะกลายเป็นเรื่องไม่ดีมากเมื่อคุณเปลี่ยนเป็น:
var suite = new TestSuite<string, int>();
suite.Add(x => x.Length);
ดูเหมือนว่าควรจะไม่เป็นไร สำหรับฉันแล้วสิ่งนี้ทำให้ความผิดพลาดชัดเจนขึ้น:
var suite = new TestSuite<string, int>();
suite.Plus(x => x.Length);
นั่นเป็นเพียงการขอร้องให้เป็น:
var suite = new TestSuite<string, int>().Plus(x => x.Length);
เป็นการดีที่ฉันต้องการให้ผู้ใช้ไม่ต้องบอกว่าชุดทดสอบไม่เปลี่ยนรูป ฉันต้องการให้พวกเขาตกอยู่ในหลุมแห่งความสำเร็จ นี้อาจจะเป็นไปไม่ได้ แต่ผมอยากจะลอง
ฉันขอโทษที่ทำให้คำถามดั้งเดิมง่ายเกินไปโดยพูดถึงประเภทลิสต์ที่ไม่เปลี่ยนรูปเท่านั้น คอลเล็คชั่นบางตัวนั้นไม่ได้อธิบายตัวเองได้ดีเท่าImmutableList<T>
:)