Discussions related to Visual Prolog
larryhoughton
Posts: 11
Joined: 4 Oct 2016 21:16

Extending the sample Visual Prolog sample Calendar code to use FACTS

Unread post by larryhoughton »

Hello,
I'm trying to extend the sample Visual Prolog sample Calendar code to use FACTS instead of creating the Calendar "Event" data within the code (i.e. hard coded Calendar Events).

I'm looking for guidance on the best Prolog coding strategy (i.e. commands) to make the Calendar sample code read Calendar Event data from a set of Prolog Facts. Later I'll be pulling the Facts from a MS SQL Server DB. Ideally I would want to separate the data retrieval code out to another class as the Family4 sample code explains.

The way that I'd like to create the json object (see my code below) is syntactically incorrect and all my attempts to make it syntactically correct produce a cornucopia of other errors that I'm sure would be easy to fix if I knew what I was doing.

Errors such as:
  • A foreach loop must be a Procedure (so you can't retrieve Facts within the Foreach)
    My json Value isn't compatible with my json Object (Probably something to do with the 'o' in the sample code that I can't figure out to recreate in my code)
    Struggles with keeping my Procedure/Determ/Nondeterm constrictions all in alignment
So long story short, I could really use some help. What would be the best way to modify the Calendar Sample Code to read "Events" from a set of Facts and still produce the json object for the website to retrieve?
Thanks for your patients...

Original Calendar Sample Code Snippet (Which I want to modify to use FACTS)

Code: Select all

predicates     calendar : jsonProc_name.  clauses     calendar(_Context, ArgMap) = o(Result) :- % Where 'o' is defined and what it is does is a separate mystery to me.         Result = jsonObject::new(),         Email = ArgMap:get_string("emailaddr"),         MyEvents = [            o(mkEvent("Lunch",  mkTime(1, 11, 15), mkTime(1, 14, 45),"30"),true),            o(mkEvent("Dinner", mkTime(-1, 10, 30),mkTime(2, 11, 00),"40"),true)         ],         Result:set_array("events", MyEvents).
My failing "getEvents()" code
Below is the simplest representation of the code that I wish would work. However it cannot work as written because it is syntactically incorrect and I'm pretty sure I need some help with json Values Vs json Objects syntax.

Code: Select all

predicates     getEvents : () -> jsonObject V. clauses getEvents() = (Result) :-         Result=jsonObject::new(),         MyEvents = [            foreach events(Title, Start, End, Resource,AllDay) do                 V=mkEvent(Title, Start,End, Resource,AllDay)         end foreach]
Everything below here is for reference only

"initEventFacts()"
Creates the Facts to Read (this works fine)

Code: Select all

predicates     initEventFacts : (). clauses initEventFacts():- % Save two Facts (This clause is working fine)    assert(events("My Facts Row 1", mkTime(1, 11, 15), mkTime(1, 14, 45),"30",true)),    assert(events("My Facts Row 2", mkTime(-1, 10, 30),mkTime(2, 11, 00),"40",true)).  
"MkEvent Code"
Unmodified Calendar Sample Code (used by me above and the original sample code)

Code: Select all

predicates     mkEvent : (string Title, string Start, string End, string Resource, boolean AllDay)  -> jsonObject V. clauses     mkEvent(Title, Start, End, Resource, AllDay) = V :-         V = jsonObject::new(),         V:set_string("title", Title),         V:set_string("start", Start),         V:set_string("end", End),         V:set_string("resource", Resource),         V:set_boolean("allDay", AllDay).
User avatar
Thomas Linder Puls
VIP Member
Posts: 1398
Joined: 28 Feb 2000 0:01

Unread post by Thomas Linder Puls »

Let us start with the 'o'. It comes from the domain json::jsonValue (here with an extended domain description):

Code: Select all

class json ... domains     jsonValue =         n;         f;         t;         r(real Number);         s(string String);         a(jsonValue* Array);         o(jsonObject Object) [presenter(presenter_jsonValue)].     % @short Represent the JSON values corresponding to the ECMA 404 standard.<br>     % n - the JSON constant null<br>     % f - the  JSON constant false<br>     % t - the  JSON constant true<br>     % r(Number) - a JSON number<br>     % s(String) - a JSON string String<br>     % a(Array) - a JSON array as a list <br>     % o(Object) - a JSON object<br>     % See also http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf     % @end ...
See also As you can see a JSON value is one of 7 things, a JSON object being one of them. A JSON object is represented by a jsonObject and packed in the json::o functor in our representation.

regarding 'foreach'. foreach does not produce any value(s), what you need is a list comprehension which produces a list from a nondeterministic iteration:

Code: Select all

MyEvents = [ mkEvent(Title, Start,End, Resource,AllDay) || events(Title, Start, End, Resource, AllDay) ]
However, I think it you should avoid/minimize data caching in your application. I.e. instead of loading data into facts and then serve them from the facts, you should rather serve them directly from the database. The layer structure from the family4 example is a good idea. Your Web service layer will use with a business layer which will use a data layer which will use the SQL database.

Code: Select all

class myCalendarWebService : rpcService   constructors     new : (myCalendarBL CalendarBL).   end class myCalanderWebService     implement myCalendarWebService inherits jsonRpcServiceSupport   facts     calendarBL : myCalendarBL.   clauses     new(CalendarBL) :-         calendarBL := CalendarBL,         setProc_name("calendar", calendar).   class predicates     calendar : jsonProc_name. clauses     calendar(_Context, ArgMap) = o(Result) :-         Email = ArgMap:get_string("emailaddr"),         Events = calendarBL:getEvents_email(Email),         Result = jsonObject::new(),         EventsJson = [ mkJsonEvent(E) || E in Events ], % transform prolog events to JSON events         Result:set_array("events", Events).   ....        
Regards Thomas Linder Puls
PDC
larryhoughton
Posts: 11
Joined: 4 Oct 2016 21:16

Unread post by larryhoughton »

Okay, I've conquered my aforementioned json 'o' and Procedure issues with your help, thank you. And I have the sample ODBC code working with an MS SQL DB. What I can't put together now is how the results from an SQL query become available for goal processing. That is, with a Fact I can simply resolve all of the Events with something like:

Code: Select all

events(Title,StartTime,EndTime,Resource) % Where none of the variables are bound
And with a Fact, I can do backtracking and all the things that make Prolog great.
With SQL I can retrieve the same fields with something like:

Code: Select all

Select Title,StartTime,EndTime,Resource from Events
But how do I retrieve the data in such a way that I can use Prolog logic like backtracking, etc?, For reference, up to now I thought the answer was to retrieve the field data with SQL and assert it into Facts.

For future readers of this thread, here are the modifications I made to the Calendar sample code to use Facts ....
The big breakthrough was using the suggestion (see this thread) to stop using the foreach loop and instead use list comprehension:

Code: Select all

MyEvents = [ mkEvent(Title, Start,End, Resource,AllDay) || events(Title, Start, End, Resource, AllDay) ]
My version only deals with the one type of Event (shown above).

Code: Select all

predicates     calendar : jsonProc_name. clauses     calendar(_Context, ArgMap) = o(Result) :-     Result= mkEvent(). % Removed everything else for my test   predicates    mkEvent : () -> jsonObject V. clauses % Creates a new class object "MyEventData"     mkEvent() = V :-     MyEventData=data::new(),     MyEventData:initEventFacts(),  %  Asserts some Event Facts     V=MyEventData:getEvents().    % Retrieves the Event Facts into "V" a json object   /* Retrieves all of the Events from the asserted Facts */ predicates     getEvents : () -> jsonObject V.  getEvents() = Result :-         Result=jsonObject::new(),         MyEvents = [ o(mkEvent(Title, Start,End, Resource,AllDay)) || events(Title, Start, End, Resource, AllDay) ], % This command loads up all of the Events into an Array "MyEvents".  Note the 'o' before mkEvent         Result:set_array("events", MyEvents),         R30 = mkResource("30", "Facts DB Larry"),         R30:set_string("email", "SomeEmail@cox.net"),         Result:set_array("resources", [o(R30)]).
Post Reply