I'm looking for a more elegant way to solve the problem

I’m making wrappers over rest api methods. my code represents similar pieces of code. I’m looking for a generalized method to wrap a rest api

'crm.lead.update'(conf(AccessToken, ClientEndpoint), Fields, Reply) :-
    bitrix24_auth:check_token,
    format(atom(Url), '~w~w', [ClientEndpoint, 'crm.lead.update']),
    bearer(AccessToken, Bearer),
    bitrix24_request:post(Url,
         json(
                  Fields
         ),
         Reply,
         [Bearer, status_code(StatusCode)]),
    (200 == StatusCode
        ->
            memberchk(result= @(true), Reply)
        ;   debug(http(error), 'error ~q', [Reply])
     ).

This code is repeated for all API methods. I’m looking for a way to get rid of this repetition. What if there is a way to write a generalized predicate?

Why wouldn’t there be?

Could add another variable to indicate success/failure of the generalized predicate, as an argument.

There’s specifics of how you want to handle failure, debugging info, errors raised, etc.

I don’t want to constantly write in code ‘crm.method1’() ‘crm.method2’() ‘crm.methodn’ I will have to wrap all the APIs in my code, how can I transform the call ‘crm.method’ into call (MethodName , args …). if there is no method call will simply fail

Is this what you want? call/2

But this will throw an error if the predicate doesn’t exist; you can either set the unknown flag appropriately (see current_prolog_flag/2) or you can wrap it:

catch(call(C,...), error(existence_error(procedure,_),_), fail)

Can use term_expansion/2 to make it elegant.

Kinda-relevant example: prolog - What would be an elegant/idiomatic way to introduce a predicte on a list of atoms? - Stack Overflow

no, that’s not what I want. Making a wrapper for a third-party rest api is a tedious task. I need a way to write to call ‘rest method’ (args …) in my program code:- predicat('rest method ', args …) I don’t want to implement every third-party rest api method. I need some syntactic sugar for this. I could do function_post(Method Rest Api , args ) :- http_client:post() and it works, but I would like to explicitly write ‘Method Rest Api’( in the code. If I explicitly implement each method, it’s a lot of boilerplate code. Explained how could I

Perhaps you can write down for us in pseudo-code what an ideal result would look like for you? That’d help to make the suggestions more relevant.

How do you solve the boilerplate problem?

I want to get rid of this code.

'crm.lead.update'(conf(AccessToken, ClientEndpoint), Id, Fields) :-
    bitrix24_auth:check_token,
    format(atom(Url), '~w~w', [ClientEndpoint, 'crm.lead.update']),
    bearer(AccessToken, Bearer),
    bitrix24_request:post(Url,
         json(
             json([
                         id = Id,
                         fields = Fields])
         ),
         Reply,
         [Bearer, status_code(StatusCode)]),
    (200 == StatusCode
        ->
            memberchk(result= @(true), Reply)
        ;   debug(http(error), 'error ~q', [Reply])
     ).

'crm.lead.get'(conf(AccessToken, ClientEndpoint), Id, Reply) :-
    bitrix24_auth:check_token,
    format(atom(Url), '~w~w', [ClientEndpoint, 'crm.lead.get.json']),
    bearer(AccessToken, Bearer),
    bitrix24_request:post(Url,
         json(
             json([
                         id = Id
                     ])
         ),
         Reply,
         [Bearer]).

'crm.lead.list'(conf(AccessToken, ClientEndpoint), Body, Reply) :-
    bitrix24_auth:check_token,
    format(atom(Url), '~w~w', [ClientEndpoint, 'crm.lead.list.json']),
    bearer(AccessToken, Bearer),
    bitrix24_request:post(Url,
         Body,
         Reply,
         [Bearer]).

'crm.lead.productrows.get'(conf(AccessToken, ClientEndpoint), Body, Reply) :-
    bitrix24_auth:check_token,
    format(atom(Url), '~w~w', [ClientEndpoint, 'crm.lead.productrows.get.json']),
    bearer(AccessToken, Bearer),
    bitrix24_request:post(Url,
                          Body,
                          Reply,
                          [Bearer]).

this is how I imagine it

Method(conf(AccessToken, ClientEndpoint), Id, Fields) :- call_method(Method, conf(AccessToken, ClientEndpoint), Id, Fields).

By writing a program to create your predicates. Simple example:

?- assert(mytest(X,Y) :- b(Y,X)).
true.

?- listing(mytest).
:- dynamic mytest/2.

mytest(A, B) :-
    b(B, A).

Could this help you?

1 Like