---
title: Method
slug: method
createdAt: 2021-06-23T18:58:36.000Z
---

Actions do not exist in Shift. Better said the type Action is an alias to a method that returns void.

`type Action<TypeArray> = Method<TypeArray, void>;`

`TypeArray` is a dependent typed `Array` of `Types`

It's definition is as follows

`type TypeArray<S:int> = Array<Type,S>();`

See dependent typing for more information

`void` is a keyword alias to type `Void`.

`type void = Void;`

void being a keyword is always available and guarenteed to be the same type. This is the same as C# and it's keyword type alias. int vs Int32

Void itself is a type alias to a type dependent empty array.

`type Void = Array<0>;`

Bringing these 2 concepts together gives us Action which is a type alias to a Method with a type argument for input, and a fixed output of type Void which is just itself Array\<0>.&#x20;

Philosophically this helps unify methods with output and no output. There is always input and there is always output. EmptySet might idealogically be the value of either of those two dimensions.

Action and Method both has keyword supplied type aliases for scoping convenience.

type action = Action;//Always in scope, and takes first precendence in type resolution

type method = Method;//Always in scope, and takes first precendence in type resolution

## Methods

Taking the above information, all method definitions in constructors are syntactic sugar to a method field.

Method is a record type and is immutable.

Some example methods in their common format you'd experience in C# and then the field syntax.

:::CodeblockTabs
Shift

```csharp
int PlusTwo(int foo)
{
    return foo + 2;
}

//Identical behavior/mechanics as above, just a different syntax for writing
//Long hand lambda syntax for block definition
method<int,int> PlusTwo = (int foo) 
{
    return foo + 2;
};

//Short hand lambda syntax is supported for trivial blocks
method<int,int> PlusTwo = x => x + 2;

//Type inference on both the input and output of the method
method PlusTwo int x => x + 2;


//Separate example just to demostrate multiple parameters

//Type inference infers method to be Method<[int,int],int>
method AddTogether (int a, int b) => a + b;
```
:::

C# developers will find the initial syntax most common and for complex methods the most commonly used.

Some examples of void return types from C# applied to Shift

:::CodeblockTabs
Shift

```csharp
//Example 1:
void SomeSideEffectMethod(ComplexType foo)
{
    var json = JsonConvert.Serialize(foo);
    File.WriteAllText("./saveMe.json", foo);
}

//Example 2:
action<ComplexType> SomeSideEffectMethod => (SomeSideEffectMethod foo)
{
    var json = JsonConvert.Serialize(foo);
    File.WriteAllText("./saveMe.json", foo);
}

//Example 3:
action<ComplexType> SomeSideEffectMethod => (SomeSideEffectMethod foo)
{
    var json = JsonConvert.Serialize(foo);
    File.WriteAllText("./saveMe.json", foo);
    return;
}

//Example 4:
action<ComplexType> SomeSideEffectMethod => (SomeSideEffectMethod foo)
{
    var json = JsonConvert.Serialize(foo);
    File.WriteAllText("./saveMe.json", foo);
    return new void();
}
```
:::

All 4 examples are the same, just using different syntax and amounts of inference. The first form is the most likely form you'd see such as thing in a service. Very similiar to C#.

Unpacking what's going on.

Just like before with the method examples; Example 1 is syntactic sugar for defining an action field. Hence the only diffference between 1 and 2 being the syntax.

It's common in C# when having a void return type to use no `return` statements. This is shown in Example 1 and 2. But in Shift <u>EVERYTHING </u>has an output, which means there is always a returned value.&#x20;

The compiler infers that when a `void` return type is specified that the final line of the block will return a new instance of void.

Furthermore the compiler understands that a return statement without a value, is being asked to return a new void;

Array's are record types in Shift. This means they have equality checking based on their contents, not their instance identifier.

:::CodeblockTabs
Shift

```csharp
var output = SomeSideEffectMethod(foo);

var emptySet = new Array<0>();
Array<0> bar;//Showing off type default values.

var areEquivalant = output == emptySet
    && output = bar
    ;

var sameType = output@ == emptySet@
    && output@ == bar@
    ;

Console.WriteLine(areEquivalant);//Outputs true
```
:::

Variable bar was thrown in to also demostrate the equivalence of type aliases. void and Array\<0> <u>ARE</u> the same type. Void just an alias. This means anywhere you could use the alias you can use what the alias is defined as.

The core take away and thing to remember is a type alias is no inherietence. Void does not inherit from Array\<0>, it IS Array\<0> with a different name for type resolution purposes.

Some more examples hammering home the type alias versus the definition are interchangable.

:::CodeblockTabs
Shift

```csharp
//Example 5:
action<ComplexType> SomeSideEffectMethod => (SomeSideEffectMethod foo)
{
    var json = JsonConvert.Serialize(foo);
    File.WriteAllText("./saveMe.json", foo);
    return new Array<0>();
}

//Example 6:
action<ComplexType> SomeSideEffectMethod => (SomeSideEffectMethod foo)
{
    var json = JsonConvert.Serialize(foo);
    File.WriteAllText("./saveMe.json", foo);

    var emptySetToReturn = new Array<0>();

    return emptySetToReturn;
}

//Example 6:
action<ComplexType> SomeSideEffectMethod => (SomeSideEffectMethod foo)
{
    var json = JsonConvert.Serialize(foo);
    File.WriteAllText("./saveMe.json", foo);

    Array<0> emptySetToReturn;

    return emptySetToReturn;
}
```
:::

#

