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

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

Top comments (0)

Imagine monitoring actually built for developers

Billboard image

Join Vercel, CrowdStrike, and thousands of other teams that trust Checkly to streamline monitor creation and configuration with Monitoring as Code.

Start Monitoring

👋 Kindness is contagious

Dive into an ocean of knowledge with this thought-provoking post, revered deeply within the supportive DEV Community. Developers of all levels are welcome to join and enhance our collective intelligence.

Saying a simple "thank you" can brighten someone's day. Share your gratitude in the comments below!

On DEV, sharing ideas eases our path and fortifies our community connections. Found this helpful? Sending a quick thanks to the author can be profoundly valued.

Okay