2016-04-24 14 views
7

Tôi chuyển sang Prolog nó sau khi học logic mệnh đề và vị ngữ.Cách đọc các vị từ trong prolog

Tôi đã tự hỏi nếu ai đó có thể làm rõ cú pháp cho tôi khi tôi gặp sự cố khi đọc nó.

Tôi có thể đọc một cái gì đó như bên dưới một cách dễ dàng. Vì vậy, nó đang nói

X là đi xuống của Y nếu X là con của Y.

Sau đó, nó tiếp tục nói

X là đi xuống của Y nếu X là con của Z và Z là đi xuống của Y.

descend(X,Y) :- 
    child(X,Y). 
descend(X,Y) :- 
    child(X,Z), 
    descend(Z,Y). 

Nhưng một khi tôi đã vào tìm kiếm vào lập trình danh sách Tôi đang đấu tranh để đọc cú pháp của các biến vị ngữ. Ví dụ dưới đây

remove([], _, []). 
remove([X | Xs], X, Ys) :- remove(Xs, X, Ys). 
remove([Y | Xs], X, [Y | Ys]) :- X \== Y, remove(Xs, X, Ys). 

Từ thử nghiệm nó, nó loại bỏ mục thứ hai, vì vậy ví dụ nếu tôi gõ vào

remove([a,b,c], b, Ys). 

tôi sẽ nhận được Ys = [a,c].

Nhưng tôi không biết làm thế nào để đọc cú pháp, nếu ai đó có thể phá vỡ nó cho tôi, điều đó thật tuyệt.

Trả lời

2

Thực tế là bạn cần phải thử nghiệm nó chỉ để xem những gì nó nói rằng remove/3 có lẽ không phải là cũng được đặt tên. remove là khá chung chung và lá mở câu hỏi "loại bỏ những gì?". Ngoài ra, nó là bắt buộc và Prolog muốn là quan hệ. Có lẽ một tên tốt hơn sẽ là list_without/3 mà nói rằng danh sách trong đối số thứ 3 là danh sách trong đối số đầu tiên, nhưng không có đối số thứ hai.

Hãy làm như vậy, hãy đọc những gì bạn có.

Đọc remove/3 ngữ của bạn có thể được thực hiện như sau:

remove([], _, []). 

Danh sách sản phẩm nào vẫn là danh sách trống nếu tôi loại bỏ bất kỳ phần tử.

remove([X | Xs], X, Ys) :- remove(Xs, X, Ys). 

Danh sách Ys là danh sách [X|Xs] với X yếu tố loại bỏ nếuYs là danh sách tôi nhận được sau khi loại bỏ tất cả các yếu tố từ XXs.

remove([Y | Xs], X, [Y | Ys]) :- X \== Y, remove(Xs, X, Ys). 

[Y|Ys] là danh sách [Y|Xs] với X yếu tố loại bỏ nếuX là không giống như YYs là danh sách tôi nhận được sau khi loại bỏ tất cả các yếu tố từ XXs.

Làm bài tập, bạn nên thử đọc lại, nhưng sử dụng tên quan hệ hơn, chẳng hạn như đổi tên mẫu mà tôi đã cung cấp.

+0

hoàn hảo cảm ơn bạn, cú pháp đã được thực sự khó hiểu cho tôi và có vẻ là rất khác nhau từ cách tôi thường đọc vị ngữ. – user6248190

+0

@ user6248190 Tôi bắt đầu bằng cách suy nghĩ về một mệnh đề vị ngữ như đã nói, * Như vậy là đúng ** nếu ** .... * theo sau là một chuỗi các điều kiện. – lurker

+0

xin lỗi một điều nữa, là có một cách ngắn hơn để làm những gì loại bỏ vị ngữ đang làm gì? Tại sao có 3 dòng loại bỏ? – user6248190

4

Vì bạn có một số nền tảng trong logic, bạn có thể thấy hữu ích khi đọc các quy tắc dưới dạng công thức logic. Hãy thay thế (\ ==)/2 bởi dif/2 sau đó loại bỏ/3 đọc như sau:

remove([], _, [])true

remove([X | Xs], X, Ys)remove(Xs, X, Ys)

remove([Y | Xs], X, [Y | Ys])dif(X,Y)remove(Xs, X, Ys)

Lưu ý cách mũi tên hàm ý trỏ đến phần đầu của quy tắc. Điều đó có nghĩa là cơ thể của quy tắc là tiền lệ và người đứng đầu của quy tắc là hậu quả. Vì vậy, bạn đọc một quy tắc là: nếu phần thân của quy tắc là đúng thì đầu của quy tắc là đúng. Các mục tiêu trong các quy tắc được kết nối bằng cách kết hợp. Lưu ý rằng thực tế có true là tiền đề, nghĩa là remove([], _, []) luôn đúng. Mặt khác, nếu phần thân của quy tắc là sai thì quy tắc không thành công nhưng vị từ vẫn có thể thành công nếu phần thân của quy tắc khác là đúng. Nếu cơ thể của tất cả các quy tắc khác là sai thì vị từ không thành công. Vì vậy, có một số quy tắc cho một vị ngữ cấu thành logic hoặc: vị từ remove/3 thành công nếu rule1 HOẶC rule2 HOẶC rule3 thành công.

Khi bạn yêu cầu cú pháp cụ thể, nó cũng là cơ hội để làm quen với ký hiệu đầu và đuôi cho danh sách. Nghĩa là, bạn có thể viết phần tử đầu tiên (s) của một danh sách rõ ràng thì một danh sách constructor | và phần còn lại của danh sách:

[1|Xs] ... danh sách bắt đầu với 1 và sau đó có một phần còn lại

[1,2|Xs] ... danh sách bắt đầu với 12 theo sau là một phần còn lại

[X|Xs] ... danh sách đã ít nhất một yếu tố tiếp theo là một phần còn lại

Lưu ý cách các yếu tố danh sách được phân cách bằng 012.trong khi phần còn lại của danh sách được phân tách bằng |. Thuật ngữ sau | thực sự là một danh sách và cũng có thể là một danh sách trống.Dưới đây là một số ví dụ cho các danh sách bình đẳng:

[1] cũng giống như [1|[]]

[1,2] = [1|[2]] = [1|[2|[]]] = [1,2|[]]

Đối với danh sách sau đây đã có 8 cách để viết nó:

[1,2,3] = [1,2|[3]] = [1|[2,3]] = [1|[2|[3|[]]]] = ...

Với những quan sát trên, bạn sẽ kiểm tra từng quy tắc một. Như @ lurker đã làm điều đó trong câu trả lời của mình, tôi sẽ không đi vào chi tiết. Tuy nhiên, tôi muốn nói thêm rằng nếu một quy tắc có một số mục tiêu, giống như quy tắc thứ 3 trong ví dụ của bạn, tôi thấy hữu ích khi đi bộ qua các mục tiêu cùng một lúc:

remove([Y | Xs], X, [Y | Ys]) :- 

tử Y của danh sách ban đầu cũng trong danh sách mà không X NẾU ...

remove([Y | Xs], X, [Y | Ys]) :- 
    dif(X,Y), 

... X là khác nhau từ Y VÀ ...

remove([Y | Xs], X, [Y | Ys]) :- 
    dif(X,Y), 
    remove(Xs, X, Ys). 

... mối quan hệ giữ cho Xs, XYs.

Vậy tại sao lại thay thế? Vị từ được xây dựng sẵn (\ ==)/2 chỉ thành công hoặc thất bại mà không có sự hợp nhất hoặc tác dụng phụ. Nó là tốt cho thử nghiệm bất bình đẳng hạn tại một thời gian nhất định nhưng không có bất kỳ tác dụng sau này. Hãy xem xét các truy vấn sau đây:

?- X=Y, X\==Y. 
no 

Đầu tiên các biến XY được thống nhất và sau đó kiểm tra cho bất bình đẳng thất bại. Nhưng:

?- X\==Y, X=Y. 
X = Y 

Đầu tiên kiểm tra sự bất bình đẳng thành công, nếu không Prolog thậm chí sẽ không xem xét mục tiêu thứ hai. Sau đó, XY được hợp nhất thành công. Đây là ý của tôi là không có hiệu lực sau này trên. Vì vậy, tất cả mọi thứ tôi đã viết ở trên về việc đọc các vị từ không thực sự có ý nghĩa với (\ ==)/2.

Là một phiên bản ngắn hơn tôi ném sau trong chiếc mũ, sử dụng if_/3=/3:

list_without_element([],[],_E). 
list_without_element([X|Xs],L,E) :- 
    if_(X=E,L=Ys,L=[X|Ys]), 
    list_without_element(Xs,Ys,E). 
+2

Hoặc, nói rõ hơn bằng cách sử dụng 'tfilter/3' cùng với' dif/3': 'list_without_element (Es, Xs, E): - tfilter (dif (E), Es, Xs) .' – repeat

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