On Sat, May 17, 2025 at 3:54 PM Eric Blake <ebl...@redhat.com> wrote:
>
> On Sat, May 17, 2025 at 12:07:40PM -0400, Nikolaos Chatzikonstantinou wrote:
> >
> > I wonder if a plugin system that extends the language is a potential
> > idea to explore. It could transform certain slower native m4 functions
> > to e.g. Python or Scheme functions (because I'm considering rewriting
> > this in Guile one day... I do not know what compels me to always think
> > of reimplementing stuff). Of course m4-native functions can always be
> > written since m4 is Turing complete, but they may be inefficient.
>
> In fact, branch-2.0 in m4.git does just that - it has experimental
> code to allow loadable modules, where you can write new builtins in
> any language, and as long as the .so fits the ABI that m4 expects,
> dynamically expand the language at runtime.  The problem is that it
> has been years since anyone has tried to work on that branch (even
> longer than what has gone into branch-1.6).  What's more, there are so
> few m4 programmers out there that you are going to have a hard time
> convincing anyone to use a faster m4 with plugin modules, when they
> can just use a faster language with more community knowledge from the
> get-go.
>
> And speaking of Turing complete, Doug McIlroy has an interesting demo
> at how not only is m4 Turing complete with all of its builtins, but if
> you strip it down to JUST the define macro, it is still Turing
> complete:
>
> https://www.tuhs.org/mailman3/hyperkitty/list/t...@tuhs.org/thread/7ZRYUMZ2QNKE24QWUFT7MRK74COT7BIQ/

I only briefly skimmed over it, it has some cool techniques. They
definitely went the academic route to prove this by creating a model
for arithmetic. I prefer the hand-wavy route: m4 is turing complete
merely by supporting syscmd(). I want to share my own m4 code that I
wrote when I studied m4 to fix issues with Guile's Autotools macros
(haven't gotten around to that yet) Once I managed to implement lambda
functions in a language that didn't originally support them I was
pretty convinced of its coolness. I also managed to cram in currying,
in a way completing a challenge mentioned by Kenneth J. Turner in
"Exploiting the m4 Macro Language":

> Unfortunately a single Curry macro cannot be defined since the number of 
> parameters to be fixed must be known.

I amused the author by e-mailing him my solution. M4 has enough
syntactic manipulation power that you can implement a lot of
functional programming in it, like foldr and so on. I actually think
it's a good tool to teach syntactic manipulation to talented students,
*especially* if we can get an IDE (debugger?) around it, that shows
all the steps of expansion. Of course debugmode() can do this, but
it's a bit more technical than I'd like it to be.

--- m4 source, cut here ---

define(apply,`ifelse($1,`',`',$1(shift($@)))')

define(id, $@)
define(
  peel,
  `ifelse(eval($1 == 0),1,`id(``$2'')',eval($1 ==
1),1,`id(`$2')',`peel(decr($1),$2)')')

define(
  randhex,
  `esyscmd(`od -N$1 -An -tx1 /dev/urandom | tr -d " \n"')')

define(
  lambda__aux,
  `define($1,$2)`$1'')

define(
  lambda,
  `peel(3,``lambda__aux('lambda_``''`randhex(5), ``$1'')'')')

# curry(f,arg1,...,argn)
# Partially applies arg1, ..., argn to f.
# Note that there must be at least one argument, i.e. n >= 1.
define(
  curry,
  `lambda(`$1(shift($@),'$`'@`)')')

--- m4 source, cut here ---

Reply via email to