Thanks to visit codestin.com
Credit goes to github.com

Skip to content

bakaq/qupak

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Qupak: Pattern Matching for library(reif)

This library provides predicates to do pattern matching in a way that complements and expands on library(reif).

Tested on Scryer Prolog 0.10.

Pattern matching

The core predicate of this library is pattern_match_t/3. It has a non-reified version pattern_match/2, along with some operator aliases (=~)/3 (the pattern is always in the side of the ~).

The pattern consists of a term that is a clean representation of what you want to match. You always need to specify how a term will be matched with a wrapping functor. All of the wrapping functors have operators provided for ergonomics.

(+)/1: Ground

Matches a ground term. Doesn't need to be atomic.

?- a(1,2,3) =~ +a(1,2,3).
   true.
?- =~(a(1,2,3), +a(1,2,3), T).
   T = true.

(-)/1: Bind variable

Binds a variable. This does normal unification, not reified unification like (?)/1.

?- a(1,2,3) =~ -X.
   X = a(1,2,3).
?- =~(a(1,2,3), -X, T).
   X = a(1,2,3), T = true.

(?)/1: Reified unification

Does reified unification. If used in a non-reified predicate, it's basically the same thing as (-)/1, but creates a spurious choice point. When used in a reified predicate, does the unification like (=)/3, exploring the dif/2 case on backtracking.

?- a(1,2,3) =~ ?X.
   X = a(1,2,3)
;  false.
?- =~(a(1,2,3), ?X, T).
   X = a(1,2,3), T = true
;  T = false, dif:dif(X,a(1,2,3)).

(*)/1: Wildcard

Matches anything, and ignores it.

?- a(1,2,3) =~ (*).
   true.
?- =~(a(1,2,3), *, T).
   T = true.

(\)/1: Compound term

Matches a compound term, applying patterns recursively. If the compound term is ground, you can use (+)/1 instead.

?- a(1,2,3,4) =~ \a(+1, -A, ?B, *).
   A = 2, B = 3
;  false.
?- =~(a(1,2,3,4), \a(+1, -A, ?B, *), T).
   A = 2, B = 3, T = true
;  A = 2, T = false, dif:dif(B,3).

(<<)/2: All binding

Binds the whole pattern to a variable. It can be used at any nesting level, not just at the top level.

?- a(1,2,3,4) =~ All << \a(+1, -A, ?B, *).
   All = a(1,2,3,4), A = 2, B = 3
;  false.
?- =~(a(1,2,3,4), All << \a(+1, -A, ?B, *), T).
   All = a(1,2,3,4), A = 2, B = 3, T = true
;  All = a(1,2,3,4), A = 2, T = false, dif:dif(B,3).

('|')/2: Guards

Runs a reified predicate after the bindings to decide if the pattern matches.

?- use_module(library(clpz)).
   true.
?- a(50) =~ (\a(-N) | clpz_t(N #< 25)).
   false.
?- a(10) =~ (\a(-N) | clpz_t(N #< 25)).
   N = 10.
?- =~(a(50), (\a(-N) | clpz_t(N #< 25)), T).
   N = 50, T = false.
?- =~(a(10), (\a(-N) | clpz_t(N #< 25)), T).
   N = 10, T = true.

match/2: Reified pattern matching switch

The match/2 predicate implements something like a switch/match statement on top of if_/3 and the pattern matching predicates from this library. The arms are matched in order, and the first one to succeed is the one taken.

When a (?)/1 pattern backtracks and tries the dif/2 case, it will test the next arms in the match/2. The dif/2 constraint will be available for all the arms from there on.

?- [user].
example_match(Term, Out) :-
    match(Term, [
        +a ~> Out = 1,
        \b(-N) ~> Out = N,
        \c(?N) ~> Out = N,
        (*) ~> Out = wildcard
    ]).


?- example_match(a, Out).
   Out = 1.
?- example_match(b(10), Out).
   Out = 10.
?- example_match(c(10), Out).
   Out = 10
;  Out = wildcard, dif:dif(_A,10).

About

Pattern matching for Prolog with library(reif).

Topics

Resources

License

Stars

Watchers

Forks

Languages