2011-05-16 18 views
5

Tôi cần phải làm bài tập về nhà này bằng cách sử dụng prolog (SWI-hương vị) và không thể có được đầu của tôi xung quanh một số điều.Prolog, danh sách xây dựng với mệnh đề có điều kiện

Ví dụ: nếu tôi muốn lặp qua danh sách và thêm các phần tử của nó vào danh sách khác, nhưng CHỈ nếu chúng đáp ứng một số điều kiện nhất định, tôi sẽ làm như thế nào? Tôi có thể thêm tất cả, hoặc không, nhưng nếu tôi thêm mệnh đề kiểm tra tình trạng này, toàn bộ đệ quy hóa ra là "sai". Tôi hiểu tại sao điều này là, nhưng không có ý tưởng làm thế nào để sửa chữa nó. Về cơ bản những gì tôi muốn là:

goal(Stuff) :- do_something(X), 
       only_do_this_if_something(Y), 
       always_do_this(Z). 

Hiện nay, nếu only_do_this_if_something(Y) thất bại, cũng always_do_this(Z) doesnt xảy ra như toàn bộ mục tiêu biến sai ...

+2

+1 vì trung thực về việc cần trợ giúp cho bài tập về nhà. – csl

+0

có thể trùng lặp của [vòng lặp Prolog và báo cáo điều kiện?] (Http://stackoverflow.com/questions/3964420/prolog-loops-and-conditional-statements) –

+1

@GuyC: Không có gì đặc trưng cho SWI ở đây! – false

Trả lời

8

bạn có thể sử dụng nếu cấu trúc:

<condition> -> (do_something) ; (do_something else) 

trong trường hợp này:

goal(Stuff):- 
    do_something(X), 
    if_something(Y)-> do_this(Y) ; true, 
    always_do_this(Z). 

hoặc bạn chỉ đơn giản là viết hai mệnh đề như:

goal(Stuff):- 
    do_something(X), 
    conditional_stuff(Y), 
    always_do_this(Z). 

conditional_stuff(Y):- 
    condition(Y), 
    do_this(Y). 

conditional_stuff(_). 
+0

Cảm ơn, phần đầu tiên của thông báo này đã giải quyết được vấn đề khá độc đáo. – n00bist

0

thử bỏ qua/1 vị:

goal(Stuff) :- 
    do_something(X) 
    ignore(only_do_this_if_something(Y)), 
    always_do_this(Z). 

bỏ qua/1 gọi đối số duy nhất và thành công bất cứ khi nào nó không thành công hay không:

ignore(X) :- X, !. 
ignore(_). 
1

Kiểm tra mô hình lập trình sau đây, được sử dụng khá nhiều trong Prolog:

  • Duyệt qua danh sách, một yếu tố tại một thời điểm
  • Đặt một trường hợp cơ sở cho các đệ quy
  • Trong một khoản, kiểm tra xem các điều kiện áp dụng và làm điều gì đó, sau đó tiếp tục với đệ quy
  • Trong mệnh đề tiếp theo bỏ qua và tiếp tục với đệ quy

Bạn phải sử dụng lệnh cắt (!) để cấm quay lại hoặc kiểm tra rõ ràng rằng điều kiện không áp dụng trong điều khoản sau.

Lưu ý rằng bạn nói rằng bạn muốn có một danh sách đầu ra với các mục mà 'cái gì' áp dụng (mà không phải là những gì bạn đã viết trong mã của bạn) ...

Áp dụng mô hình này để vấn đề của bạn nó sẽ giống như thế này:

myRecursion([], []). % This is the base case 
myRecursion([Item|Tail], [Item|NTail]):- 
    something_applies(...), 
    do_something(...), 
    only_do_this_if_something(...), 
    always_do_this(...). 
    myRecursion(Tail, NTail). 
myRecursion([Item|Tail], NTail):- 
    not(something_applies(...)), 
    do_something(...), 
    always_do_this(...), 
    myRecursion(Tail, NTail). 
+0

-1. Điều này phức tạp và dễ bị lỗi do sự lặp lại và hoàn toàn không cần thiết vì Prolog có cấu trúc if-then-else. –

+1

Tôi hoàn toàn không đồng ý với bạn;) Tôi tin rằng rõ ràng hơn là có các điều khoản riêng biệt cho các hành động riêng biệt. Phần đầu của phần thân của mỗi mệnh đề phân biệt giữa các trường hợp và sau đó bạn chỉ cần làm bất cứ điều gì bạn muốn làm trong phần còn lại của mệnh đề. Cố gắng hiểu một đoạn mã với một vài cấu trúc if-then-else và tôi tin rằng bạn có thể đồng ý với tôi. Nó là ok, tuy nhiên, để sử dụng một số if-then-elses ở đây và ở đó nếu chúng không ảnh hưởng đến khả năng đọc. – gusbro

+0

Tôi thường xuyên sử dụng cấu trúc if-then-else và tìm thấy nó góp phần rất lớn vào tốc độ * và * rõ ràng của mã của tôi. Ý nghĩa logic của nó là rõ ràng hơn so với ý nghĩa của cắt, trong khi nó duy trì nguyên tắc DRY so với phong cách của bạn. –

1

Nếu tôi hiểu đúng, thì những gì bạn cần là một vị như include/3:

include(:Goal, +List1, ?List2) 
    Filter elements for which Goal succeeds. True if List2 contains 
    those elements Xi of List1 for which call(Goal, Xi) succeeds. 

Cách sử dụng examp le:

?- include(number, [a(b), 2, _, 1.2, C, '1'], L). 
L = [2, 1.2]. 

Bây giờ bài tập về nhà của bạn trở thành "cách triển khai include/3". Khi bạn đã triển khai phiên bản include/3, bạn có thể kiểm tra xem phiên bản có khớp với phiên bản SWI hay không bằng cách xem mã nguồn của nó: listing(include).

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