Reputation: 85
I have a simple rule in SWI-Prolog which I want to implement in an AWS Lambda function.
I will receive an Event in the following json
form:
{
"key1": "value1",
"key2": "value2",
"key3": "value3"
}
My problem is that I can only read from atom-like
arrays or json files but not plain json
in a compound
form.
What I would like to do is something like this:
lambda_handler(Event, Context, Response) :-
atom_json_dict(Event, Dict, []),
my_simple_rule(Dict.key1, Dict.key2, Dict.key3),
Response = '{"result": "yes"}'.
my_simple_rule
is a condition which returns true or false depending on the values passed.
What I've tried so far does not work because SWI-Prolog expects either a Stream o a String when using atom_json_term/3, json_read/2,3 or json_read_dict/2,3.
I also tried to force the JSON into a string this way:
format(atom(A), "~w", {"key1": "value1", "key2": "value2", "key3":"value3"}).
Expecting this so that I can then convert it to a Term
(Prolog dict):
{"key1": "value1", "key2": "value2", "key3":"value3"}
But the result is the following:
'{key1:value1,key2:value2,key3:value3}'
Which fails.
Does any one know how I can use a plain JSON within Prolog?
Upvotes: 1
Views: 378
Reputation: 85
So... I was wrong about how SWI-Prolog handles the Event json
in Lambda, so I will post my findings here in case someone encounters a similar challenge.
At first I though that the Event json
arrived like this: {"key1": 1, "key2": 2, "key3": 3}
.
However, it looks a little more like this: json([key1=1, key2=2, key3=3]
. Which makes the parsing task different.
To solve it I used the following code which I hope will be self explanatory:
:- use_module(library(http/json)).
:- use_module(library(http/json_convert)).
% use this to test locally. If it works this way i should work in lambda:
handler(json([key1=10, key2=2, key3=3]), _, Response).
% Function handler
handler(json(Event), _, Response) :-
json_to_prolog(json(Event), Json_term), % I transform the event json into a prolog term
atom_json_term(A, Json_term, []), % I convert the JSON_term into an atom
atom_json_dict(A, Dicty, []), % I convert the atom into a dict
my_simple_function(Dicty.key1, Dicty.key2, Dicty.key3, Result), % Function evaluation
json_to_prolog(json([result_key1="some_message", result_key2=Result]), Result_json), % Transform json term into actual json
atom_json_term(Response, Result_json, []). % Transform json into atom so that lambda does not complain
my_simple_function(N1, N2, N3, Result) :-
Result is N1 + N2 + N3.
The input needed (your test json
in lambda) would be:
{
"key1": 1,
"key2": 2,
"key3": 3
}
While the output should look like this:
{
"result_key1": "some_message",
"result_key2": 6
}
I hope this works as a template to use SWI-Prolog on AWS.
By the way, I recommend you take a look to this repository to make your custom Prolog runtime for Lambda.
Upvotes: 0
Reputation: 60004
Event
it's already a structured term, so here is an 'ad hoc' adapter.
Let's say we have a file j2d.pl
containing
:- module(j2d,
[ j2d/2
]).
j2d(Event,Dict) :-
Event={CommaSequence},
l2d(CommaSequence,_{},Dict).
l2d((A,R),D,U) :- !, updd(A,D,V), l2d(R,V,U).
l2d(A,D,U) :- updd(A,D,U).
updd(K:V,D,U) :- atom_string(A,K), put_dict(A,D,V,U).
then it's possible to test the code from the SWI-Prolog console:
?- use_module(j2d).
true.
?- Event={
"key1": "value1",
"key2": "value2",
"key3": "value3"
}.
Event = {"key1":"value1", "key2":"value2", "key3":"value3"}.
?- j2d($Event,Dict).
Dict = _14542{key1:"value1", key2:"value2", key3:"value3"},
Event = {"key1":"value1", "key2":"value2", "key3":"value3"}.
The unusual $Event
syntax it's an utility of the console (a.k.a REPL), that replaces the variable Event
with its last value (a.k.a binding).
Your code could become
:- use_module(j2d).
lambda_handler(Event, Context, Response) :-
j2d(Event,Dict),
my_simple_rule(Dict.key1, Dict.key2, Dict.key3),
Response = '{"result": "yes"}'.
Upvotes: 2