Z# (Zee-sharp)

A new .NET language

Module

The module directive attaches the code in the file to a named (logical) unit. This name is also used with import.

Multiple code files can be part of the same module within the same assembly.

# module math

Note the use of the # pragma syntax, for the module functionality is a compiler feature that is performed at compile-time.

The name may contain a few special characters: . and _ . This is a valid module name:

# module myproject.Custom_String1

Module names are Identifiers too.

In a sense, the module name is also the namespace of the code in the file.

A module file can contain type, variable and function declarations as well as (top-level) statements. The statements will be run in order (top to bottom) when the module is initialized.

Packaging libraries is not part of the language but a function of the compiler. It uses modules to group code together. The module identifies all the code -not just the exported public identifiers.


Should the module statements module and import only be used at the top of the file, or can they appear anywhere?

.NET: Circular Assembly references are not supported. Multiple modules can go into one Assembly.


Should there be a way to mark a module as open/closed for extension? No. Only multiple files within the same assembly (compilation).

What about file-scope state?

// file-scope
# module this_is_my_module
globalVar: U8 = 42  // accessible by all files in module?

Yes. module-static state is accessible by all module files.


TBD


TBD: Services

Module as a boundary for implementing ‘services’?

A service would be an ‘object’ that communicates via messaging - the original OO concept.

Services as single threaded and concurrent. No additional threads allowed inside a service.

Exported functions are the public API for the service and the function parameters are the fields inside the request-message it receives. The return value (which can be a tuple) is the response message the client receives.

Async/await is a separate concern and is mainly used as a .NET interop feature.

A runtime framework is needed to host these services. I don’t think HTTP would be a good fit. Something like gRPC would do better perhaps?

Maybe have a service be the conventional remote API and a component be the in-memory implementation for it? That way a component can be wrapped in different types of Service endpoints (REST/gRPC/JSON/XML)…?

Actor Model / Active Object Pattern? An isolated component with an Event/Message Queue and a private (pooled?) processing thread… Preferably stateless? No (non-constant) data sharing across threads, ever.

We may want to add a proxy to immutable objects to share the proxy (identity) and not the object itself (Clojure does this) - so that changes to the immutable object -becoming a new instance- can be pointed to by the proxy?


TBD

The principle of declaring a file to be part of a module can be extended to OO classes/records as well. A future extension could introduce the class or record keyword to interpret the file as a class implementation. Although currently the idea is selectively generate C# records based on the presence of self-bound functions.