Cái tên nào hay nhất cho một phương thức add add không biến đổi trên một bộ sưu tập bất biến?


229

Xin lỗi vì tiêu đề khó hiểu - nếu tôi có thể đưa ra một tiêu đề ngắn gọn, tôi sẽ không phải đặt câu hỏi.

Giả sử tôi có một loại danh sách bất biến. Nó có một hoạt động Foo(x)trả về một danh sách bất biến mới với đối số được chỉ định là phần tử phụ ở cuối. Vì vậy, để xây dựng một danh sách các chuỗi có các giá trị "Xin chào", "bất biến", "thế giới" bạn có thể viết:

var empty = new ImmutableList<string>();
var list1 = empty.Foo("Hello");
var list2 = list1.Foo("immutable");
var list3 = list2.Foo("word");

(Đây là mã C # và tôi quan tâm nhất đến đề xuất C # nếu bạn cảm thấy ngôn ngữ là quan trọng. Về cơ bản, đây không phải là câu hỏi về ngôn ngữ, nhưng thành ngữ của ngôn ngữ có thể quan trọng.)

Điều quan trọng là các danh sách hiện tại không bị thay đổi bởi Foo- vì vậy empty.Countvẫn sẽ trả về 0.

Một cách khác (thành ngữ hơn) để đi đến kết quả cuối cùng sẽ là:

var list = new ImmutableList<string>().Foo("Hello")
                                      .Foo("immutable")
                                      .Foo("word");

Câu hỏi của tôi là: tên tốt nhất cho Foo là gì?

EDIT 3 : Như tôi tiết lộ sau này, tên của loại có thể không thực sự ImmutableList<T>, điều này làm cho vị trí rõ ràng. Thay vào đó hãy tưởng tượng rằng nó TestSuitevà nó bất biến bởi vì toàn bộ khuôn khổ mà nó là một phần của bất biến ...

(Kết thúc chỉnh sửa 3)

Các tùy chọn tôi đã đưa ra cho đến nay:

  • Add: phổ biến trong .NET, nhưng ngụ ý đột biến của danh sách gốc
  • Cons: Tôi tin rằng đây là tên bình thường trong các ngôn ngữ chức năng, nhưng vô nghĩa với những người không có kinh nghiệm trong các ngôn ngữ đó
  • Plus: yêu thích của tôi cho đến nay, nó không ngụ ý đột biến đối với tôi . Rõ ràng điều này cũng được sử dụng trong Haskell nhưng với những kỳ vọng hơi khác nhau (một lập trình viên Haskell có thể mong đợi nó sẽ thêm hai danh sách lại với nhau thay vì thêm một giá trị vào danh sách khác).
  • With: phù hợp với một số quy ước bất biến khác, nhưng không có cùng "tính bổ sung" với IMO.
  • And: không mô tả lắm.
  • Toán tử quá tải cho +: Tôi thực sự không thích điều này nhiều; Tôi thường nghĩ rằng các nhà khai thác chỉ nên được áp dụng cho các loại cấp thấp hơn. Tôi sẵn sàng để được thuyết phục mặc dù!

Các tiêu chí tôi đang sử dụng để lựa chọn là:

  • Cung cấp ấn tượng chính xác về kết quả của cuộc gọi phương thức (nghĩa là danh sách ban đầu có phần tử phụ)
  • Làm cho nó rõ ràng nhất có thể mà nó không làm thay đổi danh sách hiện có
  • Âm thanh hợp lý khi kết nối với nhau như trong ví dụ thứ hai ở trên

Vui lòng hỏi thêm chi tiết nếu tôi không làm cho mình đủ rõ ràng ...

EDIT 1: Dưới đây là lập luận của tôi cho thích Plusđến Add. Hãy xem xét hai dòng mã này:

list.Add(foo);
list.Plus(foo);

Theo quan điểm của tôi (và đây một vấn đề cá nhân) thì cái sau rõ ràng là có lỗi - nó giống như viết "x + 5;" như một tuyên bố trên chính nó. Dòng đầu tiên có vẻ ổn, cho đến khi bạn nhớ rằng nó không thay đổi. Trong thực tế, cách mà toán tử cộng tự nó không làm thay đổi toán hạng của nó là một lý do khác khiến Plustôi thích. Không có sự quá tải nhẹ của quá tải toán tử, nó vẫn đưa ra các ý nghĩa tương tự, bao gồm (đối với tôi) không làm thay đổi các toán hạng (hoặc mục tiêu phương thức trong trường hợp này).

EDIT 2: Lý do không thích Thêm.

Nhiều câu trả lời khác nhau có hiệu quả: "Đi với Thêm. Đó là những gì DateTime, và StringReplacecác phương pháp, v.v ... điều đó không làm cho tính bất biến trở nên rõ ràng." Tôi đồng ý - có quyền ưu tiên ở đây. Tuy nhiên, tôi đã nhìn thấy rất nhiều người gọi DateTime.Addhoặc String.Replacekỳ vọng đột biến . Có rất nhiều câu hỏi của nhóm tin tức (và có thể là những câu hỏi SO nếu tôi tìm hiểu kỹ) được trả lời bởi "Bạn đang bỏ qua giá trị trả về của String.Replace; chuỗi là bất biến, một chuỗi mới được trả về."

Bây giờ, tôi nên tiết lộ một sự tinh tế cho câu hỏi - loại có thể không thực sự là một danh sách bất biến, mà là một loại bất biến khác. Cụ thể, tôi đang làm việc trên một khung điểm chuẩn nơi bạn thêm các bài kiểm tra vào một bộ và điều đó tạo ra một bộ mới. Có thể rõ ràng rằng:

var list = new ImmutableList<string>();
list.Add("foo");

là sẽ không đạt được bất cứ điều gì, nhưng nó trở thành một nhiều murkier khi bạn thay đổi nó để:

var suite = new TestSuite<string, int>();
suite.Add(x => x.Length);

Có vẻ như nó sẽ ổn thôi. Trong khi đó, với tôi, làm cho sai lầm rõ ràng hơn:

var suite = new TestSuite<string, int>();
suite.Plus(x => x.Length);

Đó chỉ là cầu xin để được:

var suite = new TestSuite<string, int>().Plus(x => x.Length);

Lý tưởng nhất, tôi muốn người dùng của tôi không phải nói rằng bộ thử nghiệm là bất biến. Tôi muốn họ rơi vào hố thành công. Điều này có thể không thể, nhưng tôi muốn thử.

Tôi xin lỗi vì đã đơn giản hóa quá mức câu hỏi ban đầu bằng cách chỉ nói về một loại danh sách bất biến. Không phải tất cả các bộ sưu tập đều khá tự mô tả như ImmutableList<T>:)


2
@Adam: Không, cái sau rõ ràng là lỗi. Cả hai đều thực sự buggy (như họ đang làm gì với kết quả) - nhưng là người đầu tiên không tìm lỗi với tôi.
Jon Skeet

36
Là một chú chó con?
Michael Myers

7
Concat / Condog ... làm việc cho tôi! ;)
gnovice

11
Uncat - đó sẽ là một con mèo zombie.
Erik Forbes

2
@Trap: Điều đó thật tệ khi tạo ra chất lỏng API.
Jon Skeet

Câu trả lời:


130

Trong tình huống như vậy, tôi thường đi cùng Concat. Điều đó thường ngụ ý với tôi rằng một đối tượng mới đang được tạo ra.

var p = listA.Concat(listB);
var k = listA.Concat(item);

3
Đây là những gì tôi sử dụng, vì đó là những gì System.Linq.Enableable sử dụng - quyết định đã được đưa ra. :) Tôi không thể là người duy nhất xác định mức quá tải của riêng mình đối với tiện ích mở rộng Concat trên IEnumerable để chấp nhận một giá trị duy nhất được thêm vào.
Daniel Earwicker

9
1 Đây là những câu trả lời chính xác cho việc duy trì tính nhất quán đặt tên trong khuôn khổ.
Sam Harwell

Trừ khi tôi thiếu nó, System.Linq.Enumerable (và Linq nói chung) chỉ sử dụng Concat () cho "chuỗi + chuỗi", không bao giờ "mục + chuỗi". Vấn đề mà ai đó "có thể mong đợi nó sẽ thêm hai danh sách lại với nhau thay vì thêm một giá trị vào danh sách khác" được đưa ra rõ ràng là lý do không sử dụng một trong các tùy chọn ban đầu khác.
Ssswift

119

Tôi muốn đi với Cons, vì một lý do đơn giản: nó có nghĩa chính xác là những gì bạn muốn.

  1. Tôi là một fan hâm mộ lớn của việc nói chính xác những gì tôi muốn nói, đặc biệt là trong mã nguồn. Một người mới sẽ phải tra cứu định nghĩa của Cons chỉ một lần, nhưng sau đó đọc và sử dụng nó hàng ngàn lần. Tôi thấy rằng, về lâu dài, sẽ tốt hơn khi làm việc với các hệ thống giúp cho trường hợp phổ biến trở nên dễ dàng hơn, ngay cả khi chi phí trả trước cao hơn một chút.

  2. Thực tế là nó sẽ "vô nghĩa" với những người không có kinh nghiệm về FP thực sự là một lợi thế lớn. Như bạn đã chỉ ra, tất cả các từ khác bạn tìm thấy đều có một số ý nghĩa và ý nghĩa đó hơi khác biệt hoặc mơ hồ. Một khái niệm mới nên có một từ mới (hoặc trong trường hợp này là một từ cũ). Tôi thà rằng ai đó phải tìm định nghĩa về Nhược điểm, hơn là giả định không chính xác anh ta biết Add làm gì.

  3. Các hoạt động khác mượn từ các ngôn ngữ chức năng thường giữ nguyên tên gốc của chúng, không có thảm họa rõ ràng. Tôi chưa thấy bất kỳ sự thúc đẩy nào để đưa ra các từ đồng nghĩa cho "bản đồ" và "thu nhỏ" nghe có vẻ quen thuộc hơn với những người không phải là người kiểm lâm, tôi cũng không thấy bất kỳ lợi ích nào từ việc này.

(Tiết lộ đầy đủ: Tôi là một lập trình viên Lisp, vì vậy tôi đã biết Cons nghĩa là gì.)


16
Đừng quên rằng khả năng khám phá rất quan trọng - nếu tôi gõ "testSuite." và nhìn vào danh sách các phương thức, tôi muốn thấy một phương pháp gợi ý đúng. Tôi có lẽ sẽ không tìm kiếm một cái tên vô nghĩa (với tôi) trên phạm vi đó là những gì tôi muốn.
Jon Skeet

33
Nếu tôi cảm thấy lén lút, tôi sẽ tạo một phương thức Thêm mà chỉ đơn giản là ném một ngoại lệ với message = "Sử dụng Nhược điểm để thêm vào một Danh sách bất biến". :-)
Ken

2
Nó sẽ không giết bất cứ ai để đọc một vài dòng bình luận giải thích lý do tại sao tên đó là gì và nói đến "Cấu trúc và giải thích các chương trình máy tính" của Abelson & Sussman.
John R. Strohm

16
Theo truyền thống, khuyết điểm thêm vào lúc đầu chứ không phải cuối. Vì vậy, nó là một tên có khả năng gây hiểu nhầm cho phương pháp được mô tả.
walkytalky

16
Chỉ để lưu lập trình viên không có chức năng tiếp theo, một cú nhấp chuột hoặc 3 ... en.wikipedia.org/wiki/Cons từ từ "xây dựng", biểu thức "to cons x lên y" có nghĩa là xây dựng một đối tượng mới với ( khuyết điểm xy)
bí ẩn

59

Thật ra tôi thích And, đặc biệt là theo cách thành ngữ. Tôi đặc biệt thích nó nếu bạn có một thuộc tính chỉ đọc tĩnh cho danh sách rỗng và có thể đặt hàm tạo riêng tư để bạn luôn phải xây dựng từ danh sách trống.

var list = ImmutableList<string>.Empty.And("Hello")
                                      .And("Immutable")
                                      .And("Word");

Tôi thích ý tưởng trống rỗng. Vẫn không thuyết phục về Và mặc dù. Nó chỉ là một chút blah.
Jon Skeet

Nó giống như cách tôi nghĩ về việc xây dựng một danh sách các thứ bằng ngôn ngữ tự nhiên. Nếu bạn đọc thành tiếng thì có vẻ trực quan hơn Add hoặc Plus. "Danh sách" là danh sách trống và "Xin chào" và "Không thay đổi" và "Từ". Tuy nhiên, tôi đồng ý rằng nó ít rõ ràng hơn trong sự cô lập.
tvanfosson

52

Bất cứ khi nào tôi gặp rắc rối với danh pháp, tôi lại chạm vào nhau.

thesaurus.com trả lại cái này cho "add":

Định nghĩa: liền kề, tăng; bình luận thêm

Từ đồng nghĩa: affix, annex, ante, append, augment, cow up, boost, build up, Charge up, continue, cue in, hình trong, thịt ra, nóng lên, tăng, tăng, hitch lên, móc lên, móc lên với, bao gồm, kích lên, jazz lên, tham gia cùng nhau, pad, parlay, piggyback, cắm vào, đổ nó lên, trả lời, chạy lên, nói thêm, tát, ném tuyết, súp lên, tăng tốc, tăng vọt, bước lên, bổ sung, làm ngọt, giải quyết, gắn thẻ

Tôi thích âm thanh của Adjoin, hoặc đơn giản hơn Join. Đó là những gì bạn đang làm, phải không? Phương pháp này cũng có thể áp dụng để tham gia của người khác ImmutableList<>.


1
Tôi cũng giống như 'Tham gia' nhưng trong hầu hết các trường hợp, khi bạn tham gia 2 đối tượng, bạn kết thúc bằng 1. Trong trường hợp này, nếu bạn tham gia 2 đối tượng, bạn thực sự đang tạo một đối tượng mới.
Lập trình viên ngoài vòng pháp luật

1
Tôi không biết bất kỳ trường hợp nào trong .NET, Perl, PHP hoặc thậm chí VBScript trong đó Tham gia ngụ ý đột biến. Thiết kế sao cho A và B tham gia để tạo C, trong đó C luôn là một thực thể mới.
spoulson

Tôi thích Tham gia và tôi hoàn toàn đồng ý với thesaurus.com :) Sử dụng nó mọi lúc khi nghi ngờ về một cái tên.
Skurmedel

var suite = new TestSuite <string, int> () .Join (x => x.Lipse);
Sly Gryphon

3
Đi với Piggyback, imo. Hoặc HookUpWith.
Chris Marasti-Georg

48

Cá nhân, tôi thích .With (). Nếu tôi đang sử dụng đối tượng, sau khi đọc tài liệu hoặc nhận xét mã, nó sẽ rõ ràng những gì nó làm và nó đọc ok trong mã nguồn.

object.With("My new item as well");

Hoặc, bạn thêm "Cùng" với nó .. :)

object.AlongWith("this new item");

+1. "VỚI" là một toán tử infix trong SETL thực hiện điều tương tự. Nếu SETL sử dụng thì nó phải đúng :-)
finnw

1
Bah ... Ai dùng VB nữa? :) Uh .. Opps .. Điều đó có thành tiếng không? heh .. Nhưng, không, trong tất cả sự nghiêm túc, đó là lý do tại sao tôi coi là "Cùng với", điều đó sẽ loại bỏ vấn đề VB. Chỉ có khoảng một triệu cách khác nhau mà anh ta có thể đi với cách này ... Ý tôi là, ngay cả những cách điên rồ như: object.Plus () hoặc Object.Ex hiệnPlus () ... vv ... Đó là một câu hỏi hay đã đăng, tuy nhiên ... heh ..
LarryF

33

Tôi đã kết thúc với Add cho tất cả các Bộ sưu tập bất biến của mình trong BclExtras . Lý do là nó là một cái tên dễ đoán. Tôi không lo lắng quá nhiều về việc mọi người nhầm lẫn Thêm với một bổ sung đột biến vì tên của loại được đặt trước là bất biến.

Trong một lúc, tôi đã xem xét Cons và các tên kiểu chức năng khác. Cuối cùng tôi đã giảm giá cho họ vì họ gần như không nổi tiếng. Chắc chắn các lập trình viên chức năng sẽ hiểu nhưng họ không phải là đa số người dùng.

Tên khác: bạn đã đề cập:

  • Thêm vào đó: Tôi đang mơ ước / giặt cái này. Đối với tôi điều này không phân biệt nó là một hoạt động không đột biến nữa so với Add
  • Với: Sẽ gây ra sự cố với VB (ý định chơi chữ)
  • Quá tải toán tử: Khả năng khám phá sẽ là một vấn đề

Tùy chọn tôi đã xem xét:

  • Concat: String's là bất biến và sử dụng cái này. Thật không may, nó chỉ thực sự tốt để thêm vào cuối
  • CopyAdd: Sao chép cái gì? Nguồn, danh sách?
  • AddToNewList: Có thể là một cái tốt cho Danh sách. Nhưng những gì về Bộ sưu tập, Ngăn xếp, Hàng đợi, v.v ...

Thật không may, dường như không có một từ nào

  1. Chắc chắn là một hoạt động bất biến
  2. Có thể hiểu được với phần lớn người dùng
  3. Đại diện trong ít hơn 4 từ

Nó thậm chí còn kỳ quặc hơn khi bạn xem xét các bộ sưu tập khác ngoài Danh sách. Lấy ví dụ Stack. Ngay cả các lập trình viên năm đầu tiên cũng có thể nói với bạn rằng Stacks có một cặp phương thức Push / Pop. Nếu bạn tạo một ImmutableStack và đặt cho nó một cái tên hoàn toàn khác, hãy gọi nó là Foo / Fop, bạn vừa thêm nhiều công việc để họ sử dụng bộ sưu tập của bạn.

Chỉnh sửa: Trả lời Plus Chỉnh sửa

Tôi thấy bạn đang đi đâu với Plus. Tôi nghĩ rằng một trường hợp mạnh hơn sẽ thực sự là Minus để loại bỏ. Nếu tôi thấy những điều sau đây chắc chắn tôi sẽ tự hỏi các lập trình viên đang nghĩ gì trên thế giới

list.Minus(obj);

Vấn đề lớn nhất tôi gặp phải với Plus / Minus hoặc một cặp mới là cảm giác như quá mức cần thiết. Bộ sưu tập đã có một tên riêng biệt, tiền tố bất biến. Tại sao đi xa hơn bằng cách thêm từ vựng có ý định thêm phân biệt giống như tiền tố Bất biến đã làm.

Tôi có thể thấy các đối số trang web cuộc gọi. Nó làm cho nó rõ ràng hơn từ quan điểm của một biểu thức. Nhưng trong bối cảnh của toàn bộ chức năng có vẻ như không cần thiết.

Chỉnh sửa 2

Đồng ý rằng mọi người chắc chắn đã bị String.Concat và DateTime.Add nhầm lẫn. Tôi đã thấy một số lập trình viên rất sáng đánh vào vấn đề này.

Tuy nhiên tôi nghĩ rằng ImmutableList là một đối số khác nhau. Không có gì về String hoặc DateTime mà thiết lập nó là Bất biến đối với một lập trình viên. Bạn chỉ cần biết rằng nó bất biến thông qua một số nguồn khác. Vì vậy, sự nhầm lẫn là không bất ngờ.

ImmutableList không có vấn đề đó vì tên xác định hành vi của nó. Bạn có thể tranh luận rằng mọi người không biết bất biến là gì và tôi nghĩ điều đó cũng hợp lệ. Tôi chắc chắn không biết điều đó cho đến năm 2 ở trường đại học. Nhưng bạn có cùng một vấn đề với bất kỳ tên nào bạn chọn thay vì Thêm.

Chỉnh sửa 3: Điều gì về các loại như TestSuite không thay đổi nhưng không chứa từ này?

Tôi nghĩ điều này dẫn đến ý tưởng rằng bạn không nên phát minh ra tên phương thức mới. Cụ thể bởi vì rõ ràng có một ổ đĩa để làm cho các loại bất biến để tạo điều kiện cho các hoạt động song song. Nếu bạn tập trung vào việc thay đổi tên của các phương thức cho các bộ sưu tập, bước tiếp theo sẽ là các tên phương thức biến đổi trên mỗi loại bạn sử dụng là bất biến.

Tôi nghĩ rằng nó sẽ là một nỗ lực có giá trị hơn để thay vào đó tập trung vào việc làm cho các loại có thể nhận dạng là Bất biến. Bằng cách đó bạn có thể giải quyết vấn đề mà không cần suy nghĩ lại về mọi mẫu phương thức đột biến ngoài kia.

Bây giờ làm thế nào bạn có thể xác định TestSuite là bất biến? Trong môi trường ngày nay tôi nghĩ có một vài cách

  1. Tiền tố với bất biến: ImmutableTestSuite
  2. Thêm một thuộc tính mô tả mức độ bất biến. Điều này chắc chắn là ít khám phá
  3. Không nhiều lắm.

Tôi đoán / hy vọng là các công cụ phát triển sẽ bắt đầu giúp giải quyết vấn đề này bằng cách giúp dễ dàng xác định các loại bất biến chỉ bằng cách nhìn (màu sắc khác nhau, phông chữ mạnh hơn, v.v ...). Nhưng tôi nghĩ đó là câu trả lời mặc dù thay đổi tất cả các tên phương thức.


Đã thêm lý do cho sở thích của tôi cho Plus hơn Thêm vào câu hỏi. Rất hoan nghênh ý kiến ​​về lý do đó. Tôi thực sự cởi mở với ý tưởng rằng tôi thật ngớ ngẩn.
Jon Skeet

@JaredPar: Thế còn nếu loại được gọi là TestSuite thì sao?
Jon Skeet

Rất muốn cho +1 khác để chỉnh sửa 3, nhưng rõ ràng là không thể. (Trong trường hợp của tôi, tôi không cố gắng để có được sự song song - Tôi tin rằng sự bất biến dẫn đến mã dễ hiểu hơn.) Tôi vẫn không hoàn toàn tin rằng Add là con đường để đi, nhưng sự hỗ trợ cho câu trả lời ở đây có sức thuyết phục.
Jon Skeet

Nếu bạn có thể thả câu hỏi này vào cuộc trò chuyện tại nơi làm việc, điều đó cũng thật tuyệt vời, btw. Tôi bắt đầu cuộc thảo luận về danh sách C #, vì vậy một số đồng nghiệp có thể đã tham gia. Cũng có thể hỏi nội bộ tại Google ...
Jon Skeet

@Jon, tôi nghĩ rằng tôi biết một nơi tốt để bỏ câu hỏi này tại nơi làm việc :)
JaredPar

27

Tôi nghĩ rằng đây có thể là một trong những tình huống hiếm hoi khi chấp nhận quá tải cho người +vận hành. Trong thuật ngữ toán học, chúng ta biết rằng +không nối thêm thứ gì đó vào cuối của thứ khác. Nó luôn kết hợp hai giá trị với nhau và trả về một giá trị kết quả mới.

Ví dụ, rõ ràng là bằng trực giác khi bạn nói

x = 2 + 2;

giá trị kết quả của x là 4, không phải 22.

Tương tự như vậy,

var empty = new ImmutableList<string>();
var list1 = empty + "Hello";
var list2 = list1 + "immutable";
var list3 = list2 + "word";

nên làm rõ những gì mỗi biến sẽ giữ. Cần phải rõ ràng rằng list2không được thay đổi trong dòng cuối cùng, nhưng thay vào đó, nó list3được gán kết quả của việc thêm "từ" vào list2.

Nếu không, tôi sẽ chỉ đặt tên hàm Plus ().


Điều gì xảy ra nếu bạn có một danh sách chung, mà bạn có thể thêm một số nguyên (nói) hoặc một danh sách số nguyên khác một cách hợp pháp ? Sau đó, việc sử dụng + này sẽ xung đột với nối.
vây

@finnw: Tôi không thấy quan điểm của bạn. Với một danh sách tôi sẽ luôn mong đợi + có nghĩa là nối thêm, cho dù bạn đang thêm một yếu tố hay nhiều yếu tố.
Bill Lizard

4
Đối với API có thể sử dụng lại, bạn cũng nên có một phương thức được đặt tên, trong trường hợp ai đó đang sử dụng lớp của bạn từ một ngôn ngữ mà không bị quá tải toán tử.
Neil

"Cho dù bạn đang thêm một yếu tố hay nhiều yếu tố" - nếu bạn muốn thêm danh sách dưới dạng một yếu tố thì sao? tức là, [1] + 2 = [1,2]nhưng [1] + [2] = [1,[2]]. Những gì bạn đang đề xuất là hành vi không nhất quán. Đây có lẽ là lý do tại sao Python không cho phép bạn thêm một yếu tố theo cách này.
mở

Chà, trong một ngôn ngữ được nhập tĩnh như C #, bạn có thể cho biết loại phần tử danh sách là gì, cho dù danh sách danh sách hoặc danh sách các phần tử, vì vậy bạn có thể sử dụng loại để quyết định nên thêm một phần tử là danh sách hay ghép hai danh sách.
Dobes Vandermeer

22

Để rõ ràng nhất có thể, bạn có thể muốn đi với wordier CopyAndAdd, hoặc một cái gì đó tương tự.


Không phải tất cả các bộ sưu tập bất biến đòi hỏi một bản sao để thêm mặc dù. Hãy nghĩ về những cây bất biến, chúng chỉ cần một nút mới và có thể sử dụng cây hiện có như một chiếc lá.
JaredPar

BTW, tôi đọc hồ sơ của bạn, sau đó tuổi theo thứ tự và thoáng ngạc nhiên về tuổi của bạn. Sanity đá ngay sau đó.
JaredPar

Nhận xét đầu tiên: Tôi sử dụng cây rất hiếm khi suy nghĩ đó không bao giờ xảy ra với tôi. Đó là một điểm tốt.
Michael Myers

Nhận xét thứ hai: Tôi thú nhận, tôi đã làm nó cho huy hiệu! Tôi chỉ không muốn đưa ra tuổi của mình. (Tôi thực sự trẻ hơn bạn, nhưng tôi có thể chơi đồng hồ bấm giờ cũ kỹ khá tốt nếu tôi cần. Và tôi không phải là người duy nhất có tuổi được liệt kê là 89.)
Michael Myers

Đối số cây bất biến là một điểm mạnh, điểm tốt. Vì vậy, EquivalentReferenceWithAdded (x) sẽ chiến đấu với lập luận đó, nhưng nghe có vẻ ngu ngốc và khó suy luận.
TheBlastOne

21

Tôi sẽ gọi nó là Extend () hoặc có thể là ExtendWith () nếu bạn cảm thấy thực sự dài dòng.

Mở rộng có nghĩa là thêm một cái gì đó vào một cái gì đó khác mà không thay đổi nó. Tôi nghĩ rằng đây là thuật ngữ rất phù hợp trong C # vì nó tương tự như khái niệm về các phương thức mở rộng - chúng "thêm" một phương thức mới vào một lớp mà không "chạm" vào chính lớp đó.

Mặt khác, nếu bạn thực sự muốn nhấn mạnh rằng bạn hoàn toàn không sửa đổi đối tượng ban đầu, sử dụng một số tiền tố như Get- có vẻ như không thể tránh khỏi đối với tôi.


1
Still kinda ngụ ý làm một cái gì đó cho các đối tượng cơ sở.
hỗn loạn

18

Đã thêm (), Nối ()

Tôi thích sử dụng thì quá khứ cho các hoạt động trên các đối tượng bất biến. Nó truyền đạt ý tưởng rằng bạn không thay đổi đối tượng ban đầu và thật dễ dàng để nhận ra khi bạn nhìn thấy nó.

Ngoài ra, vì các tên phương thức đột biến thường là các động từ hiện tại, nên nó áp dụng cho hầu hết các trường hợp cần thiết về tên phương thức bất biến mà bạn gặp phải. Ví dụ, một ngăn xếp bất biến có các phương thức "đẩy" và "bật".


1
Python cũng sử dụng quy ước này. Ví dụ, các hàm dựng sẵn đảo ngược () và sort ().
Joe

18

Tôi thích đề xuất mmyer của CopyAndAdd . Để phù hợp với chủ đề "đột biến", có lẽ bạn có thể đi với Bud (sinh sản vô tính), Phát triển , Tái tạo hoặc Tiến hóa ? =)

EDIT: Để tiếp tục với chủ đề di truyền của tôi, làm thế nào về Procreate , ngụ ý rằng một đối tượng mới được tạo ra dựa trên đối tượng trước đó, nhưng với một cái gì đó mới được thêm vào.


14

Đây có lẽ là một sự kéo dài, nhưng trong Ruby có một ký hiệu thường được sử dụng để phân biệt: addkhông biến đổi; add!đột biến. Nếu đây là một vấn đề phổ biến trong dự án của bạn, bạn cũng có thể làm điều đó (không nhất thiết phải với các ký tự không phải là chữ cái, nhưng nhất quán sử dụng một ký hiệu để chỉ ra các phương pháp đột biến / không biến đổi).


+1. điều này không được thực thi bởi ngôn ngữ, nhưng được thỏa thuận như một quy ước. Tôi thích điều đó.
oma


13

Có thể sự nhầm lẫn bắt nguồn từ thực tế là bạn muốn hai thao tác trong một. Tại sao không tách chúng ra? Phong cách DSL:

var list = new ImmutableList<string>("Hello");
var list2 = list.Copy().With("World!");

Copysẽ trả về một đối tượng trung gian, đó là bản sao có thể thay đổi của danh sách gốc. Withsẽ trả lại một danh sách bất biến mới.

Cập nhật:

Nhưng, có một bộ sưu tập trung gian, có thể thay đổi xung quanh không phải là một cách tiếp cận tốt. Đối tượng trung gian nên được chứa trong Copyhoạt động:

var list1 = new ImmutableList<string>("Hello");
var list2 = list1.Copy(list => list.Add("World!"));

Bây giờ, Copyhoạt động cần một đại biểu, nhận được một danh sách có thể thay đổi, để nó có thể kiểm soát kết quả sao chép. Nó có thể làm nhiều hơn là nối thêm một phần tử, như loại bỏ các phần tử hoặc sắp xếp danh sách. Nó cũng có thể được sử dụng trong hàm ImmutableListtạo để tập hợp danh sách ban đầu mà không có danh sách bất biến trung gian.

public ImmutableList<T> Copy(Action<IList<T>> mutate) {
  if (mutate == null) return this;
  var list = new List<T>(this);
  mutate(list);
  return new ImmutableList<T>(list);
}

Bây giờ không có khả năng giải thích sai bởi người dùng, họ sẽ tự nhiên rơi vào hố thành công .

Một cập nhật khác:

Nếu bạn vẫn không thích danh sách có thể thay đổi được đề cập, ngay cả khi có trong đó, bạn có thể thiết kế một đối tượng đặc tả, sẽ chỉ định hoặc tập lệnh , cách hoạt động sao chép sẽ chuyển đổi danh sách của nó. Cách sử dụng sẽ giống nhau:

var list1 = new ImmutableList<string>("Hello");
// rules is a specification object, that takes commands to run in the copied collection
var list2 = list1.Copy(rules => rules.Append("World!"));

Bây giờ bạn có thể sáng tạo với các tên quy tắc và bạn chỉ có thể hiển thị các chức năng mà bạn muốn Copyhỗ trợ, không phải toàn bộ khả năng của một IList.

Đối với việc sử dụng chuỗi, bạn có thể tạo một hàm tạo hợp lý (dĩ nhiên sẽ không sử dụng chuỗi):

public ImmutableList(params T[] elements) ...

...

var list = new ImmutableList<string>("Hello", "immutable", "World");

Hoặc sử dụng cùng một đại biểu trong một hàm tạo khác:

var list = new ImmutableList<string>(rules => 
  rules
    .Append("Hello")
    .Append("immutable")
    .Append("World")
);

Điều này giả định rằng rules.Appendphương thức trả về this.

Đây là những gì nó sẽ trông như thế nào với ví dụ mới nhất của bạn:

var suite = new TestSuite<string, int>(x => x.Length);
var otherSuite = suite.Copy(rules => 
  rules
    .Append(x => Int32.Parse(x))
    .Append(x => x.GetHashCode())
);

@Jordao: Bởi vì loại thành phần này dẫn đến một hình thức initalization đơn giản hơn nhiều. Tại sao có hai biến riêng biệt khi tôi chỉ muốn một biến? Tương tự như vậy, tôi không muốn tạo một bản sao có thể thay đổi - tôi muốn mọi thứ đều bất biến trong suốt, vì điều đó dẫn đến mã dễ hiểu hơn về IMO.
Jon Skeet

Tất cả những điều này vẫn còn khá khó sử dụng hơn "Plus", vv Cảm ơn những ý tưởng liên quan đến đột biến, nhưng tôi chắc chắn thích cách tiếp cận "giữ cho nó bất biến".
Jon Skeet

Có lẽ sau đó sẽ luôn có những giải thích sai về ngữ nghĩa thực sự của hoạt động. Nếu bạn theo lộ trình đối tượng đặc tả, sẽ không có đột biến xảy ra (ít nhất là không ở bên ngoài), đối tượng chỉ xác định đối tượng bất biến mới sẽ trông như thế nào. Những gì bạn có là một hoạt động đi từ một đối tượng bất biến sang một đối tượng khác, và vì nó được gọi là Sao chép, không có chỗ cho những hiểu lầm.
Jordão

Các tên duy nhất phù hợp với bạn dường như là tên ghép, như CopyAndAppend, CopyAndAdd, v.v.
Jordão

1
Tôi thực sự đang phát triển hơn về cách tiếp cận này (với tất cả các chỉnh sửa) dưới dạng API cho các bộ sưu tập bất biến. Tuy nhiên, tôi sẽ lập luận rằng việc kết hợp phương pháp này với các phương thức trợ giúp cho các thông số kỹ thuật mặc định, chẳng hạn như Concat, mang lại điều tốt nhất cho cả hai thế giới.
gai

11

Một vài suy nghĩ ngẫu nhiên:

  • Bất biếnAdd ()
  • Nối ()
  • ImmutableList <T> (ImmutableList <T> originalList, T newItem) Trình xây dựng

1
+1 cho bất biếnAdd; không quan tâm đến Append (quá giống StringBuilder.Append đang gây đột biến) và phiên bản constructor là một vấn đề khó khăn trong việc xâu chuỗi.
Jon Skeet

10

DateTime trong C # sử dụng Thêm. Vậy tại sao không sử dụng cùng tên? Miễn là người dùng của lớp bạn hiểu lớp là bất biến.


Tôi cho rằng DateTime.Add đã được biết là gây nhầm lẫn cho mọi người ... nhưng tôi đồng ý rằng nó cho thấy sự ưu tiên.
Jon Skeet

1
Cũng giống như các phương thức để thay đổi một chuỗi gây nhầm lẫn cho các nhà phát triển mới. Nhưng chẳng mấy chốc, mọi người đều biết rằng "chuỗi là bất biến"
Tundey

9

Tôi nghĩ rằng điều quan trọng mà bạn đang cố gắng đạt được là điều khó diễn đạt là sự không biến đổi, vì vậy có thể một cái gì đó có một từ rộng rãi trong đó, một cái gì đó như CopyWith () hoặc InstancePlus ().


9

Tôi không nghĩ rằng ngôn ngữ tiếng Anh sẽ cho phép bạn ám chỉ sự bất biến theo cách không thể nhầm lẫn trong khi sử dụng một động từ có nghĩa tương tự như "Thêm". "Plus" gần như làm điều đó, nhưng mọi người vẫn có thể phạm sai lầm.

Cách duy nhất bạn sẽ ngăn người dùng nhầm đối tượng với một thứ gì đó có thể thay đổi là bằng cách làm cho nó rõ ràng, thông qua tên của chính đối tượng hoặc thông qua tên của phương thức (như với các tùy chọn dài dòng như "GetCopyWith" hoặc "CopyAndAdd").

Vì vậy, chỉ cần đi với yêu thích của bạn, "Plus."


9

Đầu tiên, một điểm khởi đầu thú vị: http://en.wikipedia.org/wiki/Naming_conventions_(programming) ... Đặc biệt, hãy kiểm tra các liên kết "Xem thêm" ở phía dưới.

Tôi ủng hộ Plus hoặc And, hiệu quả như nhau.

Plus và And đều dựa trên toán học về từ nguyên. Như vậy, cả hai hoạt động toán học hàm ý; cả hai đều mang lại một biểu thức đọc một cách tự nhiên như các biểu thức có thể phân giải thành một giá trị, phù hợp với phương thức có giá trị trả về. Andmang ý nghĩa logic bổ sung, nhưng cả hai từ đều áp dụng trực giác vào danh sách. Addbao hàm hành động được thực hiện trên một đối tượng, xung đột với ngữ nghĩa bất biến của phương thức.

Cả hai đều ngắn, đặc biệt quan trọng với tính nguyên thủy của hoạt động. Các hoạt động đơn giản, thường xuyên thực hiện xứng đáng với tên ngắn hơn.

Thể hiện ngữ nghĩa bất biến là điều tôi thích làm qua ngữ cảnh. Đó là, tôi chỉ đơn giản là ngụ ý rằng toàn bộ khối mã này có một cảm giác chức năng; cho rằng mọi thứ là bất biến. Đó có thể chỉ là tôi, tuy nhiên. Tôi thích sự bất biến là quy tắc; nếu nó được thực hiện, nó đã được thực hiện rất nhiều ở cùng một nơi; khả năng biến đổi là ngoại lệ.


8

Làm thế nào về Chain () hoặc Đính kèm ()?


1
Đính kèm chắc chắn âm thanh như là đột biến. Có lẽ WithAttached sẽ khôn ngoan hơn, nhưng rất gần với WithAdded, đã được thảo luận ở trên.
TheBlastOne

Thật buồn cười khi "xâu chuỗi" được nhắc đến bao nhiêu lần khi mô tả những gì đang cố gắng thực hiện với điều này. (5 lần), nhưng không được cung cấp như một đề nghị! Đó là điều đầu tiên xuất hiện visualthesaurus.com(không liên kết) khi tôi tìm kiếm concatenate.
cod3monk3y

7

Tôi thích Plus (và Minus). Chúng dễ hiểu và ánh xạ trực tiếp đến các hoạt động liên quan đến các loại bất biến nổi tiếng (các con số). 2 + 2 không thay đổi giá trị của 2, nó trả về một giá trị mới, không thay đổi.

Một số khả năng khác:

Mối nối ()

Ghép ()

Tăng lên()


6

Làm thế nào về mate , mateWith , hoặc coitus , cho những người tuân theo. Về mặt sinh sản, động vật có vú thường được coi là bất biến.

Đi ném Liên cũng vậy. Mượn từ SQL.


2
+1 cho Liên minh. Tôi, tuy nhiên, mượn nó trực tiếp từ lý thuyết tập hợp. :-)
Christoffer Lette

SQL không nhận được nhiều thuật ngữ từ lý thuyết tập hợp sao?
Jason D

1
Ngoài ra, Union ngụ ý phân biệt .. Nếu bạn muốn bao gồm các bản sao (ít nhất là trong TSQL), bạn phải sử dụng Union All một cách rõ ràng.
cây gai dầu

6

Rõ ràng tôi là người Obj-C / ca cao đầu tiên trả lời câu hỏi này.

NNString *empty = [[NSString alloc] init];
NSString *list1 = [empty stringByAppendingString:@"Hello"];
NSString *list2 = [list1 stringByAppendingString:@"immutable"];
NSString *list3 = [list2 stringByAppendingString:@"word"];

Không chiến thắng bất kỳ trò chơi golf mã nào với điều này.


+1 [object]By[Verb]ing[Object]:tiền tố của phương thức ngụ ý rằng một chuỗi mới sẽ được trả về trái ngược với đơn giản [verb][Object]:, điều này sẽ làm thay đổi đối tượng tại chỗ.
Dave DeLong

3
+1. Tôi không hiểu sự ác cảm của mọi người đối với tính dài dòng (hay còn gọi là tài liệu tự luận).
hatfinch

5

Tôi nghĩ "Thêm" hoặc "Plus" nghe có vẻ tốt. Tên của danh sách phải đủ để truyền đạt sự bất biến của danh sách.


Nó không có danh sách, nó là một bộ thử nghiệm.
tstenner

5

Có thể có một số từ nhớ tôi nhiều hơn về việc tạo một bản sao và thêm nội dung vào đó thay vì làm thay đổi thể hiện (như "Kết hợp"). Nhưng tôi nghĩ rằng có một số đối xứng cho những từ đó cho các hành động khác cũng sẽ tốt để có. Tôi không biết một từ tương tự cho "Loại bỏ" mà tôi nghĩ cùng loại như "Kết nối". "Plus" nghe có vẻ hơi lạ đối với tôi. Tôi không mong đợi nó sẽ được sử dụng trong bối cảnh phi số. Nhưng điều đó cũng có thể đến từ nền tảng không phải tiếng Anh của tôi.

Có lẽ tôi sẽ sử dụng chương trình này

AddToCopy
RemoveFromCopy
InsertIntoCopy

Chúng có những vấn đề riêng của chúng, khi tôi nghĩ về nó. Người ta có thể nghĩ rằng họ loại bỏ một cái gì đó hoặc thêm một cái gì đó vào một đối số được đưa ra. Không chắc chắn về nó cả. Những từ đó cũng không chơi hay trong chuỗi, tôi nghĩ vậy. Quá dài dòng để gõ.

Có lẽ tôi sẽ chỉ sử dụng "Thêm" đơn giản và bạn bè. Tôi thích cách nó được sử dụng trong toán học

Add 1 to 2 and you get 3

Chà, chắc chắn, số 2 vẫn là số 2 và bạn nhận được một số mới. Đây là về hai con số chứ không phải về một danh sách và một yếu tố, nhưng tôi nghĩ nó có một số tương tự. Theo tôi, addkhông nhất thiết có nghĩa là bạn biến đổi một cái gì đó. Tôi chắc chắn thấy quan điểm của bạn rằng có một tuyên bố cô đơn chỉ chứa một addvà không sử dụng đối tượng mới được trả lại sẽ không có lỗi. Nhưng bây giờ tôi cũng đã nghĩ một lúc về ý tưởng sử dụng tên khác ngoài "thêm" nhưng tôi không thể nghĩ ra tên khác, mà không khiến tôi nghĩ "hmm, tôi sẽ cần xem tài liệu để biết cái gì đó là về "bởi vì tên của nó khác với những gì tôi mong đợi được gọi là" thêm ". Chỉ là một vài suy nghĩ kỳ lạ về điều này từ litb, không chắc nó có ý nghĩa gì cả :)


Nhưng một bản sao không phải lúc nào cũng cần thiết trong một bộ sưu tập bất biến. Lấy một cây nhị phân chẳng hạn. Thêm một gốc mới không cần sao chép, chỉ cần một giá trị mới trong đó một trong những chiếc lá là cây cũ
JaredPar

KISS - Nếu việc đặt tên bắt đầu bao gồm chi tiết triển khai, tất cả các tên phương thức sẽ trở nên quá dài. "Thêm" là đủ đơn giản và thực hiện công việc.
mP.

1
@mP: Một lần nữa bạn sử dụng cụm từ "chi tiết triển khai" theo cách mà tôi tin là không phù hợp. Cho dù đó là một danh sách được liên kết hoặc một mảng dưới mui xe là một chi tiết thực hiện . Tôi có thể thay đổi việc thực hiện mà không thay đổi API. Các khía cạnh bất biến không phải là một chi tiết thực hiện.
Jon Skeet

1
đúng. JaredPar, nhưng tôi nghĩ nó cũng không quan trọng dù nó thực sự sao chép cây hay chỉ sử dụng cây hiện có và sử dụng nó như một chiếc lá cho cây mới được trả lại. Ý tôi là, đó chỉ là một chi tiết thực hiện. Nó cũng tương tự đối với (tôi tin) hoạt động chuỗi con cho lớp chuỗi của java.
Julian Schaub - litb


5

Tôi nghĩ rằng Plus()Minus()hoặc, thay vào đó Including(), Excluding()là hợp lý trong việc ngụ ý hành vi bất biến.

Tuy nhiên, không có sự lựa chọn đặt tên nào sẽ làm cho nó hoàn toàn rõ ràng với mọi người, vì vậy cá nhân tôi tin rằng một nhận xét tài liệu xml tốt sẽ đi một chặng đường rất dài ở đây. VS ném những thứ này ngay vào mặt bạn khi bạn viết mã trong IDE - chúng khó có thể bỏ qua.


4

Append- bởi vì, lưu ý rằng tên của các System.Stringphương thức gợi ý rằng chúng biến đổi thể hiện, nhưng chúng không.

Hoặc tôi khá thích AfterAppending:

void test()
{
  Bar bar = new Bar();
  List list = bar.AfterAppending("foo");
}

Giống như đối số DateTime trước đó, tôi đồng ý với các ưu tiên nếu nó không được cho thực tế là rất nhiều lập trình viên làm hy vọng phương pháp chuỗi để làm công cụ. Họ phải được nói (đôi khi lặp đi lặp lại) rằng các chuỗi là bất biến. Tôi muốn lôi kéo các nhà phát triển khách hàng của mình vào hố thành công :)
Jon Skeet

Tôi thích Append ngày càng nhiều. Nó phân biệt rằng bạn không làm thay đổi bộ sưu tập mà tham gia vào nó.

4

list.CopyWith(element)

Smalltalk cũng vậy :)

Và cũng list.copyWithout(element)loại bỏ tất cả các lần xuất hiện của một phần tử, điều này hữu ích nhất khi được sử dụng như list.copyWithout(null)để loại bỏ các phần tử chưa đặt.


3

Tôi sẽ chọn Add, bởi vì tôi có thể thấy lợi ích của một cái tên tốt hơn, nhưng vấn đề sẽ là tìm các tên khác nhau cho mọi hoạt động bất biến khác có thể làm cho lớp khá lạ lẫm nếu điều đó có ý nghĩa.


Vâng, tôi thấy quan điểm của bạn. Tôi nghĩ rằng tôi vẫn thích Plus, nhưng đó là một điểm đáng để xem xét.
Jon Skeet

Cảm ơn Jon. Tôi mong được sử dụng khuôn khổ của bạn. Tôi chỉ đọc về nó và nó có vẻ rất tốt. Cảm ơn một lần nữa.
Joan Venge
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.