External Issue: Add a purely functional subsystem

19150, "skaller", "Add a purely functional subsystem", "2022-02-01T02:36:53Z"

Summary of Problem

I propose a function keyword to construct a function in a manner somewhat similar to the existing proc construction.

Functions will have the following properties:

  • guaranteed pure with no side effects
  • referentially transparent
  • only accept one argument
  • pass by value only except for owned class
  • guaranteed thread safe (after argument transfer)
  • type given by D -> C where D is the domain and C the codomain
  • return function and accept function fully supported
  • function closures cannot be put in user heap data structures

In phase 1 I propose only monomorphic functions. This will be extended to support parametric polymorphism in phase 2. In phase 2, sum types will also be added. Further extensions will be detailed later. Interface constraints should be included but will have to conform to strict requirements to be acceptable.

Requirements.

  • C++ back end.
  • fix 3 * int and (int,int) notational errors.

Comments.

We cannot pass a const entity to a function because the const binding does not guarantee immutability AFAIK. On the other hand an owned object can safely be modified by the function. in particular an owned array can be modified without loss of referential transparency.

Difficulties

A function can use a proc internally. It is hard to verify the result is correct.
Initially, this should probably be disabled. Introducing fully type checked and
verified functions is, in fact, partly intended to familiarise users with the
impact of a well designed type system, to support subsequent repair
of the existing proc system.

Options

It may be useful to add pre- and post-condition clauses. Suggested syntax is:
requires expr where expr is any boolean and expect expr where expr is any boolean and may also use the keyword result to refer to the final returned value. Like this:

function f(a:int require a>0): int expect result > 0 { ... }

The run time test for the precondition must be generated at the point of call, since any failure is the fault of the caller. The post condition test can be generated inside the function, since any fault is a failure of the function implementation.