How to list the clauses inside a module in SWI-Prolog? - reflection

SWI-Prolog has for example the library(dcgbasics) for use with DCGs.
While referencing the module is easy with use_module/1, e.g.
:- use_module(library(dcg/basics)).
trying to use listing/1 with it is not so easy.
?- listing(dcg:_).
true.
?- listing(dcgbasics:_).
true.
?- basics:listing.
true.
What is the correct way to get a listing of the clauses in library(dcg/basics)?
Follow up after answer given.
To list a specific clause, e.g. blanks//0 the query is
?- listing(dcg_basics:blanks).
blanks(A, B) :-
blank(A, C),
!,
D=C,
blanks(D, B).
blanks(A, A).
true.

Use either:
?- dcg_basics:listing.
Or:
?- listing(dcg_basics:_).
The first argument of use_module/1-2 is a file specification, not a module name. But listing the module contents requires the actual module name, which may be different (as it is the case here) from the module file basename. But how to find the module name from the file specification? In the particular case of SWI-Prolog:
?- absolute_file_name(library(dcg/basics), Path, [extensions([pl])]),
module_property(Module, file(Path)).
Path = '/Users/pmoura/lib/swipl/library/dcg/basics.pl',
Module = dcg_basics.

Related

SProxy in purescript?

What's the use of Sproxy in purescript?
In Pursuit, it's written as
data SProxy (sym :: Symbol)
--| A value-level proxy for a type-level symbol.
and what is meant by Symbol in purescipt?
First, please note that PureScript now has polykinds since version 0.14 and most functions now use Proxy instead of SProxy. Proxy is basically a generalisation of SProxy.
About Symbols and Strings
PureScript knows value level strings (known as String) and type level strings (known as Symbol).
A String can have any string value at runtime. The compiler does not track the value of the string.
A Symbol is different, it can only have one value (but remember, it is on the type level). The compiler keeps track of this string. This allows the compiler to type check certain expressions.
Symbols in Practice
The most prominent use of Symbols is in records. The difference between a Record and a String-Map is that the compiler knows about the keys at compile time and can typecheck lookups.
Now, sometimes we need to bridge the gap between these two worlds: The type level and the value level world. Maybe you know that PureScript records are implemented as JavaScript objects in the official compiler. This means we need to somehow receive a string value from our symbol. The magical function reflectSymbol allows us to turn a symbol into a string. But a symbol is on the type level. This means we can only write a symbol where we can write types (so for example in type definition after ::). This is where the Proxy hack comes in. The SProxy is a simple value that "stores" the type by applying it.
For example the get function from purescript-records allows us to get a value at a property from a record.
get :: forall proxy r r' l a. IsSymbol l => Cons l a r' r => proxy l -> Record r -> a
If we apply the first paramerter we get:
get (Proxy :: Proxy "x") :: forall r a. { x :: a | r } -> a
Now you could argue that you can get the same function by simply writing:
_.x :: forall r a. { x :: a | r } -> a
It has exactly the same type. This leads to one last question:
But why?
Well, there are certain meta programming szenarios, where you don't programm for a specific symbol, but rather for any symbol. Imagine you want to write a JSON serialiser for any record. You might want to "iterate" over every property of the record, get the value, turn the value itself into JSON and then concatinate the key value pair with all the other keys and values.
An example for such an implementation can be found here
This is maybe not the most technical explanation of it all, but this is how I understand it.

Mirror binary tree in Prolog

What I have...
tree(nil).
tree(b(Left,_,Right)) :-
tree(Left),
tree(Right).
mirror(b(Left,Head,Right), NewTree) :-
mirror(Left,NewLeft),
mirror(Right,NewRight),
NewTree = b(NewRight,Head,NewLeft).
What I'm querying...
mirror(b(nil,a,b(nil,b,nil)), Result).
Expected result
Result = b(b(nil,b,nil),a,nil).
The tree b(Left,Right,Head) is the first argument of mirror, NewTree is the goal. mirror(Left,NewLeft) recurses through the left side and yields the goal NewLeft, same for Right. NewTree is the tree b(NewRight,Head,NewLeft).
I'm not sure why this isn't working could someone please help.
Based on your current code
tree(nil).
tree(b(Left,_,Right)) :-
tree(Left),
tree(Right).
mirror(b(Left,Head,Right), NewTree) :-
mirror(Left,NewLeft),
mirror(Right,NewRight),
NewTree = b(NewRight,Head,NewLeft).
you are very close.
As noted in a comment by Steven
You're missing the base case for mirror/2. What should NewTree be when the input tree is nil?
is very helpful.
Before getting to the full working predicate lets clear up a other things.
The predicate for tree is not needed.
tree(nil).
tree(b(Left,_,Right)) :-
tree(Left),
tree(Right).
I don't know if you are showing this to shows us that you know how a tree works or what but for others reading this predicate it is not needed for the answer.
That leaves only
mirror(b(Left,Head,Right), NewTree) :-
mirror(Left,NewLeft),
mirror(Right,NewRight),
NewTree = b(NewRight,Head,NewLeft).
A standard style with using a variable that works like an input and output with several usages is for the starting one, append a 0, then for each succeeding use increase the appended number and for the result append nothing.
mirror(b(Left0,Head,Right0), NewTree) :-
mirror(Left0,Left),
mirror(Right0,Right),
NewTree = b(Right,Head,Left).
Next =/2 is just doing unification. This can be refactored as such
mirror(b(Left0,Head,Right0), b(Right,Head,Left)) :-
mirror(Left0,Left),
mirror(Right0,Right).
Now back to your problem
Since a tree is a recursive structure, it can be processed with with recursion. Predicates that work on recursive data structures need a base clause and a clause to do the recursion. You already have a clause to do the recursion but just need a base clause.
If you use the SWI-Prolog gui tracer on your code for the query
mirror(b(nil,a,b(nil,b,nil)), Result).
you will see
that when one of the branches is just nil there is no mirror/2 rule to handle this case.
Adding
mirror(nil,nil).
will solve your problem.
?- mirror(b(nil,a,b(nil,b,nil)), Result).
Result = b(b(nil, b, nil), a, nil).
The entire predicate.
mirror(nil,nil).
mirror(b(Left0,Head,Right0), b(Right,Head,Left)) :-
mirror(Left0,Left),
mirror(Right0,Right).

Prolog, issues with base case failing

I'm currently writing a prolog A* search function, and ran into an issue with one of my queries. So I decided to manually test the base case, as that's where the trace was failing.
addAChild([Child],[],[Child]):-
write(woo empty).
I manually ran:
addAChild([c(1,1,p(1,2)),[]],[],A).
but it just fails.
Any help would be appreciated.
[Child] (a 1-element list) cannot unify with [c(1,1,p(1,2)),[]] (a 2-elements list).
That's why it is failing.
You can manually test in the interactive interpreter that those two terms fail to unify:
?- addAChild([Child],[],[Child]) = addAChild([c(1,1,p(1,2)),[]],[],A).
false.
and then you can inspect recursively which part is failing.
The term name (addAChild) and the arity (3) is the same, so we can rule off this issue.
Then proceed to unify each argument:
?- [Child] = A.
A = [Child].
?- [] = [].
true.
?- [Child] = [c(1,1,p(1,2)),[]].
false.

How to display the definition of a function

This is probably a newbie question... but is it possible to show the definition of a (user defined) function? While debugging/optimizing it is convenient to quickly see how a certain function was programmed.
Thanks in advance.
You can use the #edit macro, which is supposed to take you to the definition of a method, similarly to how the #which macro which shows the file and line # where that particular method was defined, for example:
julia> #which push!(CDFBuf(),"foo")
push!{T<:CDF.CDFBuf}(buff::T, x) at /d/base/DA/DA.jl:105
julia> #which search("foobar","foo")
search(s::AbstractString, t::AbstractString) at strings/search.jl:146
Note that methods that are part of Julia will show a path relative to the julia source directory "base".
While this is not an automatic feature available with Julia in general (as pointed out by Stefan), if you add docstrings when you define your initial function, you can always use the help?> prompt to query this docstring. For example
julia> """mytestfunction(a::Int, b)""" function mytestfunction(a::Int, b)
return true
This attaches the docstring "mytestfunction(a::Int, b)" to the function mytestfunction(a::Int, b). Once this is defined, you can then use the Julia help prompt (by typing ? at the REPL), to query this documentation.
help?> mytestfunction
mytestfunction(a::Int, b)

issues regarding prolog backtracking to find other solution

I am beginner of Prolog.
what I have is a function traverse a list and return true when it satisfies the condition.
for example, check_version checks if the package version met the condition(eg. the version satisfies the condition such as greater than or less than the specific version) and check_all checks takes a list of versions and conditions to check one by one.
package('python', '2.6.5').
package('python', '2.5.4').
package('python', '1.5.2').
package('python', '3.1.0').
check_version(Pac, Ver, Cmp, V):-
package(Pac, V),
cmp_version(V, Ver, Cmp).
check_all( Pac, [], [], V):-
package(Pac, V).
check_all(Pac, [Ver], [Cmp], V):-
check_version(Pac, Ver, Cmp, V).
check_all(Pac, [Ver|VerS], [Cmp|CmpS], V):-
check_version(Pac, Ver, Cmp, V),
check_all(Pac, VerS, CmpS, V).
The problem I have is when try to find other solutions, it gives me duplicate solution.
I get:
check_all('python', ['3.0','2.4'], [lt,ge], V).
V = '2.6.5' ;
V = '2.6.5' ;
V = '2.5.4' ;
V = '2.5.4' .
expected:
check_all('python', ['3.0','2.4'], [lt,ge], V).
V = '2.6.5' ;
V = '2.5.4' .
I used trace to track it, and the problem I found, when it try to find another solution it back tracks and will return fail until find the right solution. Like the example above, apparently, it will return true for V='2.6.5' at first and take that to back track and run the functions, and we expect it returns false and then when it reach the beginning it run package('python', V) and V will take another value.
...
Exit: (7) check_all(python, ['3.0', '2.4'], [lt, ge], '2.6.5') ? creep
V = '2.6.5'
...
Fail: (9) check_version(python, '2.4', ge, '2.6.5') ? creep
Redo: (8) check_all(python, ['2.4'], [ge], '2.6.5') ? creep
Call: (9) check_version(python, '2.4', ge, '2.6.5') ? creep
Call: (10) package(python, '2.6.5') ? creep
Exit: (10) package(python, '2.6.5') ? creep
when back tracking, in check_all, it fails at check_all as we expected, but it returns true when it backtracks check_version and run package(python, '2.6.5') as V=2.6.5 a new value. so it return true again when V=2.6.5. is there any way to solve this problem?
To localize your problem, first reduce the size of your input. A single element suffices:
?- check_all('python', ['3.0'], [lt], V).
Now, which rules apply for a single element?
Both rules apply! So remove the more specialized one.
There is also another way how to localize such a problem. Simply compare the rules to each other and try to figure out a case where they both apply. The last rule applies for VerS = [] when also the first applies.
Applying a predicate to each element of a list is best done by a predicate that has the list as its first argument. Without going into detail, this makes the predicate succeed when the iteration is complete, if the argument is a list and not a variable (i.e. when it is an input argument). You should have two clauses: one to deal with the empty list and one for the general case:
foo([]). % succeed
foo([X|Xs]) :-
/* apply a predicate to X */
foo(Xs). % apply predicate to the rest of the list
An important thing here is that you don't need a third clause that deals with lists with one element only, since a list with one element is actually a list with an element and an empty list as its tail:
?- [a] == [a|[]].
true.
?- [a] = [a|[]].
true.
Another important thing is that there is nothing you should be doing in the base case, empty list (at least for your example).
To the problem now: your inputs are
the package name
two lists holding pairs of arguments to a predicate you have defined elsewhere (cmp_version/3). This is your list of conditions.
Implementation:
Known packages are available as facts: they can be enumerated by backtracking.
Conditions are an input arguments, provided as a list: you need to apply the condition to each element of the list(s).
The predicate:
check_all([], [], _, _).
check_all([V|Vs], [C|Cs], Name, Version) :-
package(Name, V), % enumerate all known packages by backtracking
cmp_version(Version, V, Cmp), % condition
check_all(Vs, Cs, Name, Version). % apply condition to the rest of the list(s)
You should read the documentation of maplist. You can express the query for example as:
?- maplist(check_version(python), ['3.0', '2.4'], [lt, ge], Versions).
where you have defined a predicate check_version/4 that looks something like:
check_version(Name, V, Cmp, Version) :-
package(Name, Version),
cmp_version(Version, V, Cmp).
As a side note, maplist will reorder its arguments to make it behave like the explicit iteration above.
EDIT
Naming issues, after #mat's comments: one very useful naming convention is to use a name that has descriptive one-word names for the arguments, delimited by underscores. For example, package/2 becomes package_version/2 since its first argument is the package and the second one the version.

Resources