2012-05-18 26 views
5

tôi có một danh sách mà tôi tạo ra như sau:Làm thế nào để tạo biến toàn cầu trong prolog

tab([(top,left),(top,middle),(top,right),(center,left),(center,middle), 
    (center,right),(bottom,left),(bottom,middle),(bottom,right)]). 

tôi muốn tạo một AllPosition biến toàn cầu đó là một tab. Vì vậy, tôi đã làm như sau:

tab(AllPos). 

Điều này có đúng không?

Sau đó, tôi phải theo dõi vấn đề: Tôi có một chức năng nhận được một trong các cặp trong tab. Điều đó tôi muốn loại bỏ. Vì vậy, tôi đã làm điều này:

place(Line, Column, Tab) :- 
AllPos \== [_,_] /*while AllPos isn't empty - not sur if this is done this way*/ -> (member((Line,Column), AllPos) -> (erase(AllPos, (Line,Column), AllPos)). 

xóa phần tử Element from List và tạo danh sách mới Danh sách mới bằng Danh sách nhưng không có phần tử. Cả hai chức năng membererase đều hoạt động.

Điều này là ... Như bạn có thể đã nhận thấy tôi sử dụng AllPos ở khắp mọi nơi. Đó là bởi vì tôi muốn, tôi muốn sửa đổi nó để tôi có thể sử dụng nó sau này (sau khi đã gỡ bỏ một số yếu tố từ nó), trong một chức năng khác. Logic của tôi có đúng không? Tôi có thể sử dụng AllPos đã sửa đổi trong một chức năng khác không? Cảm ơn

+0

Cũng vui lòng xem câu hỏi và câu trả lời về cách [** tránh biến toàn cầu **] (http://stackoverflow.com/questions/19005042/how-to-avoid-using-assert-and-retractall-in -prolog-to-implement-global-or-state) trong Prolog. – mat

Trả lời

0

Tóm lại: không, logic của bạn không chính xác. Có nhiều vấn đề nhỏ và lỗi với mã của bạn, nhưng vấn đề lớn hơn là tiền đề cơ bản. Có vẻ như bạn đang nghĩ về vấn đề một cách sai lầm. Nói chung, nếu bạn đang cố gắng cập nhật trạng thái toàn cầu trong chương trình Prolog, bạn cần suy nghĩ lại về thiết kế của mình. Nhà nước thường được thực hiện bởi các đối số cho các vị từ, vì vậy thay vì hợp nhất AllTabs trong phần thân của place/4, tôi đã mong đợi tập hợp hiện tại Tabs được chuyển thành một đối số. Nếu bạn thực sự muốn cập nhật trạng thái toàn cầu của chương trình, thì bạn cần xem xét các biến vị ngữ assertretract.

Một số điểm cụ thể:

tab(AllPos). 

này tuyên bố một vị với một biến không ràng buộc vào đầu. Đó là nhiều hay ít vô nghĩa (bạn có thể đọc là "nó là trường hợp mà tab là đúng của một cái gì đó, nhưng chúng tôi không có thông tin về những gì nó là đúng của").

AllPos \== [_,_] 

sử dụng này AllPos là trong một phạm vi khác nhau để tab/1, vì vậy ngoài việc chia sẻ cùng một chuỗi ký tự trong tên biến, hai công dụng của AllPos không có quan hệ gì cả.

1

thêm vào câu trả lời của Ian:

thường sử dụng khẳng định/rút lại chậm.việc triển khai nhiều prolog có cách hiệu quả hơn cho các biến toàn cục có thể thay đổi (ví dụ của séc SWI-Prolog lib)

bây giờ, nếu bạn muốn một bất biến biến toàn cầu có thể được mã hóa gần giống như bạn đã làm; bạn sẽ "tuyên bố" nó như myvar(42). nhưng để sử dụng nó, bạn sẽ phải làm điều này:

foo:- 
    myvar(Var), 
    do_something(Var). 

một lần nữa, sử dụng các biến toàn cầu có thể thay đổi là không thực sự gợi ý và có thể dẫn đến rất, rất xấu và khó khăn để phát hiện lỗi do backtracking.

+0

[Liên kết trong câu trả lời này] (http://www.swi-prolog.org/pldoc/doc_for?object=section%282,%276.3%27,swi%28%27/doc/Manual/gvar.html% 27% 29% 29) dường như bị hỏng. –

+0

@AndersonGreen cổ vũ, cố định! –

4

Trong SWI-Prolog, bạn có thể sử dụng: b_setval(name, value)b_getval(name, value). Và trong trường hợp bạn không muốn các giá trị thay đổi trở lại trong trường hợp backtracking, bạn có thể làm cho chúng trở thành toàn cầu thực tế bằng cách sử dụng: nb_setval(name, value)nb_getval(name, value).

Như vậy ví dụ nếu bạn có một chương trình và bạn muốn kiểm tra mức độ thường xuyên nó đã đi qua một con đường nhất định, bạn có thể sử dụng:

recursive(100). 
recursive(X) :- add, Y is X + 1, recursive(Y). 

add :- nb_getval(counter, C), CNew is C + 1, nb_setval(counter, CNew). 

testRecursion 
:- 
    % Set counter to zero 
    nb_setval(counter, 0), 

    % Run some code with 'add' 
    recursive(0), !, 

    % Print the results 
    nb_getval(counter, CounterValue), 
    write('Steps: '), writeln(CounterValue). 

này là tốt đối với một số trường hợp thử nghiệm, nhưng nói chung bạn sẽ muốn tránh các biến toàn cầu trong Prolog vì Prolog có nghĩa là lập trình trong logic.