MacroUse - vilinski/nemerle GitHub Wiki

The most interesting features we implemented using macros

Table of Contents

Introduction

This page is dedicated to the features of Nemerle and its library, which have been implemented using our meta-programming facilities.

Understanding how macros work is not necessary for using any of them. It would be useful only for knowing that those examples are just a tip of an iceberg called meta-programming and that you can easily implement even nicer things.

Please refer to class library documentation for a reference list of implemented macros.

Design by contract

Languages like Eiffel or Spec# incorporate a methodology called Design by Contract to reason about programs, libraries, methods. It allows to write more secure and correct software and specify its behavior.

A quick example below shows how it looks in Nemerle with its syntax extensions. Note that the invariant, requires and ensures syntax is added to the scope by opening Nemerle.Assertions namespace containing design by contract macros.

using Nemerle.Assertions;

class BeerControl 
invariant m_temperature <= 6.0
{
  public DrinkUsingAStraw (how_much : float) : void
  requires how_much > 0.0
  {
    m_amount -= how_much
  }

  public DissipationHandler () : void
  ensures m_amount > 0.0
  {
    when (AReallySmallNumber < m_amount) {
      m_temperature += (Room.Temperature - m_temperature) / 100.0;
      m_amount -= 0.1; // loss due to the evaporation
    }
  }
  
  private mutable m_temperature : float;
  private mutable m_amount : float;
}

See here for more...

Compile-time validation of embedded languages

In many programming tasks there is a need for using domain-specific languages for performing some specialized operations. The examples are regular expressions used for searching and matching parts of text, formatting strings of printf function or SQL for obtaining data from database. All those languages have their own syntax and validity rules.

Most of DSLs are used inside a general-purpose language by embedding programs written in them into strings. For example, to query a database about elements in some table, one writes an SQL statement and sends it to the database provider as a string. The common problem with this approach is verifying correctness of embedded programs - if the syntax is valid, if types of the variables used match, etc. Unfortunately, in most cases all those checks are performed at runtime, when a particular program is expected to execute, but fails with a syntax or invalid cast error.

All this happen, because the compiler of our general-purpose language treats DSL programs just as common strings. It is not surprising though - it was not designed to verify any particular domain-specific language - but it would be nice to do it before runtime. In Nemerle we can use macros to handle some of the strings in a special way - for example run a verification function against them.

This mechanism is very general and it is used in some parts of Nemerle standard library (like regular expression matching, printf-like functions). Please refer to our SQL macros description for more information.

Partial evaluation

Partial evaluation is a process of specializing given program with some of its inputs, which are known statically. This way we obtain a new program, which is the optimized version of the general one. Implementation of this technique often involves program generation and rewriting.

Macros can be used as a convenient tool for partial evaluation in a similar way to multi-stage programming.

A tutorial explains how to use macros in such a setting. There are examples describing specialization technique (power function, permutation algorithm) and others.

Concurrency constructs

Most of the features of Polyphonic C# were implemented in our library using Nemerle macros. You can use these specialized features for safer multithreading application, by simply importing Nemerle.Concurrency namespace.

Currently you can see some examples.

Design patterns

Some design patterns can be greatly automated by macros. Instead of writing massive amount of code, programmer can just generate neccessary methods, fields, etc. or transform handwritten classes according to the needs, reducing maintainance costs and bugs introduced by commonly used copy & paste method.

Aspects-Oriented programming

As for now see this.

More

More examples can be found at the class library documentation page.

⚠️ **GitHub.com Fallback** ⚠️