---
title: Core Concepts
slug: core-concepts
createdAt: 2021-06-26T17:17:39.000Z
---

This is a high level overview of the major differences between Shift and C#. It also notes somethings that might be identical or similiar just because their major concepts. Some ideas/concepts may be mentioned twice because of it's interaction with other concepts.

Check out [Decisions](docId\:OjKdtGgWs_dwMdfQdq6wG) for things up in the air + thoughts around why I'm on the fence about it.

# CLR Binding

All .NET/CLR assemblies can be consumed in Shift. Shift will expose those types in a Shift equivilant. This means the vast majority of the existing ecosystem is usable, Shift isn't starting from scratch.

Furthermore the binding is bidirectional. Shift compiles to a CLR assembly meaning that a Shift project/library can be consumed by any .NET target langauge.

This means if you want to start using Shift, you can start with your next library or project being in Shift, not requiring you to abandon your previous codebase.

# Type Dependence

One of the showcase features of Shift is full support for Type Dependence.

When defining argument types for generics you can signify a dependent type via the `:` operator

:::CodeblockTabs
Shift

```csharp
record MyRecord<T, Size:int>
{
    T Foo;

    int AddToSize(int bar)
    {
        return Size + bar;
    }

}
```
:::

Above you can see for record MyRecord that there are two type arguments T and Size.

A type argument when accompanied by the : operator then supplies the type of the value that be passed in. What this means is that Size will not be a Type passed in, but instead an `int`. Unlike compared to a constructor taking an int in, this is a part of the Type's definition. Anything that compares types will know that these are not the same.

Let's look at instatiation of the type.

:::CodeblockTabs
Shift

```csharp
var myrec = new MyRecord<Giraffe,7>();
var rec2 = new MyRecord<Giraffe,30>();

var sameType = myRec@ == rec2@;//False

Console.WriteLine(myRec);//MyRecord<Giraffe,7>
Console.WriteLine(rec2);//MyRecord<Giraffe,30>
//Default ToString for a value is uncertain atm, so above is just an example

Console.WriteLine(myRec@.Size);//7

var together = myRec@.Size + rec2@.Size;

Console.WriteLine(together);//37
```
:::

Furthermore let's look back to T. It's the normal type argument syntax that most languages use for generics. In Shift it's using type inference, as there are actually no type arguments that aren't type dependent. In long form the record's definition really is

`record MyRecord<T:Type, Size:int>`

The default constraint for a dependent type is to be a Type. When interacting with how Types behaves and are accessed this allows you to pass Giraffe as the first type argument when declaring the new Type.

Checkout [Dependence](docId\:c_TiJQcMasPzqpr12kpdu) for a deep dive into the type dependence system

# Types

All type definitions are also namespaced symbols for accessing that type. This means there is no need for the `typeof` operator. A Type and a reference to a Type Definition are unified in Shift.

onsequently the typeof operator doesn't exist as it serves no purpose.

```csharp
var intType = typeof(int);//C#
var intType = int;//Shift - Fails in C# as an invalid statement

var list = new List<int>();//C#
var list = new List<typeof(int)>/();//Shift if the typeof operator wasn't removed

//More importantly
var list = new List<intType>();
```

Dependent type arguments can be supplied a constant or a variable. Since all regular type arguments are just inferred dependent types (T\:Type) that means all type arguments can actually be variables. This is what allows the last line in the above example work.

:::CodeblockTabs
Shift

```csharp
var foo = new MyRecord<Giraffe, 0>();

var zero = 0;
var foo2 = new MyRecord<Giraffe,zero>();

var giraffeType = Giraffe;
var foo3 = new MyRecord<giraffeType,zero>();

var bigGiraffe = new Giraffe(Size.MEGA);
var foo4 = new MyRecord<bigGiraffe@,zero>();
//Shows off the @ operator

var sameType = foo@ == foo2@ 
    && foo@ == foo3@
    && foo@ == foo4@
    ;//True - They're all identical type
```
:::

The above are only the same type because int is a record, and uses value equivilance. If a type with reference equivilance is passed in, then&#x20;

See [Types](docId\:JvnDFq5GKWsOepMI2SfYz) for more information about Types. There are a lot of interactions and implications that are explored there.

# Type Aliases

Shift supports type aliases as a convenience for defining types. Type aliases can be any combination of open and closed generics in it's definition.

:::CodeblockTabs
Shift

```csharp
type IntList = List<int>;//Closed generic example
type ListAlias<T> = List<T>;//Open generic example
type StringKeyedDictionary<T> = Dictionary<string, T>;//Mixed open and closed
type InferredTypeArgs = Dictionary<K,V>;
```
:::

When defining a type alias that points at a generic type you only need to specify the type arguments if you want to change the ordering of types or partially close the definition. Otherwise you can drop the type arguments from the left and the compiler will infer based on the right.

InferredTypeArgs uses type inference to actually be of type `InferredTypeArgs<K,V>`

See [Type Alias](docId\:AUgJMCCvISx5gMHmrF4sC) for more information.

# Null

Does not exist. You cannot a `null` to a variable.&#x20;

Reference types do not initialize to null and there is no way to get them there.

C# reference types are either initialized to a non-null default state or wrapped in Nullable. The type Nullable's Value property behaves different than C#. It will returned a fully initialized instance if the wrapped type is null.

# Action, Func, and Void

Methods take the place of Delegates, Actions, and Funcs in Shift. They've all been unified into this one Record type. Check out [Method](docId\:GDyTdA2qp1iVc7I30nT2n) for more info.

The closest thing to an action is a Method\<T, void> which is a method that returns a Void.&#x20;

A void (keyword alias to Void) is a type alias to Array\<0>.&#x20;

- Checkout [Primitives](docId\:mwkYKvjStikZ2sXSVln1i) for more information about void
- Checkout [Dependence](docId\:c_TiJQcMasPzqpr12kpdu) for more information about Array\<0>

# Constructors

Constructors in Shift are syntactic sugar for methods. Checkout the [Constructor](docId:8cur6rtDH4zhi8fdH6VhO) page for more information.

In general it's a method that is handed an already instantiated instance of the type and returns the type

```csharp
structure BasicStructure
{
    int A;
    int B;

    this(int a)
    {
        A = a;
    }

}

//The constructor is syntactic sugar for
extend new<BasicStructure> with this(a, BasicStructure self)
{
    self.A = a;    
    return self;
};
```

Constructors actually belong to the standard library supplied New class. Explained below in the New section.

See [Constructors](docId\:Xqe2GxWIOLp1Cq3eRqDdR) under discussions for some ongoing thoughts about the area.&#x20;

# New

When you type `var foo = new Goose("Honk Honk");` what is going on in Shift? It's not the same as C#.

This is syntactic sugar for New\.Construct\<T>("Honk Honk");

So new Goose ("Honk Honk") will bind to the New library (standard library supplied) and supply type argument Goose, and then 1 string variable.

You can imagine the insides of the New library being something like this

```csharp
T Construct<T,ParameterSet>(ParameterSet arguments)
{

    var fullSet = arguments + default(t);
    //Tuple + operator produces a new tuple 
    //with (leftterms...rightterms)

    return this@
        .Methods
        .Where(x => x.Name == :this)
        .OfType<Method<fullSet@TA,T>>//Only methods that are the right constructor
        .Single
        (fullSet)
        ;
}
```

Break down the do notation line by line

First Statement

- We need to build a new type array that is the passed in arguments + the type being instantiated. This comes in handy during the second statement
- We do this by passing in the arguments + a default instance of T
  - This is also where T is allocated into memory

Second Statement

- Get a reference to the library type itself.
  - The @ operator is syntactic sugar for .GetType()
- Retrieve the collection of methods
- Filter to only methods that have the `this` identifier.
  - : in this context is the syntax for defining an identifier literal
  - This is similiar to the symbol operator in some languages
- Filter to methods that match the right method syntax.
  - Methods that will return the type we're constructing
  - Methods that have the exact match of parameters passed into this function
    - Specifically the parameters + the instantiated type since it's the final argument in the constructor always
    - fullSet@ is getting the type of fullSet and then we're accessing the TypeArray
- Ensure only 1 result came back. The compile is fucked if this throws an exception
- Invoke it and pass in the arguments
- End statement, which passes this r-value to the return command which bubbles up out of the block.

It's worth noting that this isn't the literal implementation but supposed to be repersentative of what is happening. Something somewhere has to actually allocate memory and get a reference to pass to the constructor.

# Interference

Local scoped variables can use `var` just like in C#.

When declaring variables, the default constructor is always inferred. Or more accurately there is no null value for reference types, and everything has a default value that is non-null. There is always a system supplied constructor of () for every type.

### Namespacing

Namespaces are inferred from relative path to folder.&#x20;

- Root namespace is the project name.
- Namespaces can be explicitly defined via namespace \{ } which scopes everything inside C# style

Namespaces do not need to be imported to be used.

- The compiler will infer which using statements and only throw an error when ambiguity exists
- Using statements to pull a namespace into local scope are necessary if a type is ambiguious based on the linked libraries.
- Using statements can be placed
  - Top level in file, scoping the entire file
  - In a construct scoping the entire construct
  - In a block scoping just the block

# Access Modifiers

In Shift there is no scope modifiers. There is no private, protected, internal, public. Everything acts as though it's public.

Check out [Philosophy](docId\:x4BNd9VAXNludm4t3u1_1) as to some thoughts on why. I'm very aware that this is chucking a bundle of dynamite on encapsulation.

Each type class (structure|record|library|service) is accesible from anywhere and all fields can be accessed from anywhere. This is intentional to force everything public and reduce how much boilerplate there is when defining types and aspects.

# Readonly

Similiar there is no ability to mark something readonly. All fields are readonly except for structure fields. There are no modifiers to vary this.
