
\documentclass[12pt]{article}
\usepackage[T2A,OT1]{fontenc}
\usepackage[default]{cantarell}
\usepackage[a4paper, top=20mm, bottom=20mm, left=20mm, right=20mm]{geometry}
\usepackage[utf8]{inputenc}
\usepackage[russian, english]{babel}
\usepackage{tabu}
\usepackage{hyperref}
\usepackage{parskip}
\usepackage{graphicx}
\usepackage{tabularx}
\usepackage{float}
\floatstyle{boxed}
\restylefloat{figure}
\usepackage{setspace}
\onehalfspacing
\author{Artyom Bologov}
\date{\today}
\title{Explaining Wisp Without Parentheses}
\makeatletter
\def\endenv{\expandafter\end\expandafter{\@currenvir}}
\makeatother
\begin{document}
\maketitle

Many people—including even some Lispers!—dislike Lisp's
overabundance of parentheses—called P-WORD from now on.
Looking at
\href{https://www.reddit.com/r/lisp/comments/b2784p/is_there_a_word_for_that_fat_stack_of_parens_at/}{overly friendly tiger tails}
all day might be somewhat tiring.
Many Lisp programmers rely on indentation as a marker of code structure/nesting instead.
There's a niche for indentation-based syntax,
cleaner and more readable than all these P-WORD.

Enter Wisp.
\href{https://srfi.schemers.org/srfi-119/}{SRFI-119}, a Scheme Request for Implementation from 2015.
It's super minimalist with only two special syntax markers and indentation as the only nesting indicator.
It also supports the P-WORD syntax, so that one can always fall back to the comfort of regular Scheme.

One problem with Wisp, though—it's
defined in terms of P-WORD syntax.
It's not self-sufficient and only makes sense to the ones already into Lisp.
Wisp is not suitable for Lisp propaganda aiming at those disliking the P-WORD.
And that propaganda,
\href{https://youtu.be/cI1sltJMVuM?si=N5AP3yvzaTRX5MQc&t=1034}{according to Arne Babenhauserheide},
the author of SRFI-119, is one of the goals for the syntax.

This post tries to explain Wisp as a self-sufficient language.
No mention of the P-WORD.
Let's see whether it's even possible.

\section*{A Bit of Cheating: Blocks} \label{blocks}

P-WORD is a marker of s-expressions in Lisps.
So one needs an alternative word/concept for... everything Lisp has?
I suggest "block", as in Python blocks.
Blocks are numerous, almost everything in Wisp is blocks.
Blocks usually occupy a line of their own.
Procedure calls are blocks:
\begin{figure}[h!]\begin{verbatim}
procedure arg1 arg2
\end{verbatim}\caption{Procedure call as a block}\end{figure}


Procedure call might be split over multiple lines.
Arguments to the procedure—often blocks themselves—are marked by deeper indentation level:
\begin{figure}[h!]\begin{verbatim}
procedure arg
          another-procedure arg1 arg2
\end{verbatim}\caption{Procedure call as a multiline indented block}\end{figure}

Special forms with bodies are blocks too:
\begin{figure}[h!]\begin{verbatim}
begin
 procedure arg
 another-procedure arg1 arg2
\end{verbatim}\caption{Begin form as a nested multiline block}\end{figure}

Wisp concerns itself with blocks and how they wrap each other.
You'll see how both Wisp operators tie into this.

\section*{Period: No Blocks!} \label{period}

So I said that almost everything in Wisp is a block, didn't I?
Almost.
In case there's something that isn't a block, it needs to be delineated.

Say you want to return \verb|#t| from your function.
It's not a block, it calls no function.
That's why it must be marked with the period—to be returned verbatim:
\begin{figure}[h!]\begin{verbatim}
lambda :
  . #t
\end{verbatim}\caption{Returning a value instead of interpreting it as a block}\end{figure}

\section*{Inline Colon as an Application Marker} \label{inline-colon}

Colon is the second operator in Wisp, and it's also concerned with blocks.
But it has two different uses depending on where in the code it is found.
One of the uses is inline.
Colon between two things.
When positioned like that, the colon means nested procedure applications/block.
Making the right part up until newline an argument to the left part.
Something like Haskell \verb|$| operator.
Examples:
\begin{figure}[h!]\begin{verbatim}
;; display a sum of 1 and 2
display : + 1 2
;; display a sum of 1 with a difference of 2 and 3
display : + 1 : - 2 3
\end{verbatim}\caption{Examples of colon as procedure application operator}\end{figure}

You can also see inline colon in some special forms.
Procedure creation depends on colons, for example.
\begin{figure}[h!]\begin{verbatim}
define : a b c
  . #t
;; Equivalent
define a
  lambda : b c
    . #t
\end{verbatim}\caption{Defining/creating a new procedure using the inline colon}\end{figure}

It definitely is not a procedure application operator in this context.
But it's still used this way—as
a block that \verb|define| requires for procedure prototype.
Colon is a mere syntactic marker, not a semantic one.
You just need to memorize the use of the colon in \verb|define|/\verb|lambda|.
Much like in any language with syntax.

\section*{Leading Colon: Wrapping Block} \label{leading-colon}

Another use of the colon is the leading colon case.
It introduces a new block.
A new layer of nesting for things.
Even if the thing after it is a block—like procedure call—already.
It's useful for Scheme special forms
like \verb|let|:
\begin{figure}[h!]\begin{verbatim}
let
  :
    a 3
    b 4
;; Or the form I like more
let
  : a 3
    b 4
\end{verbatim}\caption{Use of the leading colon in let-bindings}\end{figure}

Both of the cases above involve multi-line blocks.
The indentation makes both lines a part of the colon-introduced block.
But what if the leading colon doesn't wrap multiple lines?
What if there are no lines indented below it?
Then it just wraps whatever follows:
\begin{figure}[h!]\begin{verbatim}
do
  ;; Using inline colon for procedure application too
  : i 0 : + 1 i
  : = 10 i
 display i
;; 0123456789
\end{verbatim}\caption{Use of the leading colon in do}\end{figure}

The only use for the leading colon is macros, really.
There are not a lot of macros in Scheme, so you can easily memorize the patterns.
Like with \verb|lambda|, \verb|define|, \verb|let|, and \verb|do|.

\section*{Curly-infix Notation} \label{curly-infix}

We've got rid of
P-WORD, but what about prefix math?
It hurts.
Any way to replace it with something more intuitive/familiar?
\href{https://srfi.schemers.org/srfi-105/}{Like SRFI-105}, curly-infix expressions.

Wisp SRFI requires curly-infix expressions as part of the dialect.
So one can freely do
\begin{figure}[h!]\begin{verbatim}
display {1 + 2}
\end{verbatim}\caption{Use of curly-infix expression in Wisp}\end{figure}

Missed weird precedence rules and duplicated signs?
Here you go!

\section*{Applying The Takeaways} \label{applying}

\begin{itemize}\item Blocks are mere lines.
\item  Blocks can be nested, with inner blocks indented deeper than the outer block.
\item  Non-blocks should be marked with the period \verb|.|.
\item  Blocks can be nested inline with the colon \verb|:|.
\item  Blocks can be wrapped in the extra block with the colon too. It's usually important for macros.
\item  Curly-infix notation should be available on Wisp systems too.
\end{itemize}

How about applying it to the ultimate syntactic monstrosity, \verb|case-lambda|?
\begin{figure}[h!]\begin{verbatim}
define my-plus
 case-lambda
  ;; Wrapping the thing into a block.
  : a
    ;; Returning the value verbatim
    . a
  : a b
    ;; Curly-infix use
    {a + b}
  : a b c
    ;; Inline colon use
    + a : + b c
  : a b . rest
    ;; A multiline procedure application
    apply + a b
          . rest
\end{verbatim}\caption{case-lambda in Wisp}\end{figure}

I like how it looks!
Despite inconsistencies and being absolutely useless, of course.
An ultimate test and result of our newly acquired understanding of Wisp!

The whole reason for me exploring Wisp is the news of it being
\href{https://www.gnu.org/software/guile/news/gnu-guile-3010-released.html}{added to Guile 3.0.10}!
\href{https://www.gnu.org/software/guile/manual/html_node/SRFI_002d119.html}{The manual section is quite frugal, though}.
So let this post be an introduction to Wisp syntax,
with the added benefit of self-sufficiency and absence of paren... the P-WORD, sorry.
Go try Wisp, you might end up liking it as much as I did!

P.S. I was irritated by Guix not shipping Guile 3.0.10 for so long.
And using the SRFI-provided parser (either Python or Guile-specific one) wasn't cool.
So I made my own... as an \verb|ed| script.
Find it at \href{scripts/wisp.ed}{scripts/wisp.ed}!
It produces correct results in 90% of cases and works everywhere \verb|ed| does.
So... Can I call it the most portable Wisp implementation?

\par\noindent\rule{\textwidth}{0.4pt}
Copyright 2022-2025 Artyom Bologov (aartaka).
Any and all opinions listed here are my own and not representative of my employers; future, past and present.

\end{document}
