Thuật ngữ cho một chức năng mà khi được gọi lặp đi lặp lại, có tác dụng tương tự như gọi một lần?


96

(Giả sử môi trường đơn luồng)

Một chức năng đáp ứng tiêu chí này là:

bool MyClass::is_initialized = false;

void MyClass::lazy_initialize()
{
    if (!is_initialized)
    {
        initialize(); //Should not be called multiple times
        is_initialized = true;
    }
}

Về bản chất, tôi có thể gọi hàm này nhiều lần và không lo nó khởi tạo MyClassnhiều lần

Một chức năng không đáp ứng tiêu chí này có thể là:

Foo* MyClass::ptr = NULL;

void initialize()
{
    ptr = new Foo();
}

Gọi initialize()nhiều lần sẽ gây rò rỉ bộ nhớ

Động lực

Thật tuyệt khi có một từ ngắn gọn duy nhất để mô tả hành vi này để các chức năng được mong đợi đáp ứng tiêu chí này có thể được nhận xét hợp lệ (đặc biệt hữu ích khi mô tả các chức năng giao diện dự kiến ​​sẽ bị ghi đè)


67
Đối với cử tri thân thiết: trong khi sự thật là 99,999% (ước tính sơ bộ) của tất cả các câu hỏi "tên đó" là lạc đề vì họ không có câu trả lời duy nhất, chính xác, không mơ hồ và khách quan Đặt tên hoàn toàn chủ quan và dựa trên ý kiến, câu hỏi này có một câu trả lời duy nhất, chính xác, không mơ hồ, khách quan, được đưa ra bởi chính OP.
Jörg W Mittag

30
Gọi nó nhiều lần sẽ có hiệu lực, vì có thể có mã khác đã thay đổi 'var' ở giữa.
RemcoGerlich

7
Tại sao câu hỏi này được hỏi, nếu OP biết câu trả lời tại thời điểm hỏi ? Có bất kỳ lý do nào khác ngoài việc xây dựng rep / points / karma không?
dotancohen

13
@dotancohen Q / A tự trả lời kiểu là một trong những khái niệm chính trên StackExchange.
glglgl

17
@glglgl: Tôi đồng ý, cho câu hỏi với công đức. Công đức nào có câu hỏi này? Tôi thực sự lo ngại rằng chúng tôi sẽ bắt đầu nhận mọi câu hỏi về CS 101 và được OP trả lời ngay lập tức, mọi thuật ngữ CS được hỏi và được xác định ngay lập tức bởi OP, và mọi ưu và nhược điểm của thuật toán cơ bản được trả lời ngay lập tức bởi OP ( không nhất thiết phải OP này). Đó có phải là trang web mà chúng tôi muốn phần mềm tạo ra không?
dotancohen

Câu trả lời:


244

Loại chức năng / hoạt động này được gọi là Idempotent

Idempotence (UK: / dɛmˈpoʊtəns /, [1] US: / aɪdəm - /) [2] là tài sản của các hoạt động nhất định trong toán học và khoa học máy tính, theo đó chúng có thể được áp dụng nhiều lần mà không thay đổi kết quả ngoài ứng dụng ban đầu.

Trong toán học, điều này có nghĩa là nếu f là idempotent, f ( f (x)) = f (x), điều này giống như nói ff = f .

Trong khoa học máy tính, điều này có nghĩa là nếu bình f(x);thường, f(x);cũng giống như f(x); f(x);.

Lưu ý: Những ý nghĩa này có vẻ khác nhau, nhưng theo ngữ nghĩa của trạng thái biểu thị , từ "idempotent" thực sự có cùng một ý nghĩa chính xác trong cả toán học và khoa học máy tính.


Bình luận không dành cho thảo luận mở rộng; cuộc trò chuyện này đã được chuyển sang trò chuyện .
maple_shaft

51

Thuật ngữ chính xác cho điều này (như Woustas đề cập ) là idempotence. Tôi muốn thêm rằng trong khi bạn có thể gọi func1phương thức của mình là idempotent, bạn không thể gọi nó là một hàm thuần túy . Các thuộc tính của hàm thuần túy là hai: nó phải là idempotent và nó không được có tác dụng phụ, nghĩa là không có đột biến của các biến tĩnh cục bộ, biến không cục bộ, đối số tham chiếu có thể thay đổi hoặc luồng I / O.

Lý do tôi đề cập đến điều này là một hàm idempotent có tác dụng phụ cũng không tốt, vì idempotent về mặt kỹ thuật đề cập đến đầu ra trả về của hàm và không phải là tác dụng phụ. Vì vậy, về mặt kỹ thuật func2phương pháp của bạn là không cần thiết, vì đầu ra không thay đổi theo đầu vào.

Bạn rất có thể muốn xác định rằng bạn muốn một hàm thuần túy. Một ví dụ về hàm thuần túy có thể như sau:

int func1(int var)
{
    return var + 1;
}

Đọc thêm có thể được tìm thấy trong bài viết Wikipedia "Hàm thuần túy" .


37
Tôi nghĩ định nghĩa về tính không ổn định của bạn là quá hẹp, hay nói cách khác, bạn đang sử dụng định nghĩa toán học về tính không thay đổi, không phải là lập trình. Ví dụ, các phương thức PUTDELETEHTTP được gọi là idempotent chính xác thực thi các hiệu ứng phụ của chúng nhiều lần có tác dụng tương tự như chỉ thực hiện chúng một lần. Bạn đang nói "idempotency có nghĩa là f∘f = f", trong khi trong lập trình, chúng tôi có nghĩa là "thực thi fcó tác dụng tương tự như thực thi f; f". Lưu ý rằng bạn có thể dễ dàng chuyển đổi nghĩa thứ hai thành nghĩa cũ bằng cách thêm tham số "thế giới".
Jörg W Mittag

23
@Neil "Idempotency là một thuật ngữ toán học." Không, nó cũng không được sử dụng trong các hệ thống phân phối / giao tiếp máy chủ và máy khách và cũng được mô tả như JörgWMittag mô tả nó. Đây là một khái niệm hữu ích vì nó cho phép nhiều yêu cầu đến một máy chủ / máy khách có cùng thao tác / tin nhắn mà không thay đổi những gì mà thông điệp ban đầu đặt ra. Điều này hữu ích khi bạn có liên lạc không đáng tin cậy và bạn cần thử lại một lệnh vì thông báo máy khách bị hủy hoặc máy chủ trả lời.
opa

7
Bạn nên đi vào chi tiết hơn về sự khác biệt giữa thuần khiết và bình dị. Ví dụ của bạn func1 không phải là idempotent bởi vì func1(1) != func1(func1(1)).
Tezra

5
Sự tinh khiết và bình dị là khác nhau. Một hàm thuần túy không nhất thiết phải là idempotent theo nghĩa toán học (nó rõ ràng là idempotent về mặt tác dụng phụ, vì nó không có). Hàm Idempotent (theo nghĩa lập trình) không nhất thiết phải thuần túy, như trong ví dụ được đưa ra bởi OP. Ngoài ra, như opa đã đề cập, idempotence là một tài sản hữu ích với cách sử dụng hoàn toàn khác với độ tinh khiết. Định nghĩa của bạn về độ tinh khiết là "bình thường và không có tác dụng phụ" là sai hoặc ít nhất là gây hiểu lầm, hạ thấp.
Frax

5
Trong ngữ cảnh lập trình, không có "tác dụng phụ", nhưng nếu bạn mở rộng định nghĩa để bao gồm điều này, thì một hàm idempotent và một hàm thuần sẽ có nghĩa tương tự. Không, chúng không có nghĩa là điều tương tự cả. Vô tư, không thuần khiết : void f(int var) { someGlobalVariable = var; }. Tinh khiết, không bình dị : int func1(int var) { return var + 1; }.
JLRishe

6

Thuật ngữ này là Idempotence . Lưu ý bên dưới rằng có một sự khác biệt rõ rệt giữa một hàm Idempotent (Được gọi là đệ quy trên chính nó; Khối mã thứ hai và định nghĩa toán học) và tính không thay đổi chức năng (Được gọi liên tục với cùng một đầu vào liên tục; Khối mã đầu tiên và thường là thuật ngữ có nghĩa trong Lập trình).

Hàm f có tác dụng phụ được cho là không có tác dụng theo thành phần tuần tự f; f nếu, khi được gọi hai lần với cùng một danh sách các đối số, cuộc gọi thứ hai không có tác dụng phụ và trả về cùng giá trị như cuộc gọi đầu tiên [cần dẫn nguồn] (giả sử không có thủ tục nào khác được gọi giữa kết thúc cuộc gọi đầu tiên và bắt đầu của cuộc gọi thứ hai).

Ví dụ, hãy xem xét mã Python sau:

x = 0

def setx(n):
    global x
    x = n

setx(5)
setx(5)

Ở đây, setx là idempotent vì lệnh gọi thứ hai đến setx (có cùng đối số) không thay đổi trạng thái chương trình hiển thị: x đã được đặt thành 5 trong cuộc gọi đầu tiên và lại được đặt thành 5 trong cuộc gọi thứ hai, do đó giữ nguyên cùng giá trị. Lưu ý rằng điều này khác với tính không thay đổi trong thành phần chức năng f ∘ f. Ví dụ: giá trị tuyệt đối là idempotent theo thành phần hàm:

def abs(n):
    if n < 0:
        return -n
    else:
        return n

abs(-5) == abs(abs(-5)) == abs(5) == 5

3

Trong vật lý tôi đã nghe điều này được gọi là một phép chiếu :

một chiếu là một sự biến đổi tuyến tính P từ một không gian vector cho chính nó mà P 2 = P . Nghĩa là, bất cứ khi nào P được áp dụng hai lần cho bất kỳ giá trị nào, nó sẽ cho kết quả tương tự như khi nó được áp dụng một lần (idempotent).

Về mặt đồ họa, điều này có ý nghĩa nếu bạn nhìn vào một phim hoạt hình chiếu vector :

nhập mô tả hình ảnh ở đây

Trong bức ảnh, một 1 là dự báo của một vào b , mà là giống như ứng dụng đầu tiên của chức năng của bạn. Dự báo tiếp theo của một 1 vào b cho cùng một kết quả một 1 . Nói cách khác, khi bạn gọi một phép chiếu lặp đi lặp lại, nó có tác dụng tương tự như gọi nó một lần.

Cảnh báo công bằng: Tôi chưa bao giờ nghe thấy điều này được sử dụng ngoài vật lý, vì vậy trừ khi bạn có những loại đó trong nhóm của mình, bạn có thể khiến mọi người nhầm lẫn.


2
Đây thực sự là một ví dụ cụ thể tuyệt vời về cách có thể hiển thị một hàm idempotent (về mặt toán học và đặc biệt là trong trường hình học vectơ / đại số tuyến tính). Mặc dù "idempotence" của chức năng phần mềm là một khái niệm thực sự gần gũi, tôi không nghĩ các nhà phát triển / nhà khoa học máy tính thường sử dụng từ "phép chiếu" trong ngữ cảnh này (một "hàm chiếu" trong công nghệ phần mềm thay vì nói đến một hàm lấy một đối tượng và trả về một đối tượng mới có nguồn gốc từ nó, hoặc một thuộc tính của đối tượng đó, chẳng hạn)
Pac0

2
@ Pac0 ơi, được rồi. Tôi làm việc ở rìa giữa khoa học và lập trình, và không nhận ra từ này đã quá tải. Tôi có thể nghĩ ra một vài ví dụ giả định tại nơi làm việc mà tôi sẽ sử dụng thuật ngữ này, nhưng tôi thừa nhận làm việc với những người sẵn sàng đưa ra thuật ngữ khoa học hàng ngày :-)
user1717828

3

Nó là một thuật toán xác định vì được cung cấp cùng một đầu vào (trong trường hợp này không có đầu vào), nó sẽ luôn tạo ra cùng một đầu ra.

Trong khoa học máy tính, thuật toán xác định là một thuật toán, với một đầu vào cụ thể, sẽ luôn tạo ra cùng một đầu ra, với máy bên dưới luôn đi qua cùng một chuỗi trạng thái. Các thuật toán xác định cho đến nay là loại thuật toán được nghiên cứu và quen thuộc nhất, cũng như một trong những thuật toán thực tế nhất, vì chúng có thể được chạy trên các máy thực sự một cách hiệu quả.

Cơ sở dữ liệu SQL quan tâm đến các hàm xác định .

Hàm xác định luôn đưa ra cùng một câu trả lời khi nó có cùng đầu vào. Hầu hết các hàm SQL tích hợp trong SQLite đều mang tính xác định. Ví dụ, hàm abs (X) luôn trả về cùng một câu trả lời miễn là đầu vào X của nó giống nhau.

Một hàm phải có tính xác định nếu nó được sử dụng để tính toán một chỉ mục.

Ví dụ, trong SQLite, các chức năng không xác định sau đây có thể không được sử dụng trong một chỉ số: random(), changes(), last_insert_rowid()sqlite3_version().


6
Người hỏi func2có tính quyết định (không có hiệu ứng ngẫu nhiên liên quan), nhưng đã bị tuyên bố là vi phạm tài sản mà anh ta đang tìm kiếm.
Draco18

Rằng cùng một kết quả được tạo ra bởi sự lặp lại không giống như nói rằng kết quả tương tự được tạo ra bằng cách làm tổ hoặc xâu chuỗi. Các hàm xác định rất quan trọng đối với các kết quả lưu trữ, nhiều hơn là lập chỉ mục / băm.
mckenzm

3

Bên cạnh những câu trả lời khác, nếu có một đầu vào cụ thể đối với functon có thuộc tính này, đó là một điểm cố định , điểm bất biến hoặc fixpoint của hàm. Ví dụ: 1 cho bất kỳ công suất nào bằng 1, vì vậy (1ⁿ) ⁿ = 1ⁿ = 1.

Trường hợp đặc biệt của một chương trình tự tạo đầu ra là một quine .


Các câu hỏi dành cho phần mềm như các bộ Cantor là toán học :-). Và tất nhiên, các quines không phải là idempotent - chúng sẽ thất bại khi đầu ra đã tồn tại hoặc chúng "ghi đè" kết quả trước đó và viết một đầu ra mới, mặc dù giống hệt nhau.
Carl Witthoft
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.