Arc Forumnew | comments | leaders | submitlogin
2 points by Pauan 2028 days ago | link | parent

"Are they first-class in Nulan?"

They might be, once I make them user-customizable. At least, as "first-class" as macros.

---

"If not, I was thinking aloud that Nulan's parser might be able to subsume patterns somehow"

Well, the way I designed it, Nulan's parser is stand-alone: you can run it without any of the other Nulan stuff.

That's because the parser is really very simple. It's only concerned about lists, symbols, numbers, and strings. It has no knowledge of boxes, or macros, or anything like that.

This is by design. Although it would be possible to integrate the parser more closely into Nulan, I like the clean separation of concerns.

Patterns are currently executed during the macro expansion phase, so that's already long after the parser has run. In addition, while the parser operates everywhere, patterns can only be used in certain places.

How they work is pretty simple. Using the not-yet-created $pattern-rule macro:

  $pattern-rule foo -> {_ pat} val body
    'val + pat + body
Let's look at this program:

  (-> (foo 5) 10) 20
We're creating a function "-> (foo 5) 10" and then calling it with the argument 20.

Now, it will call the "foo" pattern with the following arguments: (foo 5), a unique variable, and 10. These represent the pattern, the argument to the function, and the body, respectively. Whatever the pattern returns is used as the body of the function.

After running the pattern, the end result is this:

  (-> u (u + 5 + 10)) 20
Let's look at another custom pattern:

  $pattern-rule and -> {_ @pat} val body
    pat.reduce
      -> x y
        pattern-match y val x
      body
This time we're calling the "pattern-match" function, which allows the pattern matching to be recursive.

Using this system, it's easy to do, for instance, list destructuring:

  $pattern-rule list -> {_ @pat} val body
    w/box i = -1
      pat.reduce
        -> x y
          pattern-match y ('val[,(++ i)]) x
        body
And now this program:

  -> (list a b c)
    prn a b c
Will get translated into this:

  -> u
    | box a = u.0
    | box b = u.1
    | box c = u.2
    | prn a b c
Though, the above "list" pattern doesn't support the @ splicing syntax, which is much more complicated to implement.