Nim Nuggets: Nim talk at Strange Loop 2021

jfondren julian.fondren at gmail.com
Sun Oct 17 11:10:16 UTC 2021


On Sunday, 17 October 2021 at 05:26:25 UTC, Araq wrote:
> On Sunday, 17 October 2021 at 04:17:38 UTC, jfondren wrote:
>> https://www.youtube.com/watch?v=d2VRuZo2pdA
>>
>> About 50% of it is inadvertent praise for D. The rest is ARC 
>> and C++ interop.
>
> Ha, good one. So where is D's hygienic AST macro system that 
> lets you reflect over types? No, string mixins and experimental 
> std.reflection in some offside branch don't count.

I like how Andrei talks about mixin in 
https://youtu.be/WsgW4HJXEAg?t=3354

"and like an idiot you get to put a string in and give it to the 
compiler to compile for you. Which sounds ridiculous, right?", 
while the slide adds that this "isn't glamorous".

But in Common Lisp you are also "like an idiot, putting a list in 
and giving it to the compiler to compile for you". Lists have 
structure but a typical macro is heavy on quoting and you can 
read the quoted parts to understand what the resulting code would 
look like. The 'code' of macros, the parts that aren't quoted but 
are doing work like constructing lists or modifying them, are 
generally also perfectly normal Common Lisp code, they just 
happen to be constructing lists of code rather than lists of 
numbers or strings.

If you want to write or maintain a simple macro in Common Lisp, 
you don't need specialized knowledge: it is enough to know Common 
Lisp.

What Nim has is more like browser DOM manipulation: knowing Nim 
is not enough, either to write a macro or maintain a macro. You 
must also know have copious specialized macro knowledge about 
nnkSmthng and nnkSmthngElseTy. The 'easy' way to approach Nim 
macros is to perform the equivalent of opening a browser's 
developer inspection tool on the desired Nim code.

Common Lisp's macros scale from absolutely trivial

```lisp
(defmacro sleep-units (value unit)
   `(sleep
      (* ,value
         ,(case unit
            ((s) 1)
            ((m) 60)
            ((h) 3600)
            ((d) 86400)
            ((ms) 1/1000)
            ((us) 1/1000000)))))
```

to whatever this is: 
https://github.com/thephoeron/let-over-lambda/blob/master/let-over-lambda.lisp#L356

For trivial cases, Nim has templates. Why? Why not remove 
templates from the language and tell people to use macros for 
trivial cases as well?

Or suppose that during a presentation this code were put on the 
screen:

```d
struct Object {
     float[2] position, velocity, facing;
     float size;
}

struct Player {
     mixin parent!Object;
     int hp;
}

mixin template parent(Struct) {
     static foreach (i, alias f; Struct.tupleof) {
         mixin("typeof(f) ", __traits(identifier, f), " = 
Struct.init.tupleof[i];");
     }
}

void main() {
     import std.stdio : writeln;

     writeln(Player([0, 0], [0, 0], [0, -1], 5.0, 100));
}
```

I could say "as you can see, I'm looping here over the members of 
the given struct, and am injecting new field definitions that 
have the same types, names, and initial values that the struct 
has." And the "as you can see" would be literal, not ironic. 
People really can look at that mixin and see what it does.

Do you think deech could've said something like that about 
https://github.com/deech/NimNuggets/blob/master/backup/migrationmacros.nim#L11 ? Do you think including that code in his presentation would've done more or less to sell Nim to the audience?

Nim macros are more capable than string mixins, but Nim's 
metaprogramming story is really not that enviable.


More information about the Digitalmars-d mailing list