Library
A library's primary use is being a collection of methods. A library can also contain readonly fields.
This is most closely equivilant to a static class in C# with readonly fields or init properties.
A library is not a type, it is a value. The major implication is you cannot create a new instance of it.
Add explaination of what type a library is
Declaration
To declare a new library define a top level construct with the keyword library followed by the desired Identifier. The name must be unique within the corresponding namespace - Namespace
A library contains any number of named:
library ExampleLibrary //Physically located in /Libraries
{
double SevenPointFive = 7.5;
double Zero;
ComplexType DefaultState;
int Double(int foo)
{
return foo * 2;
}
string MakeSuper(string phrase)
{
return $"Super {phrase}";
}
//Lambda syntax for method declaration is supported
//See Aspects/Methods for more information
bool AlwaysFalse => false;
bool Inverse (bool x) => !x;
int UseMembers(int x)
{
return x * SevenPointFive;
}
int HiddenScope(string SevenPointFive)
{
return SevenPointFive.Length() * this.SevenPointFive;
}
}Remarks
Library fields are readonly and cannot be changed. That means a non-initialized field will be left with it's default value.
All members are automatically scoped into methods during execution. The implication being that you can use these within methods. See UseMembers method in the above example for a demostration of this.
Method parameters will take scope precedence and can hide local members. You can access any hidden fields via the this keyword. Check out the hidden scope function.
Libraries cannot have constructors as they are not initialized. This understandably impacts the complexity of scoped fields immutable value.
C# Equivalent
using System;
using ExampleApp.ComplexTypeClasses;
namespace ExampleApp.Libraries
{
public static class ExampleLibrary
{
public static double SevenPointFive = 7.5;
double Zero;
ComplexType DefaultState;
public static int Double(int foo)
{
return foo * 2;
}
public static string MakeSuper(string phrase)
{
return $"Super {phrase}";
}
public static bool AlwaysFalse => false;
public static bool Inverse (bool x) => !x;
public static int UseMembers(int x)
{
return x * SevenPointFive;
}
public static int HiddenScope (string SevenPointFive)
{
return SevenPointFive.Length() * this.SevenPointFive;
}
}
}Usage
A library's aspects are directly exposed as aspects on the library's Type identifier.
Using our example the Type identifier is ExampleLibrary
As usual, we use the member access operator .
So to access member MakeSuper you would type ExampleLibrary.MakeSuper
In practice consume of the library might look like this
//A scope with statements
var foo = 5;
var saiyan = "Saiyan";
var doubled = ExampleLibrary.Double(foo);
var superSaiyan = ExampleLibrary.MakeSuper(saiyan);
var doubleMethod = ExampleLibrary.Double;
//https://en.wikipedia.org/wiki/First-class_function
var alsoDoubled = doubleMethod(5);
Console.WriteLine(doubled == alsoDoubled);//Outputs true
Console.WriteLine(doubleMethod == ExampleLibrary.Double);//Outputs true
Console.WriteLine(ExampleLibrary.SevenPointFive);//Outputs 7.5
var libraryInstance = new ExampleLibrary();
//Compilation error because libraries cannot be initialized.Remarks
The primary thing to call attention to is while the declaration has significantly less code the usage is very similiar, sometimes identical. This is in support of the approachability design pillar.