DEV Community

Gilbert for The Clause

Posted on • Edited on

3 2

A Nicer if-then-else Syntax in Prolog

Prolog has an amazing syntax, thanks to it both being homoiconic and supporting custom operators. However, writing conditionals in Prolog is often a drag.

Fortunately, we don't have to convince or wait for Prolog implementations to implement a nicer syntax. Instead, we can create our own if-else syntax today!

Example Usage

%%
%% Before
%%
foo(X) :-
  (
    X > 50 ->
    Y is X * 2,
    bar(X, blah)
  ; baz(10, 20)
  ),
  last(X).

%%
%% After
%%
foo(X) :-
  if (X > 50) then (
    Y is X * 2,
    bar(X, blah)
  )
  else (
    baz(10, 20)
  ),
  last(X).

%%
%% Before
%%
shorter_foo(X) :- (X > 10 -> bar(X); baz(X)).

%%
%% After
%%
shorter_foo(X) :- if X > 10 then bar(X) else baz(X).
Enter fullscreen mode Exit fullscreen mode

Example Usage (or operator)

I also threw in a bonus or operator so you can do "or" logic without introducing additional choice points, and not have to worry about catching multiple terms (due to it having a stronger precedence than the comma , operator):

%%
%% Before
%%
multi_foo(X, Y) :- (foo(X), !; bar(Y)).

%%
%% After
%%
multi_foo(X) :- foo(X) or bar(Y).

%%
%% Before
%%
multi_foo(X, Y) :-
  ((foo(X), !; bar(X)) ->
    Y = true
  ; Y = false
  ).

%%
%% After
%%
multi_foo(X) :-
  if (foo(X) or bar(X)) then (
    Y = true
  )
  else (
    Y = false
  ).
Enter fullscreen mode Exit fullscreen mode

The Code

Here's the code you can copy/paste into your own project to make use of this sweet, sweet syntax.

There may even be a better way using term_expansion. If you find one, leave it in the comments!

:- op(990, fx, if).
:- op(985, yfx, then).
:- op(985, yfx, else).
:- op(985, yfx, elseif).
:- op(800, xfx, or).

if(X) :- (if_then(X, Then) -> call(Then); true).

if_then(then(elseif(Try, Cond), MaybeThen), Then) :-
  !,
  (if_then(Try, Then) -> true; call(Cond), Then = MaybeThen).

if_then(then(Cond, Then), Then)  :-
  !,
  call(Cond).

if_then(else(Try, MaybeThen), Then) :-
  !,
  (if_then(Try, Then) -> true; Then = MaybeThen).

or(X,Y) :- call(X) -> true; call(Y).
Enter fullscreen mode Exit fullscreen mode

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read more →

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay