Hacker Timesnew | past | comments | ask | show | jobs | submitlogin

Macros can provide a lot of syntactic convenience over those first-class functions, especially with heavily nested structures. For example, I can replace this monadic parser definition...

    function SpecDeclP()Parser{
      return Bind(SeqRight(MyKeywordP, IdentifierP), function(nm interface{})Parser{
        return Bind(BetweenParensP(IdentifierP), function(parm interface{})Parser{
          return Bind(SetSwitchUserStateP, function(_ interface{})Parser{
            return Bind(BlockP, function(bod interface{})Parser{
              return Result("func " + nm.(string) + "(" + parm.(string) + ")" + bod.(string))
            })
          })
        })
      })
    }
...with this more readable version if I have a recursively defined "macro" called doparse...

    doparse{
      nm   <- SeqRight(MyKeywordP, IdentifierP)
      parm <- BetweenParensP(IdentifierP)
      SetSwitchUserStateP
      bod  <- BlockP
      Result("func " + nm.(string) + "(" + parm.(string) + ")" + bod.(string))
    }
This requirement arose in Haskell for its Parsec before it became a part of the syntax, then again later with the Arrow library which later also added it to the syntax. Whenever new abstractions are discovered/created, a macroing facility, whether for lisp-like syntax or some other, helps makes all the nested functions more readable.


I'm fairly sure that Haskell had do notation before Parsec.




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: