What is the definition of the symbol "=>" in Picat and how do you read it ? Is it an implication ? I have trouble to understand it since there seems to be no informations about it in the manual nor in the book.
%example using "=>"
main =>
A = true,
B = true,
C = function(A,B),
predicate(A,B).
function(true,true) = R => R = true.
predicate(true,true) => true.
How would you describe the meaning of "=>" in the previous example ? Is it just something syntactically required, such as "{" after the declaration of a method in Java, or has a deeper meaning ?
Briefly, if you use => instead of :-, you are essentially writing a deterministic predicate. As we know that Prolog is a practical programming language and it is not necessary to keep all predicates pure. A lot of time, we actually write impure programs by cut and hope single sided unification. The => just provides a convenient mechanism to write such programs.
You can understand => by program transformation.
p(A1,A2,...An), C1, C2, ... => Body
is semantically equivalent to
p(V1,V2,...Vn) :-
Pattern = p(A1,A2,...An),
Args = p(V1,V2,...Vn),
subsumes_term(Pattern, Args),
Pattern = Args,
C1, C2, ...,
!,
Body.
More detail see https://swi-prolog.discourse.group/t/picat-style-matching
Related
In Prolog predicates, I often write repetitive conditional statements like this one, but I wish they could be written more concisely:
output(Lang, Type, Output) :-
(Lang = javascript ->
Output = ["function", Type];
Lang = ruby ->
Output = ["def", Type];
Lang = java ->
Output = [Type]).
Would it be possible to replace this series of conditional statements with a more concise switch-statement?
In Prolog it is quite easy to define your own control structures, using meta-predicates (predicates that take goals or predicates as arguments).
For example, you could implement a switch construct like
switch(X, [
a : writeln(case1),
b : writeln(case2),
c : writeln(case3)
])
by defining
switch(X, [Val:Goal|Cases]) :-
( X=Val ->
call(Goal)
;
switch(X, Cases)
).
If necessary, this can then be made more efficient by compile-time transformation as supported by many Prolog systems (inline/2 in ECLiPSe, or goal expansion in several other systems).
And via operator declarations you can tweak the syntax to pretty much anything you like.
It seems that multiple clauses are made for this use case and also quite concise.
output(javascript, Type, ["javascript", Type]).
output(ruby, Type, ["def", Type]).
output(java, Type, [Type]).
slightly shorter:
output(Lang, Type, Output) :-
(Lang, Output) = (javascript, ["function", Type]) ;
(Lang, Output) = (ruby, ["def", Type]) ;
(Lang, Output) = (java, [Type]).
idiomatic:
output(Lang, Type, Output) :-
memberchk(Lang-Output, [
javascript - ["function", Type],
ruby - ["def", Type],
java - [Type]
]).
I have to write a predicate to do work like following:
?- cat(north,south,X).
X = northsouth
?- cat(alley,'91',Y).
X = alley91
?-cat(7,uthah,H).
Bad Input
H = H
Please Help..
atom_concat_redefined(A1, A2, A3) :-
( nonvar(A1) -> atom_chars(A1, Chs1) ; true ),
( nonvar(A2) -> atom_chars(A2, Chs2) ; true ),
( nonvar(A1), nonvar(A2) -> true ; atom_chars(A3, Chs3) ),
append(Chs1, Chs2, Chs3),
atom_chars(A1, Chs1),
atom_chars(A2, Chs2),
atom_chars(A3, Chs3).
This definition produces the same errors in a standard conforming implementation like SICStus or GNU - there should be no other differences, apart from performance. To compare the errors use the goal:
?- catch(atom_concat_redefined(A,B,abc+1), error(E,_), true).
E = type_error(atom,abc+1).
Note the underscore in error(E,_), which hides the implementation defined differences. Implementations provide additional information in this argument, in particular, they would reveal that atom_chars/2 or atom_concat/3 produced the error.
atom_codes/2 it's the ISO approved predicate to convert between an atom and a list of codes. When you have 2 lists corresponding to first two arguments, append/3 (alas, not ISO approved, but AFAIK available in every Prolog), will get the list corresponding to third argument, then, convert that list to atom...
Note that, while append/3 is a 'pure' Prolog predicate, and can work with any instantiation pattern, atom_codes/2 requires at least one of it's argument instantiated. Here is a SWI-Prolog implementation of cat/3, 'working' a bit more generally. I hope it will inspire you to read more about Prolog...
ac(X,Xs) :- when((ground(X);ground(Xs)), atom_codes(X,Xs)).
cat(X,Y,Z) :- maplist(ac, [X,Y,Z],[Xs,Ys,Zs]), append(Xs,Ys,Zs).
edit
as noted by #false I was wrong about append/3. Now I'll try to understand better what append/3 does... wow, a so simple predicate, so behaviour rich!
I want to parse a logical expression using DCG in Prolog.
The logical terms are represented as lists e.g. ['x','&&','y'] for x ∧ y the result should be the parse tree and(X,Y) (were X and Y are unassigned Prolog variables).
I implemented it and everything works as expected but I have one problem:
I can't figure out how to parse the variable 'x' and 'y' to get real Prolog variables X and Y for the later assignment of truth values.
I tried the following rule variations:
v(X) --> [X].:
This doesn't work of course, it only returns and('x','y').
But can I maybe uniformly replace the logical variables in this term with Prolog variables? I know of the predicate term_to_atom (which is proposed as a solution for a similar problem) but I don't think it can be used here to achieve the desired result.
v(Y) --> [X], {nonvar(Y)}.:
This does return an unbound variable but of course a new one every time even if the logical variable ('x','y',...) was already in the term so
['X','&&','X'] gets evaluated to and(X,Y) which is not the desired result, either.
Is there any elegant or idiomatic solution to this problem?
Many thanks in advance!
EDIT:
The background to this question is that I'm trying to implement the DPLL-algorithm in Prolog. I thought it would by clever to directly parse the logical term to a Prolog-term to make easy use of the Prolog backtracking facility:
Input: some logical term, e.g T = [x,'&&',y]
Term after parsing: [G_123,'&&',G_456] (now featuring "real" Prolog variables)
Assign a value from { boolean(t), boolean(f) } to the first unbound variable in T.
simplify the term.
... repeat or backtrack until a assignment v is found so that v(T) = t or the search space is depleted.
I'm pretty new to Prolog and honestly couldn't figure out a better approach. I'm very interested in better alternatives! (So I'm kinda half-shure that this is what I want ;-) and thank you very much for your support so far ...)
You want to associate ground terms like x (no need to write 'x') with uninstantiated variables. Certainly that does not constitute a pure relation. So it is not that clear to me that you actually want this.
And where do you get the list [x, &&, x] in the first place? You probably have some kind of tokenizer. If possible, try to associate variable names to variables prior to the actual parsing. If you insist to perform that association during parsing you will have to thread a pair of variables throughout your entire grammar. That is, instead of a clean grammar like
power(P) --> factor(F), power_r(F, P).
you will now have to write
power(P, D0,D) --> factor(F, D0,D1), power_r(F, P, D1,D).
% ^^^^ ^^^^^ ^^^^
since you are introducing context into an otherwise context free grammar.
When parsing Prolog text, the same problem occurs. The association between a variable name and a concrete variable is already established during tokenizing. The actual parser does not have to deal with it.
There are essentially two ways to perform this during tokenization:
1mo collect all occurrences Name=Variable in a list and unify them later:
v(N-V, [N-V|D],D) --> [N], {maybesometest(N)}.
unify_nvs(NVs) :-
keysort(NVs, NVs2),
uniq(NVs2).
uniq([]).
uniq([NV|NVs]) :-
head_eq(NVs, NV).
uniq(NVs).
head_eq([], _).
head_eq([N-V|_],N-V).
head_eq([N1-_|_],N2-_) :-
dif(N1,N2).
2do use some explicit dictionary to merge them early on.
Somewhat related is this question.
Not sure if you really want to do what you asked. You might do it by keeping a list of variable associations so that you would know when to reuse a variable and when to use a fresh one.
This is an example of a greedy descent parser which would parse expressions with && and ||:
parse(Exp, Bindings, NBindings)-->
parseLeaf(LExp, Bindings, MBindings),
parse_cont(Exp, LExp, MBindings, NBindings).
parse_cont(Exp, LExp, Bindings, NBindings)-->
parse_op(Op, LExp, RExp),
{!},
parseLeaf(RExp, Bindings, MBindings),
parse_cont(Exp, Op, MBindings, NBindings).
parse_cont(Exp, Exp, Bindings, Bindings)-->[].
parse_op(and(LExp, RExp), LExp, RExp)--> ['&&'].
parse_op(or(LExp, RExp), LExp, RExp)--> ['||'].
parseLeaf(Y, Bindings, NBindings)-->
[X],
{
(member(bind(X, Var), Bindings)-> Y-NBindings=Var-Bindings ; Y-NBindings=Var-[bind(X, Var)|Bindings])
}.
It parses the expression and returns also the variable bindings.
Sample outputs:
?- phrase(parse(Exp, [], Bindings), ['x', '&&', 'y']).
Exp = and(_G683, _G696),
Bindings = [bind(y, _G696), bind(x, _G683)].
?- phrase(parse(Exp, [], Bindings), ['x', '&&', 'x']).
Exp = and(_G683, _G683),
Bindings = [bind(x, _G683)].
?- phrase(parse(Exp, [], Bindings), ['x', '&&', 'y', '&&', 'x', '||', 'z']).
Exp = or(and(and(_G839, _G852), _G839), _G879),
Bindings = [bind(z, _G879), bind(y, _G852), bind(x, _G839)].
I wander why Mercury (10.04) can't infer determinism of next snippet:
:- pred load_freqs(int::in, io.res(list(float))::out, io::di, io::uo) is det.
load_freqs(CPU, ResFreqs, !IO):-
open_input(cpu_fn(CPU, "available_frequencies"), ResStream, !IO),
(ResStream = io.ok(Stream) ->
ResFreqs = io.ok([])
;ResStream = io.error(Err),
ResFreqs = io.error(Err)
).
It complains:
cpugear.m:075: In `load_freqs'(in, out, di, uo):
cpugear.m:075: error: determinism declaration not satisfied.
cpugear.m:075: Declared `det', inferred `semidet'.
cpugear.m:080: Unification of `ResStream' and `io.error(Err)' can fail.
cpugear.m:076: In clause for predicate `cpugear.load_freqs'/4:
cpugear.m:076: warning: variable `CPU' occurs only once in this scope.
cpugear.m:078: In clause for predicate `cpugear.load_freqs'/4:
cpugear.m:078: warning: variable `Stream' occurs only once in this scope.
But io.res have only io.ok/1 and io.error/1.
And next snippet of code compiles well:
:- pred read_freqs(io.res(io.input_stream)::in, io.res(list(float))::out, io::di, io::uo) is det.
read_freqs(io.ok(Stream), io.ok([]), IO, IO).
read_freqs(io.error(Err), io.error(Err), IO, IO).
Update #1:
It can decide det even for:
:- pred read_freqs(bool::in, io.res(io.input_stream)::in, io.res(list(float))::out, io::di, io::uo) is det.
read_freqs(no, ResStream, io.ok([]), IO, IO):- ResStream = io.ok(_).
read_freqs(F, io.ok(_), io.ok([]), IO, IO):- F = yes.
read_freqs(yes, io.error(Err), io.error(Err), IO, IO).
read_freqs(F, ResStream, io.error(Err), IO, IO):- ResStream = io.error(Err), F = no.
My reading of the Mercury rules for determinism with conditionals (below) is that for this to be considered deterministic, you should replace the -> with a ,
From the Mercury reference manual:
If the condition of an if-then-else
cannot fail, the if-then-else is
equivalent to the conjunction of the
condition and the “then” part, and its
determinism is computed accordingly.
Otherwise, an if-then-else can fail if
either the “then” part or the “else”
part can fail.
As for 'Why'. lets look at the original code with the if-then-else:
(ResStream = io.ok(Stream) ->
ResFreqs = io.ok([])
;ResStream = io.error(Err),
ResFreqs = io.error(Err)
).
If the condition fails, then the first conjunct in the else case is a semidet test. The compiler doesn't know that it must succeed (which can be inferred by the knowledge that this condition failed). In other words, the compiler is not smart enough.
That said, it's vary rare to find this problem, because usually the condition is more complicated and won't allow for this inference to be made, so it's not important that the compiler is not smart enough to determine the correct determinism here.
It is recommended to program using switches whenever possible (such as this example), it prevents the current problem and helps ensure that you've covered all the possible cases of ResStream. For example, if in the future io.error was re factored and could be io.error_file_not_found or io.error_disk_full etc the compiler would direct the programmer to fix their switch as it would now be incomplete.
Ok, it can infer det for:
:- pred load_freqs(int::in, io.res(list(float))::out, io::di, io::uo) is det.
load_freqs(CPU, ResFreqs, !IO):-
open_input(cpu_fn(0, "available_frequencies"), ResStream, !IO),
(ResStream = io.ok(Stream),
ResFreqs = io.ok([])
;ResStream = io.error(Err),
ResFreqs = io.error(Err)
).
But why "if-then-else" construction introduces semidet?
Where can I find a list of Scala's "magic" functions, such as apply, unapply, update, +=, etc.?
By magic-functions I mean functions which are used by some syntactic sugar of the compiler, for example
o.update(x,y) <=> o(x) = y
I googled for some combination of scala magic and synonyms of functions, but I didn't find anything.
I'm not interested with the usage of magic functions in the standard library, but in which magic functions exists.
As far as I know:
Getters/setters related:
apply
update
identifier_=
Pattern matching:
unapply
unapplySeq
For-comprehensions:
map
flatMap
filter
withFilter
foreach
Prefixed operators:
unary_+
unary_-
unary_!
unary_~
Beyond that, any implicit from A to B. Scala will also convert A <op>= B into A = A <op> B, if the former operator isn't defined, "op" is not alphanumeric, and <op>= isn't !=, ==, <= or >=.
And I don't believe there's any single place where all of Scala's syntactic sugars are listed.
In addition to update and apply, there are also a number of unary operators which (I believe) qualify as magical:
unary_+
unary_-
unary_!
unary_~
Add to that the regular infix/suffix operators (which can be almost anything) and you've got yourself the complete package.
You really should take a look at the Scala Language Specification. It is the only authoritative source on this stuff. It's not that hard to read (as long as you're comfortable with context-free grammars), and very easily searchable. The only thing it doesn't specify well is the XML support.
Sorry if it's not exactly answering your question, but my favorite WTF moment so far is # as assignment operator inside pattern match. Thanks to soft copy of "Programming in Scala" I found out what it was pretty quickly.
Using # we can bind any part of a pattern to a variable, and if the pattern match succeeds, the variable will capture the value of the sub-pattern. Here's the example from Programming in Scala (Section 15.2 - Variable Binding):
expr match {
case UnOp("abs", e # UnOp("abs", _)) => e
case _ =>
}
If the entire pattern match succeeds,
then the portion that matched the
UnOp("abs", _) part is made available
as variable e.
And here's what Programming Scala says about it.
That link no longer works. Here is one that does.
I'll also add _* for pattern matching on an arbitrary number of parameters like
case x: A(_*)
And operator associativity rule, from Odersky-Spoon-Venners book:
The associativity of an operator in Scala is determined by its last
character. As mentioned on <...>, any method that ends
in a ‘:’ character is invoked on its right operand, passing in the
left operand. Methods that end in any other character are the other
way around. They are invoked on their left operand, passing in the
right operand. So a * b yields a.*(b), but a ::: b yields b.:::(a).
Maybe we should also mention syntactic desugaring of for expressions which can be found here
And (of course!), alternative syntax for pairs
a -> b //converted to (a, b), where a and b are instances
(as correctly pointed out, this one is just an implicit conversion done through a library, so it's probably not eligible, but I find it's a common puzzler for newcomers)
I'd like to add that there is also a "magic" trait - scala.Dynamic:
A marker trait that enables dynamic invocations. Instances x of this trait allow method invocations x.meth(args) for arbitrary method names meth and argument lists args as well as field accesses x.field for arbitrary field names field.
If a call is not natively supported by x (i.e. if type checking fails), it is rewritten according to the following rules:
foo.method("blah") ~~> foo.applyDynamic("method")("blah")
foo.method(x = "blah") ~~> foo.applyDynamicNamed("method")(("x", "blah"))
foo.method(x = 1, 2) ~~> foo.applyDynamicNamed("method")(("x", 1), ("", 2))
foo.field ~~> foo.selectDynamic("field")
foo.varia = 10 ~~> foo.updateDynamic("varia")(10)
foo.arr(10) = 13 ~~> foo.selectDynamic("arr").update(10, 13)
foo.arr(10) ~~> foo.applyDynamic("arr")(10)
As of Scala 2.10, defining direct or indirect subclasses of this trait is only possible if the language feature dynamics is enabled.
So you can do stuff like
import scala.language.dynamics
object Dyn extends Dynamic {
def applyDynamic(name: String)(a1: Int, a2: String) {
println("Invoked " + name + " on (" + a1 + "," + a2 + ")");
}
}
Dyn.foo(3, "x");
Dyn.bar(3, "y");
They are defined in the Scala Language Specification.
As far as I know, there are just three "magic" functions as you mentioned.
Scalas Getter and Setter may also relate to your "magic":
scala> class Magic {
| private var x :Int = _
| override def toString = "Magic(%d)".format(x)
| def member = x
| def member_=(m :Int){ x = m }
| }
defined class Magic
scala> val m = new Magic
m: Magic = Magic(0)
scala> m.member
res14: Int = 0
scala> m.member = 100
scala> m
res15: Magic = Magic(100)
scala> m.member += 99
scala> m
res17: Magic = Magic(199)