2011-12-20 23 views
5

TDPL, tr. 167:Chức năng thuần túy này có thể thay đổi trạng thái không riêng tư như thế nào?

miễn là tình trạng có thể thay đổi trong một chức năng là hoàn toàn tạm (ví dụ, cấp phát trên stack) và tin (ví dụ, không được thông qua cùng bằng cách tham khảo các chức năng mà có thể làm hỏng nó), thì hàm có thể được coi là thuần khiết.

import std.stdio : writeln; 

struct M{ 
    int[4] _data; 

    pure ref int opIndex(size_t i){ return _data[i]; } 
} 

pure M foo(ref M m){ 

    m[0] = 1234; 
    return m; 
} 

void main(){ 

    M m1 = M([7, 7, 7, 7]); 

    writeln(m1); 
    foo(m1); 
    writeln(m1); 
} 

// output: 
// M([7, 7, 7, 7]) 
// M([1234, 7, 7, 7]) 

Nhà nước có thể thay đổi là nhất thời vì nó là trên stack, có đúng không? Nhưng nó không phải là riêng tư. Vì vậy, làm thế nào là foo() được phép sửa đổi m1?

+0

Tôi đã cố gắng xóa thẻ [tag: pure], vì đôi khi nó đề cập đến các hàm ảo thuần túy, đôi khi thành [pure] (http://beebole.com/pure/) và đôi khi thành [pure ] (http://en.wikipedia.org/wiki/Pure_ (programming_language)) - trong số những người khác. Nhưng tôi không biết gì về [tag: d]. Bạn có thể xác nhận xem chỉnh sửa thẻ của tôi có phù hợp không? [Tag: hoàn toàn chức năng] có hoạt động cho câu hỏi này không - tôi đã tạo [tag: pure-function], vì vậy nếu [tag: purely-functional] hoạt động, tôi nghĩ sẽ tốt hơn nếu sử dụng thẻ hiện tại. –

+0

@RichardJPLeGuen Tinh khiết như trong [độ tinh khiết chức năng] (http://en.wikipedia.org/wiki/Pure_function), vì vậy chức năng thuần túy sẽ hoạt động cho câu hỏi này. hoàn toàn chức năng, không quá nhiều. – Arlen

+0

Cảm ơn, @Arlen! –

Trả lời

6

pure đã được mở rộng một chút kể từ khi phát hành TDPL, kể từ pure như TDPL mô tả hóa ra là quá hạn chế để hữu ích ngoài chức năng toán học đơn giản và tương tự. Bạn có thể nhìn vào the online documentation cho định nghĩa hiện nay, nhưng về cơ bản đi xuống đến này:

  1. pure chức năng không thể truy cập bất kỳ mô-đun cấp hoặc các biến tĩnh có thể được biến đổi trong quá trình của chương trình (họ phải Các loại giá trị const hoặc immutable để truy cập từ chức năng pure).

  2. pure chức năng không thể gọi bất kỳ chức năng nào không phải là pure.

  3. pure chức năng không thể thực hiện I/O.

Vậy đó. Không có hạn chế nào khác. Tuy nhiên, có các hạn chế bổ sung cần thiết nếu chức năng pure sẽ được tối ưu hóa sao cho nó chỉ được gọi một lần ngay cả khi được sử dụng nhiều lần trong một tuyên bố. Cụ thể:

  • Tham số của hàm phải là immutable hoặc chuyển đổi hoàn toàn thành immutable.

Về lý thuyết có thể được mở rộng để đòi hỏi rằng của chức năng luận phải immutable hoặc ngầm mui trần để immutable (vì vậy mà một hàm với const thông số có thể được tối ưu hóa khi nó được immutable arguments), nhưng đó không phải là hiện trường hợp.

Các chức năng như vậy pure đôi khi được gọi là "mạnh" pure, trong khi các chức năng không thể được tối ưu hóa sẽ được gọi là "yếu" pure. TDPL mô tả các chức năng mạnh mẽ pure. Các hàm pure yếu được thêm vào để làm cho pure thường sử dụng được hơn.

Trong khi yếu pure chức năng thể thay đổi lập luận của họ, họ không thể thay đổi trạng thái toàn cầu, vì vậy khi chúng được gọi bằng cách mạnh mẽ pure chức năng (mà không có thể thay đổi lập luận của họ), đảm bảo rằng các mạnh pure giá trị trả về của hàm sẽ luôn giống nhau cho cùng một đối số vẫn giữ. Về cơ bản, bởi vì các hàm pure yếu kém không thể biến đổi trạng thái toàn cục, chúng là một phần của trạng thái riêng tư của hàm pure mạnh mẽ mà chúng được gọi. Vì vậy, nó rất phù hợp với những gì Andrei mô tả trong phần 5.11.1.1 purepure trong TDPL, ngoại trừ trạng thái riêng của hàm đã được mở rộng để cho phép các chức năng có thể thay đổi trạng thái riêng của nó mà không thay đổi trạng thái toàn cầu .

Một điều quan trọng khác của lưu ý đã được thêm từ TDPL liên quan đến pure là suy luận thuộc tính hàm. pure, nothrow@safe được suy ra cho các chức năng được tạo khuôn mẫu (mặc dù không phải là cho các chức năng bình thường). Vì vậy, nếu chức năng được tạo mẫu có thểpure, bây giờ là pure. Độ tinh khiết của nó phụ thuộc vào những gì nó được khởi tạo. Vì vậy, nó trở thành có thể sử dụng pure với chức năng templated, trong khi trước đây, bạn thường không thể, bởi vì nếu bạn thực hiện nó pure, nó sẽ không hoạt động với một hàm không tinh khiết. Nhưng nếu bạn không làm cho nó pure, thì bạn không thể sử dụng nó với chức năng pure, do đó, đây là vấn đề chính đối với pure. May mắn thay, sửa lỗi suy luận thuộc tính mà bây giờ mặc dù. Miễn là một chức năng theo khuôn mẫu tuân theo các quy tắc được liệt kê ở trên khi nó được khởi tạo, thì nó được coi là pure.

+0

Tôi nghĩ rằng tôi sẽ phải để cho điều này chìm vào và làm quen với những thứ như 'pure void opIndexAssign (giá trị T, size_t i) {...}' và 'pure T opIndex (size_t i) const {...} ' – Arlen

+0

Chỉ cần nghĩ về' pure' như ý nghĩa rằng hàm không thể truy cập trạng thái toàn cục có thể thay đổi được, và sau đó để trình biên dịch tối ưu hóa nó khi nó có thể. Có, công cụ sửa đổi 'pure' kết thúc trên nhiều hàm hơn các hàm có chức năng' pure', nhưng _is_ vẫn làm cho hàm 'pure' có thể hoạt động và có thể được tối ưu hóa. –

5

Tham chiếu this được coi là một phần của tham số của hàm và do hàm yếu, bạn có thể sửa đổi các tham số. Với trạng thái this được coi là một phần của đầu vào, hàm vẫn đáp ứng điều kiện có cùng đầu ra với cùng một đầu vào.

Hãy xem xét ví dụ này hoàn toàn hợp pháp, trong đó kết quả đầu ra 2:

import std.stdio : writeln; 

struct S 
{ 
    int foo = 0; 
    pure void set(size_t i){ foo = i; } 
} 


void main() 
{ 
    S s; 
    s.set(2); 
    writeln(s.foo); 
} 

Theo như tôi biết, sau khi TDPL được phát hành, định nghĩa về tinh khiết đã được mở rộng. Cuốn sách mô tả các chức năng mạnh mẽ tinh khiết. Sau đó, hai phát triển đã diễn ra: các hàm yếu kém tinh khiết được thêm vào, được phép thay đổi các tham số của chúng. Ngoài ra, suy luận tinh khiết đã được thêm vào cho các chức năng mẫu để bạn có thể sử dụng instantiation của một khuôn mẫu miễn là nó thuần khiết ngay cả khi chức năng mẫu không được trang trí với pure.

Các vấn đề liên quan