Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Picat: A New Logic-Based Language

1,676 views
Skip to first unread message

Picat-lang.org

unread,
Dec 6, 2012, 5:05:50 PM12/6/12
to
We have completed the initial design of Picat, a new logic-based programming language, and would like to seek comments and suggestions from people with different backgrounds, including Prolog programmers, in order to test and refine the design. The proposal is available at:

http://picat-lang.org/

The major differences between Picat and Prolog are: Picat supports explicit unification (pattern-matching), explicit non-determinism, functions, and imperative constructs; Picat does not support the cut operator, dynamic predicates, or operator overloading. Picat will inherit tabling and constraint programming from B-Prolog.

You can find example programs in Picat at:

http://www.picat-lang.org/download/exs.pi.txt

The tentative proposal of library modules is available at:

http://www.picat-lang.org/download/builtin.pdf

We are forming the Picat Association and would like you to join as a developer, a user, or a sponsor. We hope to release the first version with the basic functionality by May 2013.

Sincerely,
Neng-Fa Zhou

Jan Burse

unread,
Dec 6, 2012, 5:38:59 PM12/6/12
to
Picat-lang.org schrieb:
> We have completed the initial design of Picat, a new logic-based programming language, and would like to seek comments and suggestions from people with different backgrounds, including Prolog programmers, in order to test and refine the design. The proposal is available at:
>
> http://picat-lang.org/

Is it possible to define a meta interpreter for
picat in picat? Especially the action rules would
interest me.

Bye



Picat-lang.org

unread,
Dec 7, 2012, 10:19:38 AM12/7/12
to
On Thursday, December 6, 2012 5:38:59 PM UTC-5, Jan Burse wrote:
> Is it possible to define a meta interpreter for
>
> picat in picat? Especially the action rules would
>
> interest me.

No. You can't do meta-programming in Picat as you do in Prolog. You are not allowed to create certain terms, such as the dot notation (m.p(x)), the index notation (X[1]), range expressions (1..5), and loops. This restriction has pros and cons. It enables the compiler to check many things such as module quantifiers, certain data types, and variable scopes in loops, but on the other hand it disallows interpreting of these terms. I think the meta-programming ability of Prolog is overemphasized. Few people write programs to interpret other programs. Now with libraries for writing scanners and parsers, it is quite easy to write interpreters.

Action rules are always compiled, even in B-Prolog. When you have events posted by C functions or by other threads, how can you interpret action rules?

Cheers,
Neng-Fa

Picat-lang.org

unread,
Dec 7, 2012, 10:59:01 AM12/7/12
to
On Thursday, December 6, 2012 5:05:50 PM UTC-5,
Alan Baljeu wrote:
>You forgot to explain _why_ you are making a new language.
>There is a long list of languages, even logic programming
>languages, even ones with much of what you describe here.
>What does Picat achieve that wasn't possible before - and I
>mean in practical terms, not in terms of a peculiar feature
>set - that you couldn't just run with one of the other
>languages?

None of the ingredients is new and I don't see any tasks that Picat can do but are not doable in Prolog, or Mercury, or Oz. Among the features (P-predicates&functions, I-imperative, C-constraints, A-actors, T-tabling), imperative programming constructs may be new in the context. The failure to add loops into B-Prolog satisfactorily is the main motivation for Picat. In Picat, assignments and loops have a clear operational semantics. Unlike in B-Prolog, we never need to declare local variables in loops.

I heard the statistics at the Warren Symposium: 50 percent of the students at SB don't know recursion. I think the percentage is even higher in my class. But many of these students can do decent job as a professional programmer. I hope Picat will be accessible to these people. Maybe this will be something that can be achieved by Picat but not other logic-based languages.

Cheers,
Neng-Fa

Jan Burse

unread,
Dec 7, 2012, 11:50:28 AM12/7/12
to
Picat-lang.org schrieb:
> No. You can't do meta-programming in Picat as you do in Prolog.
> You are not allowed to create certain terms, such as the dot
> notation (m.p(x)), the index notation (X[1]), range expressions
> (1..5), and loops.

Is meta-programming totally exlcuded or only restricted? Can
one do the following:

forall(X, Y) :- \+ (X, \+Y).

I guess there is meta-programming in Picat, meta-programming
being the special case of zero extra arguments for call/n.
I find:

10 Higher-Order Calls

"A call passed to a higher-order predicate or function is
assumed to invoke a definition in the same module or an
imported module. If the compiler cannot bind a call to a
definition because the name is unknown, then it generates
code to search the enclosing module and the imported modules
for a definition at runtime."

> I think the meta-programming ability of Prolog is over-
> emphasized. Few people write programs to interpret other
> programs.

Dunno. Google tells me:

higher-order programming
Ungef�hr 21'300'000 Ergebnisse (0.28 Sekunden)

meta-interpreter
Ungef�hr 14'200'000 Ergebnisse (0.12 Sekunden)

> Action rules are always compiled, even in B-Prolog.
> When you have events posted by C functions or by other
> threads, how can you interpret action rules?

Many CHR systems etc.. have meta interpreters. You can view
them as a spec of a system. An other approach would be to
provide a source to source transformer. Or a mixture
of both. One can also view such approaches as reference
implementations.

GREGORY J. DUCK
A very small CHR reference implementation in Prolog
http://www.comp.nus.edu.sg/~gregory/toychr/

Meta-interpreters for standard Prolog have already shown
value for me. See for example the other thread here
on comp.lang.prolog about iterative deepening. I don't
know yet whether meta interpreters for alternative inference
methods such as CHR, action rules, forward chaining, etc..
have the same value.

Bye

Jan Burse

unread,
Dec 7, 2012, 11:59:52 AM12/7/12
to
Jan Burse schrieb:
> Meta-interpreters for standard Prolog have already shown
> value for me.

Actually the vanilla interpreter for Prolog only needs
meta-programming when you call built-ins from it. Otherwise
it can be done in pure Prolog even. You can also get rid of
the (meta/reflective?) predicate clause/2, by just representing
the clauses via some other binary fact.

The iterative deepening examples of theorem proving didn't
need built-ins in the meta interpreter.

So I guess the question whether somebody has already exhibited
a meta interpreter for action rules, and whether a toy
version can be implemented in Picat is independent of meta-
programming I guess. It would be more an exercise to exhibit
the semantics of Picat action rules in Picat.

Bye

alanb...@gmail.com

unread,
Dec 7, 2012, 12:03:19 PM12/7/12
to
I believe the stat. As for loops in logic programming, I agree it's very useful. Even for me with 15 years experience in recursive coding, it's often just easier to code loops.

But then I also found it was relatively easy to implement in Prolog. I wrote a simple goal expansion macro that converts a loop statement with iterators, conditions and code into a recursive program, and the effective capability is like that of CommonLISP's loop facility.

Is looping the only compelling reason?

Jan Burse

unread,
Dec 7, 2012, 12:11:53 PM12/7/12
to
Picat-lang.org schrieb:
> We have completed the initial design of Picat, a new logic-based
> programming language, and would like to seek comments and
> suggestions from people with different backgrounds, including
> Prolog programmers, in order to test and refine the design.
> The proposal is available at:
>
> http://picat-lang.org/

Could you say something about:

11 Action Rules and Threads

"A thread is represented as an attributed variable that contains,
amongst other attributes, a thread descriptor.
A thread can serve as a communication channel. A thread can send a
message to another thread by posting an event. Action rules can be used
to program concurrent threads."

I tried to find the same in the B-Prolog manual. But I
didn't find some new_thread built-in etc.. Could it be
that the important new feature in:

[�P�=predicates,�I�=imperative,
�C�=constraints, �A�=actors, �T�=tabling]

is the 'A'=actors. Is picat a kind of Erlang clone, or better
an improvement of Erlang by constraints?

Bye

Picat-lang.org

unread,
Dec 7, 2012, 3:57:30 PM12/7/12
to
The major reason. The function notation is also a big reason. There are hundreds of other tiny reasons. I am curious about how your loops look like. How do you deal with local variables?

Cheers,
Neng-Fa

Picat-lang.org

unread,
Dec 7, 2012, 4:16:29 PM12/7/12
to
B-Prolog does not support threads (timers in B-Prolog are implemented as native threads). Action rules are taken from B-Prolog, where actors are called agents. When applied to constraint propagation, actors are also called propagators. Unlike Erlang processes, Picat actors behave asynchronously. The wait(Channel) built-in is introduced in the design for blocking the executing thread until an event occurs on the channel. Maybe we need to add something like 'receive' of Erlang and Scala for programming concurrent threads. We still need to work out the details on actors and threads.

Cheers,
Neng-Fa
Message has been deleted

alanb...@gmail.com

unread,
Dec 10, 2012, 11:38:06 AM12/10/12
to
Locals? This is Prolog, so you just name a variable it the loop body to create it. A recursive clause is generated so the variable is local to each iteration. If you want the variable to progress each iteration, it isn't really local but an output of the loop, and it's declared as such.

What it looks like. It seems ugly, but it's powerful.

spec_con(Loc, Expr):-
expr:expression_refs(Expr, Refs)
, loop [ each(Refs, Ref) % an enumerator; can have multiple different ones
, var(Loc) % an external variable
, % optional loop body:
{ expr:complete_ref(Loc, Ref, Expanded)
, con_ref(Expanded, _R) % CHR
}
].

Jan Burse

unread,
Dec 10, 2012, 11:39:49 AM12/10/12
to
On Friday, December 7, 2012 10:59:01 AM UTC-5, Picat-lang.org wrote:
> I heard the statistics at the Warren Symposium: 50 percent
> of the students at SB don't know recursion. I think the
> percentage is even higher in my class. But many of these
> students can do decent job as a professional programmer.
> I hope Picat will be accessible to these people. Maybe this
> will be something that can be achieved by Picat but not other
> logic-based languages.

A fool with a tool is still a fool.

But yes, listening to your customers can help improve
a product. On the other hand showing students that while
and recursion are interchangeble might be also a noble
teaching goal.

Bye

Jan Burse

unread,
Dec 10, 2012, 11:41:57 AM12/10/12
to
alanb...@gmail.com schrieb:
> Locals? This is Prolog, so you just name a variable it the loop body to create it. A recursive clause is generated so the variable is local to each iteration. If you want the variable to progress each iteration, it isn't really local but an output of the loop, and it's declared as such.
>
> What it looks like. It seems ugly, but it's powerful.
>
> spec_con(Loc, Expr):-
> expr:expression_refs(Expr, Refs)
> , loop [ each(Refs, Ref) % an enumerator; can have multiple different ones
> , var(Loc) % an external variable
> , % optional loop body:
> { expr:complete_ref(Loc, Ref, Expanded)
> , con_ref(Expanded, _R) % CHR
> }
> ].

What is % CHR, do you require Prolog or Constrant Handling Rules?

Bye

alanb...@gmail.com

unread,
Dec 10, 2012, 12:55:06 PM12/10/12
to
> What is % CHR, do you require Prolog or Constrant Handling Rules?

I probably shouldn't have mentioned it, because it's not relevant to the thread, and not relevant to the loop macro discussed. The loop macro itself is not related to CHR.

The code is Prolog with a goal expansion defined on loop/1. The % CHR line is just a Prolog call to insert a CHR object, i.e. using Constraint Handling Rules.

Jan Burse

unread,
Dec 11, 2012, 6:59:02 AM12/11/12
to
Jan Burse schrieb:
> But yes, listening to your customers can help improve
> a product. On the other hand showing students that while
> and recursion are interchangeble might be also a noble
> teaching goal.

But the loops and sequences of Picat look really nice. A
typical example that can highly profit from loops is

sudoku =>
instance(N,A),
A in 1..N,
foreach(Row in 1..N)
alldifferent([A[Row,Col] : Col in 1..N])
end,
foreach(Col in 1..N)
alldifferent([A[Row,Col] : Row in 1..N])
end,
M=floor(sqrt(N)),
foreach(Row in 1..M, Col in 1..M)
Square = [A[Row1,Col1] :
Row1 in (Row-1)*M+1..Row*M,
Col1 in (Col-1)*M+1..J*M],
alldifferent(Square)
end,
solve(A),
foreach(I in 1..N) write(A[I]) end.
(From http://picat-lang.org/download/picat_proposal.pdf)

It plays well when array indexing is present, and the
above example makes also use of comprehension.

alanb...@gmail.com schrieb:
> What it looks like. It seems ugly, but it's powerful.
>
> spec_con(Loc, Expr):-
> expr:expression_refs(Expr, Refs)
> , loop [ each(Refs, Ref) % an enumerator; can have multiple
different ones
> , var(Loc) % an external variable
> , % optional loop body:
> { expr:complete_ref(Loc, Ref, Expanded)
> , con_ref(Expanded, _R) % CHR
> }
> ].
> The code is Prolog with a goal expansion defined on loop/1.
> The % CHR line is just a Prolog call to insert a CHR object,
> i.e. using Constraint Handling Rules.

I guess by goal expansion you refer to some highlevel view
of loops, and not the usual low level last call optimization
stuff found in engines.

What does the goal expansion do? Only two scenarios come to my mind:
- Creating an auxiliary predicate:
(Wanted to link to SICStus foreach, but can't find it anymore)
- Invoking a higher order fixpoint operator:
http://www.jekejeke.ch/idatab/doclet/prod/en/docs/05_run/10_docu/02_reference/04_examples/03_flag.html

Just curious, anything else?

Bye

Picat-lang.org

unread,
Dec 11, 2012, 9:40:18 AM12/11/12
to
On Tuesday, December 11, 2012 6:59:02 AM UTC-5, Jan Burse wrote:
> Jan Burse schrieb:

> It plays well when array indexing is present, and the
>
Here is my response to Richard O'Keefe's email. I am re-posting it here, hoping that it is of interest to the readers.

Cheers,
Neng-Fa

The unfortunate reality is that many students graduate without fully understanding recursion, and many of them can make a decent living as a programmer. One of my students told me that during his two years of job, he only used recursion a handful of times (he is a web programmer; he was one of the best in my class and understood recursion well). I think it is a big problem of Prolog to force programmers to use recursion. For many tasks, you don't want to use recursion. For example, you may give up if you model the Sudoku problem (you can find the example in Picat in the set of examples) using recursion. I asked my Compilers class to create test programs in Picat for testing their tokenizers and parsers and 90% of the class wrote programs with no recursion at all. See below three of the programs by a student.

/*
Add all the natural numbers below one thousand that are multiples of 3 or 5.
*/

multiple(X) = Sum =>
S = 0,
foreach(N in 1..X)
if((N mod 3)=0 ; (N mod 5) =0) then
S := S+N
end,
end,
Sum = S.


/*
What is the difference between the sum of the squares and the square of the sums?
*/
squares(Num) = D =>
SumSquare = 0,
SquareSum = 0,
foreach(N in 1..Num)
SumSquare := SumSquare + N**2
end,
foreach(N in 1..Num)
SquareSum := SquareSum + N
end,
SquareSum := SquareSum**2,
D = SquareSum - SumSquare.

/*
What is the 10001st prime number?
*/
the_prime = Prime =>
X=0,I=2,C=0,
while(C != 10001)
if(isPrime(I)) then
C := C+1,
X := I
end,
I := I + 1
end,
Prime = X.

isPrime(N) =>
foreach(C in 2..N-1)
N mod C != 0
end.

alanb...@gmail.com

unread,
Dec 11, 2012, 10:36:28 AM12/11/12
to
On Tuesday, December 11, 2012 6:59:02 AM UTC-5, Jan Burse wrote:
> Alan Baljeu wrote:
> > The code is Prolog with a goal expansion defined on loop/1.
>
> I guess by goal expansion you refer to some highlevel view
> of loops, and not the usual low level last call optimization
> stuff found in engines.
>
> What does the goal expansion do? Only two scenarios come to my mind:

By goal expansion I refer to goal_expansion/2. The call to loop/1 is replaced by a call to a generated recursive predicate loop_{GenSym}/N. The generated predicate consists of a tail-recursive clause and a terminal clause.

Refer to Lee's Logical Loops for my inspiration.

> Just curious, anything else?
These are the clauses defined so far:

count(Var, StepVar, Start, Stop) % succ(Var, StepVar) every iteration
step(Var, StepVar, Start, Code) % custom code for stepping
split(List, Head, Tail) % step through List
diff_list(List, Tail1, Tail) % step through diff_list
each(List, Elem)
var(Var) % extra parameter for the loop
{Code} % loop body

It's trivial to define more.

Jan Burse

unread,
Dec 11, 2012, 11:01:01 AM12/11/12
to
Picat-lang.org schrieb:
> I asked my Compilers class to create test programs in Picat for
> testing their tokenizers and parsers and 90% of the class wrote
> programs with no recursion at all. See below three of the programs
> by a student.

Oh this slipped my attention, you have also a
kind of destructive assignment.

test => X=0, X:=X+1, X:=X+2, write(X).
In order to handle assignments, Picat creates
new variables at compile time.
(From the Picat Proposal)

With destructive assignment it gets even a little bit
more simpler to write loops, as your following
example show:

multiple(X) = Sum =>
S = 0,
foreach(N in 1..X)
if((N mod 3)=0 ; (N mod 5) =0) then
S := S+N
end,
end,
Sum = S.

It seems that you use also assignment plus loops internally
to implement comprehension.

But one cannot use it for aggregate functions, since the loop
doesn't take an arbitrary generator.

To implement the loops with the assignments I guess you
need to do a little more than only create new variables
and rename remaining goals. You also need to keep track
of the phoney functions.

The phoney functions would express how your tail recursive
calls need to look like. The overall result resembles
SSA, although I don't know exactly how SSA would deal with
non-determinism.

But it would give you a palette of nice backend systems:
http://en.wikipedia.org/wiki/Static_single_assignment_form

Bye

P.S.: It striked me recently that already normal Prolog
with its logical variables resembles SSA.



Jan Burse

unread,
Dec 11, 2012, 11:39:04 AM12/11/12
to
Jan Burse schrieb:
> The phoney functions would express how your tail recursive
> calls need to look like. The overall result resembles
> SSA, although I don't know exactly how SSA would deal with
> non-determinism.

Maybe if you do the loop conversion before the := conversion,
then you get the phoney functions for free by the simple :=
conversion. Just a guess.

Bye

Picat-lang.org

unread,
Dec 11, 2012, 11:42:44 AM12/11/12
to
Thanks for pointing out the related work on SSA. The semantics of the := operator in Picat is exactly the same as SSA, although I was unaware of the work done on SSA. So, nothing is new and nothing is surprising in Picat. This is exactly what we wanted the language to be.

The work on SSA can serve as the foundation for := in a logic-based language. I was afraid that some people may say that it's ad hoc. I found this operator very useful. Without it, it would be very difficult to implement list comprehension.

Prolog variables are single assignment. Yes, we need to know if non-determinism can cause any problem with :=.

Cheers,
Neng-Fa

Picat-lang.org

unread,
Dec 12, 2012, 8:25:39 PM12/12/12
to
I should have mentioned that I by no means meant to champion my students programs. The point I'd like to make is that Picat is even accessible to people who don't like to use recursion. In Picat, there are better ways to solve these problems. For example,

multiple(X) = sum([N : N in 1..X, (N mod 3 = 0 ; N mod 5 = 0)]).

squares(N) = sum([I**2 : I in 1..N]) - sum([I : I in 1..N])**2.

The good thing about the aggregate function sum(L) is that the list comprehension L is converted into a loop and the aggregate is computed without actually constructing the list.

Cheers,
Neng-Fa

Picat-lang.org

unread,
Jan 5, 2013, 8:21:12 PM1/5/13
to
The complete proposal (160 pages) is available now.

http://picat-lang.org/

Comments are welcome.

Cheers,
Neng-Fa

Artem Falcon

unread,
Oct 21, 2013, 6:12:00 AM10/21/13
to
On 2012-12-07 15:59:01 +0000, Picat-lang.org said:

> The failure to add loops into B-Prolog satisfactorily is the main
motivation for Picat.
> ...
> I heard the statistics at the Warren Symposium: 50 percent of the
students at SB don't know recursion. I think the percentage is even
higher in my class.
> ...
> Cheers,
> Neng-Fa

Sry for the bumping of the old topic, but i wish to put my few bucks here.

I see no reason why a language with a proper tail recursion
optimization should promote imperative loop constructions. It's no
excuse that some pips don't know recursion. They'll not deal with
recursion in it's explicit form in most of cases.
For the loops they may use list homomorphisms like (un)fold (and for
side effects operations a variant of unfold without accumulating) and
similar primitives, which surely should be a part of language's core.
Imperative loops may be retained, but put in a separate lib.

Another thing, Neng-Fa. In a more recent thread you're proclaiming
Picat as a new Python. But i hope you're meaning Python's popularity,
and not that it was your impression when you created a Picat, as imo
Python had proven to be defective by design.

As for the rest, it's a pleasure to see a fresh yet featureful logic
programming language. So, thank you for the Picat.

neng...@gmail.com

unread,
Oct 23, 2013, 6:05:31 PM10/23/13
to
I didn't realize that this thread was still alive.

Assignment may not be a good name for LHS := RHS when LHS is a variable. It only creates a new variable for LHS and makes the old one inaccessible. I have never intended to promote this operator but I do find that many people like it. I personally also use it some times. For example, given a list L, you can create a disjunction of the elements of L this way:

Dis = 0,
foreach (X in L)
Dis := X #\/ Dis
end.

You cannot do this with a list comprehension. If you use recursion, you have to define a new predicate even if this code is used only once.

It would take a lot of efforts to make Picat as popular as Python as a scripting language. It needs many modules, a module for regular expressions, a module for SQL, modules for web services, and modules for many other things. I don't think I can do all of them alone. I hope that the current version is just a base for many other things and the community will take over the development.

An important strength that Picat has but Python (or Ruby or any functional language) does not have is modeling. You can see how nice Picat is as a modeling language for dynamic programming, planning, and constraint satisfaction problems.

Cheers,
Neng-Fa

Julio Di Egidio

unread,
Nov 4, 2013, 5:02:04 PM11/4/13
to
<neng...@gmail.com> wrote in message
news:1dcc8a91-1bf4-4ef1...@googlegroups.com...

> I didn't realize that this thread was still alive.

IMHO, this Picat language is indeed very nice. For sure, I have written
more little programs in Picat in few days than I could write in Prolog in
weeks...

I had put a wish-list together, just early impressions:

Interoperability
Conditional compilation
Non-backtrackable assignment
Zero-based structure indexing
Private predicates as arguments of meta-predicates

Anyway, I look forward to seeing the developments of Picat!

Thanks and all the best,

Julio


Andy Valencia

unread,
Nov 4, 2013, 6:05:52 PM11/4/13
to
"Julio Di Egidio" <ju...@diegidio.name> writes:
> IMHO, this Picat language is indeed very nice. For sure, I have written
> more little programs in Picat in few days than I could write in Prolog in
> weeks...

Puh-leaze. Closed source? Register to request source? I don't
install binary blobs from unknown people, and I don't spend time
guessing at closed source binary blob behavior. That was OK in the
80's, and getting lame in the 90's. But in 2013? Really?

Andy Valencia
Home page: http://www.vsta.org/andy/
To contact me: http://www.vsta.org/contact/andy.html

Julio Di Egidio

unread,
Nov 4, 2013, 6:39:16 PM11/4/13
to
"Andy Valencia" <van...@vsta.org> wrote in message
news:2013110423055...@andy-pandora.vsta.org...
> "Julio Di Egidio" <ju...@diegidio.name> writes:
>> IMHO, this Picat language is indeed very nice. For sure, I have written
>> more little programs in Picat in few days than I could write in Prolog in
>> weeks...
>
> Puh-leaze. Closed source? Register to request source? I don't
> install binary blobs from unknown people

Very considerate, yet you seem comfortable with making a fool of yourself.

Julio


tomena...@gmail.com

unread,
Nov 6, 2013, 5:17:07 AM11/6/13
to
> Dis = 0,
>
> foreach (X in L)
>
> Dis := X #\/ Dis
>
> end.
>
>
>
> You cannot do this with a list comprehension. If you use recursion, you have to define a new predicate even if this code is used only once.

The reusable recursion pattern you need here is a fold, which indeed you cannot express with a list comprehension. If you have a fold, then you don't need to define a new recursive predicate every time.

neng...@gmail.com

unread,
Nov 6, 2013, 8:25:20 PM11/6/13
to
The C source code is open and you can generate executables yourself. Picat is still in beta and you may want to get the source code after the stable version is released, unless you are interested in being a developer.

Cheers,
Neng-Fa

neng...@gmail.com

unread,
Nov 7, 2013, 12:08:21 AM11/7/13
to
By "Interoperability", do you mean interfaces with other languages? This is on the to-do list.

By "Conditional compilation", you mean something like the ifdef directive in C/C++?

Picat already has non-backtrackable assignment. For example,

Picat> get_global_map().put(x,1)

yes

Picat> get_global_map().put(x,2)

yes

Picat> X=get_global_map().get(x)
X = 2


I think 0-based indexing is more common than 1-based indexing because of historical reasons (easier for pointer manipulations), not because it is more convenient. For modeling, I found 1-based indexing more natural than 0-based indexing.

Currently, no private predicates or functions can be higher order. This is due to the design of the simple module system. I believe that a complicated module system introduces more problems than it solves. But this does not mean that the current design of the module system is not subject to change.

Cheers,
Neng-Fa

Julio Di Egidio

unread,
Nov 7, 2013, 2:55:21 PM11/7/13
to
<neng...@gmail.com> wrote in message
news:a1d05f18-ddcf-456e...@googlegroups.com...
> On Monday, November 4, 2013 5:02:04 PM UTC-5, Julio Di Egidio wrote:
<snipped>

>> I had put a wish-list together, just early impressions:
>>
>> Interoperability
>> Conditional compilation
>> Non-backtrackable assignment
>> Zero-based structure indexing
>> Private predicates as arguments of meta-predicates
>
> By "Interoperability", do you mean interfaces with other languages? This
> is on the to-do list.

Yes, I had guessed so, still I thought worth mentioning it so that you can
see that there is request for it.

> By "Conditional compilation", you mean something like the ifdef directive
> in C/C++?

Yes, exactly. In fact, Picat lacking the term rewriting features of Prolog,
I'd think conditional compilation is even more critical.

> Picat already has non-backtrackable assignment. For example,
> Picat> get_global_map().put(x,1)
> yes
> Picat> get_global_map().put(x,2)
> yes
> Picat> X=get_global_map().get(x)
> X = 2

Indeed, that is what I have ended up using: the problem is, if my tests were
correct at all, that that is very slow. I may be mistaken on this point
though...

> I think 0-based indexing is more common than 1-based indexing because of
> historical reasons (easier for pointer manipulations), not because it is
> more convenient. For modeling, I found 1-based indexing more natural than
> 0-based indexing.

0-based indexing is easier to use in many more ways than just pointer
arithmetic (conversely, 1-based indexing in e.g. geometric programming is
quite a nightmare), and it is not per chance that most programming languages
use 0-based indexing. Then when you say "for modeling" of course I cannot
really object... but the main point of interest I have in Picat is that it
is much nearer than Prolog to real world software coding, i.e. the target
would be the generic developer not just the logic programming expert. As
such, adoption of a 0-based indexing is even more compelling: when one codes
as a job, using 0-based indexing all the time except when programming in
Picat is really an annoyance and very error-prone.

> Currently, no private predicates or functions can be higher order. This is
> due to the design of the simple module system. I believe that a
> complicated module system introduces more problems than it solves. But
> this does not mean that the current design of the module system is not
> subject to change.

Yes, of course. Anyway, to clarify, I was referring to the case when one
has a public meta-predicate in a module and wants to pass to it a reference
to another predicate in that module as an argument: it is the predicate
passed as an argument that I was referring to, which, in an significant
class of scenarios (e.g. think a strategy pattern), should be private, yet
at the moment this is not allowed.

Julio


neng...@gmail.com

unread,
Nov 7, 2013, 7:44:38 PM11/7/13
to
Thanks for your explanation.

Do you have an example that uses get_global_map() and that is slow? I'd be happy to take a look at it.

The things you mentioned are mostly doable, except for 0-indexing. It requires a lot of changes to the Engine, which is shared by Picat and B-Prolog.

Cheers,
Neng-Fa

Julio Di Egidio

unread,
Nov 8, 2013, 7:17:51 PM11/8/13
to
<neng...@gmail.com> wrote in message
news:c04d490b-c729-4ad5...@googlegroups.com...
> On Thursday, November 7, 2013 2:55:21 PM UTC-5, Julio Di Egidio wrote:
>> <neng...@gmail.com> wrote in message
>> news:a1d05f18-ddcf-456e...@googlegroups.com...
>> > On Monday, November 4, 2013 5:02:04 PM UTC-5, Julio Di Egidio wrote:
>> <snipped>
>>
>> >> I had put a wish-list together, just early impressions:
>>
>> >> Interoperability
>> >> Conditional compilation
>> >> Non-backtrackable assignment
>> >> Zero-based structure indexing
>> >> Private predicates as arguments of meta-predicates
<snip>

> Thanks for your explanation.

You are very welcome.

> Do you have an example that uses get_global_map() and that is slow? I'd be
> happy to take a look at it.

Well, this is what I have concocted: I am not sure of the relevance...

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/*

Picat> cl(nbatest)
Compiling:: 'nbatest.pi'
nbatest.pi compiled in 10 milliseconds
loading...

yes

Picat> time(C = countA(3, 10.0E5))
CPU time 0.47 seconds.

yes

Picat> time(C = countM(3, 10.0E5))
CPU time 11.54 seconds.
C = 3
yes

Picat>

*/
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

module nbatest.

countA(N, I) = C =>
A = A,
( between(1, to_integer(I), _),
A0 = 0,
( between(1, N, _),
_A1 = A0 + 1,
fail
; true
),
C = A,
fail
; true
),
C = A.

countM(N, I) = C =>
Map = get_global_map(),
( between(1, to_integer(I), _),
Map.put(nbatest, 0),
( between(1, N, _),
C0 = Map.get(nbatest),
C1 = C0 + 1,
Map.put(nbatest, C1),
fail
; true
),
C = Map.get(nbatest),
fail
; true
),
C = Map.get(nbatest).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

> The things you mentioned are mostly doable, except for 0-indexing.
> It requires a lot of changes to the Engine, which is shared by Picat and
> B-Prolog.

Not a major issue, anyway: the first three items in the list I have
submitted are surely the ones I'd consider more critical.

Thanks for your attention,

Julio


Julio Di Egidio

unread,
Nov 8, 2013, 7:20:32 PM11/8/13
to
"Julio Di Egidio" <ju...@diegidio.name> wrote in message
news:l5juvu$48f$1...@dont-email.me...
> <neng...@gmail.com> wrote in message
> news:c04d490b-c729-4ad5...@googlegroups.com...

>> Do you have an example that uses get_global_map() and that is slow? I'd
>> be happy to take a look at it.
>
> Well, this is what I have concocted: I am not sure of the relevance...

Maybe more readable, with spaces in place of tabs:
Julio


Julio Di Egidio

unread,
Nov 8, 2013, 8:05:52 PM11/8/13
to
"Julio Di Egidio" <ju...@diegidio.name> wrote in message
news:l5jv4v$589$1...@dont-email.me...
> "Julio Di Egidio" <ju...@diegidio.name> wrote in message
> news:l5juvu$48f$1...@dont-email.me...
>> <neng...@gmail.com> wrote in message
>> news:c04d490b-c729-4ad5...@googlegroups.com...
>
>>> Do you have an example that uses get_global_map() and that is slow? I'd
>>> be happy to take a look at it.
>>
>> Well, this is what I have concocted: I am not sure of the relevance...
>
> Maybe more readable, with spaces in place of tabs:
<snip>

Sorry, the code is messy because I was trying to compile a variant with
actual "assignment" (i.e. with the := operator), finally I have given up and
not cleaned it. Anyway the bottom line to me would be that countM is
essentially as countA plus the map get/put calls. The significant
difference in performance seems to suggest that usage of the global map is
way more expensive than a pointer overwriting...

Anyway, I am far from sure it is as simple as that, honestly I am mainly
trying to cope with your request for clarifications but mine remains very
approximate feedback: in fact, in the meantime I have re-looked at SWI
Prolog's help on nb_setval/2, which is based on global variables, so maybe
not that different from your global map. I'd be interested in your
comments.

Julio


Julio Di Egidio

unread,
Nov 8, 2013, 8:56:03 PM11/8/13
to
<neng...@gmail.com> wrote in message
news:c04d490b-c729-4ad5...@googlegroups.com...

> Do you have an example that uses get_global_map() and that is slow? I'd be
> happy to take a look at it.

Besides performance, I have also been thinking that it would be very cool to
have non-backtracking "assignment" with a syntax as simple as a binary
operator, in fact similar to how you have introduced := for backtracking
"assignment". This, IMHO, would be quite valuable even if behind the scenes
the implementation were the same as it is at present: it is the simplicity
of code construction thanks to the built-in term rewriting that is very cool
in Picat, here as with foreach and other constructs.

I have been playing with Picat at night and week-ends for some 3 weeks, for
the most part solving puzzles (Picat's CLP is very easy to use, while for
some reason I always struggle with CLP in Prolog), but also solving a
non-trivial geometric problem (the two boards to cut and recompose into one:
this had appeared in sci.math at some point). In the meantime trying to
imaging how Picat would integrate and could interoperate into actual
production...

I may be speaking nonsense, anyway the good news is that I have no more
point to this list of "first impressions". :)

Thank you,

Julio


neng...@gmail.com

unread,
Nov 10, 2013, 7:55:03 PM11/10/13
to
Thanks for the program. I have improved the implementation of the global map. Your program runs more than twice as fast now. There is still room for improvement. Most part of the implementation is written in Picat. More speedups can be expected if part of the implementation is converted to C.

Cheers,
Neng-Fa

neng...@gmail.com

unread,
Nov 10, 2013, 8:07:26 PM11/10/13
to
With automatic dereference and automatic garbage collection, it's not easy to have such an operator for non-backtrackable updates, although I can see it's usefulness.

Another feature of Picat you may like is the planner. I have never seen any logic-based language that can solve planning problems as nicely as Picat. Take a look at the examples: http://picat-lang.org/projects.html. ASP will have a long way to go to compete with Picat on planning.

Cheers,
Neng-Fa

Wizard-Of-Oz

unread,
Dec 1, 2013, 7:40:37 AM12/1/13
to
This would be a mistake.

Wizard-Of-Oz

unread,
Dec 1, 2013, 7:44:17 AM12/1/13
to
Andy Valencia wrote:

> "Julio Di Egidio" <ju...@diegidio.name> writes:
>> IMHO, this Picat language is indeed very nice. For sure, I have
>> written more little programs in Picat in few days than I could write in
>> Prolog in weeks...
>
> Puh-leaze. Closed source? Register to request source? I don't install
> binary blobs from unknown people, and I don't spend time guessing at
> closed source binary blob behavior. That was OK in the 80's, and
> getting lame in the 90's. But in 2013? Really?

You just need to reverse engineer, is not really closed.

rupert...@googlemail.com

unread,
Jan 24, 2014, 3:55:50 AM1/24/14
to
On Thursday, December 6, 2012 10:05:50 PM UTC, Picat-lang.org wrote:
> We have completed the initial design of Picat, a new logic-based
> programming language.

Very nice, a couple of questions:

Are all variables in Picat logic variables? Can the compiler automatically detect when a variable does not need to be a full logic variable? I ask this because I think logic variables is the main thing that makes Prolog slow.

No operator overloading. Can new operators be defined at all? I find the ability to define infix operators useful in a DSL that has a more algebraic style.

Rupert

neng...@gmail.com

unread,
Jan 24, 2014, 10:04:36 AM1/24/14
to
All variables in Picat are logic variables(or mathematical variables), including variables on the left-hand sides of assignments. Automatic dereference makes logic variables a little slower to access than Van Neumann variables, but dereference chains are normally very short and, in a good implementation, this operation is combined with type-checking.

If your DSL happens to share the same tokens as Picat, then it's relatively easy to write a parser for your DSP in Picat. In my opinion, operator loading introduces more problems than it solves.

Cheers,
Neng-Fa

Joachim Schimpf

unread,
Jan 26, 2014, 10:41:48 AM1/26/14
to
On 24/01/2014 15:04, neng...@gmail.com wrote:
> All variables in Picat are logic variables(or mathematical variables),
> including variables on the left-hand sides of assignments.

Now, this is clearly not logical variable behaviour:

Picat> I=3, I:=I+1.
I = 4
yes

Picat> I=3, I:=I+1, I=3.
no


-- Joachim

neng...@gmail.com

unread,
Jan 26, 2014, 9:47:01 PM1/26/14
to
On Sunday, January 26, 2014 10:41:48 AM UTC-5, Joachim Schimpf wrote:
> On 24/01/2014 15:04, neng...@gmail.com wrote:

By "logic variables", I mean Prolog-style variables. The top-level query

Picat> I=3, I:=I+1.

is compiled to something like

Picat> I=3, I1 = I+1, print('I='), println(I1).

That's why you get the answer I=4.

The answer 'no' to the second query is expected, right?

Cheers,
Neng-Fa

rupert...@googlemail.com

unread,
Jan 27, 2014, 3:58:09 AM1/27/14
to
On Friday, January 24, 2014 3:04:36 PM UTC, neng...@gmail.com wrote:
> If your DSL happens to share the same tokens as Picat, then it's
> relatively easy to write a parser for your DSP in Picat. In my opinion,
> operator [over]loading introduces more problems than it solves.

Ok, just wasn't clear what you meant by no operator over-loading. I think over-loading means defining the same operator to do mean more than one thing, dependent on context. User defined operators, does not necessarily mean over-loading, that is, if the user can only define an operator to mean just one thing. Thanks.

Rupert

Jan Burse

unread,
Jan 27, 2014, 9:58:29 AM1/27/14
to
What could "logical" mean? Do we refer to first order
logic? Or would a reference to lambda calculus also
be allowed? I guess Picats:

X := E, S

Is usually found in imperative languages as:

X := E; S

And could also be the same as:

(lambda x.S) E

Or in Prolog that has call/n and with an appropriate
lambda library:

call(X\S,E).

And isn't logically equivalent to:

S; X := E

The picat docu says that if-then-else and loops are
compiled into auxiliary predicates, that carry around
the in and out variables.

But I guess it could be also done with some lambda
trickery.

Bye

neng...@gmail.com schrieb:

neng...@gmail.com

unread,
Jan 27, 2014, 12:22:33 PM1/27/14
to
> X := E; S
> And could also be the same as:
> (lambda x.S) E

This is an interesting translation. I guess you can also formalize the ':=' operator with monads. The good thing about ':=' is that many people who don't know lambda or monads already know the operator.

The ':=' operator is a double-edged sword. If used properly, it can be very powerful. Jut imagine how list comprehension could be implemented without this operator. On the other hand, overuse or misuse of this operator can produce messy codes. This will be a hot topic for many debates.

Cheers,
Neng-Fa

Joachim Schimpf

unread,
Jan 28, 2014, 6:59:52 AM1/28/14
to
On 27/01/2014 02:47, neng...@gmail.com wrote:
> On Sunday, January 26, 2014 10:41:48 AM UTC-5, Joachim Schimpf wrote:
>> On 24/01/2014 15:04, neng...@gmail.com wrote:
>
> By "logic variables", I mean Prolog-style variables. The top-level query
>
> Picat> I=3, I:=I+1.
>
> is compiled to something like
>
> Picat> I=3, I1 = I+1, print('I='), println(I1).

That is not a valid argument. Just because you choose to compile
into a language with logical variables does not mean your source
language has logical variables.

In Picat

I=3, I:=I+1, I=4.

it true. The removal of the (true) subgoal I:=I+1 leaves

I=3, I=4.

which now is false. Similarly, changing subgoal order gives

I=3, I=4, I:=I+1.

which is also false. So either:
- comma is not conjunction
- =/2 is not equality, or
- I is not a logical variable

I have no problem with you introducing nonlogical variables,
just don't call them something they are not.


-- Joachim

Jan Burse

unread,
Jan 28, 2014, 1:35:08 PM1/28/14
to
Hi,

I wonder very much about what counts as logical.
So sorry for stepping into the discussion.

Joachim Schimpf schrieb:
> I have no problem with you introducing nonlogical variables,
> just don't call them something they are not.

If I take:

X := E; S

As:

(lambda X.S) E

I would say X is still a logical variable. Although
not free in the full expression (lambda X.S) E, it is
bound by the lambda binder.

Otherwise I would say X behaves inside S as a free
logical variable, in inside E it should not alias with a
variable that is also named X.

Bye

P.S.: Here is some testing, using the Jekejeke
Minlog lambdas:

?- I = f(X,a), I = f(b,Y).
I = f(b,a),
X = b,
Y = a
?- I = f(b,Y), I = f(X,a).
I = f(b,a),
Y = a,
X = b
?- call(I\(I=f(X,a)),f(b,Y)).
X = b,
Y = a
?- call(I\(I=f(b,Y)),f(X,a)).
Y = a,
X = b

Or in Picat:

Picat> I = $f(X,a), I = $f(b,Y).
I = f(b,a)
X = b
Y = a
Picat> I = $f(b,Y), I = $f(X,a).
I = f(b,a)
Y = a
X = b
Picat> I := $f(X,a), I = $f(b,Y).
I = f(b,a)
X = b
Y = a
Picat> I := $f(b,Y), I = $f(X,a).
I = f(b,a)
Y = a
X = b


But somehow Picat seems to stretch the notion of
free variable. In my opinion it should show the I
value for the two last example above, at least under
the lambda interpretation.

I am speculating that Picat doesn't show the free
variables but the most inner variables in the
top-level. Take the following example:

Picat> I = $f(b,Y), I := $f(X,a).
I = f(_91b0,a)

And compare it with the Jekejeke Minlog lambdas:

?- I = f(b,Y), call(I\true,f(X,a)).
I = f(b,Y),
X = b

The Prolog lambdas do show the outer I and not
the inner I.

The above example shows also an error or restriction of
the current Prolog lambdas implementation. The bound I
and the outer I do alias, thats why we get X = b,
although we shouldn't.

The correct usage of the Prolog lambdas would require
a renaming of variables in the continuation so that there
is no clash between free and bound variables. The
correct call is then:

?- I = f(b,Y), call(J\true,f(X,a)).
I = f(b,Y),

So the Picat rewriting is still cool, we cannot
make the error from the previous query.

Bye

Jan Burse

unread,
Jan 28, 2014, 1:37:09 PM1/28/14