Tag Archives: constructors

Object (post) initialization

Skila-1 had auto constructor as its object initialization version, but few days ago I was writing some ordinary Config type in C# and when I added builder pattern I realized how little C# is missing to get proper object initialization.

Thus I scratched the idea of reimplementing Skila-1 approach and I added object (post) initialization — it is much simpler to implement and it feels completely like C# (whenever I can I prefer to stick to already popular language). Using C# syntax it is just:

public class Point
{
    public init double X { get; }
    public init double Y { get; }
}

var p = new Point() { X = 5, Y = 7 };
p.X = 3; // error

Yes, all it takes is little modifier added to field/property indicating that despite it is readonly it is allowed to be assigned (initialized) during post initialization. The type itself is immutable, there is no additional mechanism added, everybody is happy.

The older approach has its advantages (single initialization for starter) but since it can be added in any time I will stick with this lightweight approach for now.

Advertisement
Tagged , ,

Meet the constructors family

Most of the time you will use init constructor which works pretty much as the one seen in C#, Swift, or Python. The memory for object is already allocated, you just have to set the values for the object members.

Next we have field initializers — which you use, but you don’t define explicitly:

class Foo
  let myField Int = 3;
end

That 3 will be moved to field initializer constructor, there is one per each class and it is called automatically just after alloc constructor, which simply allocates memory.

Similarly to field initializer, there is a type initializer — this one can be written explicitly:

class Foo
  static let myField Int = 3;
  static let other Int;

  static private def init()
    this.other = 2;
  end
end

In above code you see only one initialization inside type initializer, but compiler will drag down that 3 there as well.

All the fun is with the remaining two constructors — let’s start with new one, its generated code looks always the same:

class Foo
  •••
  static def () Self // new constructor
    let __this = Self.alloc();
    __this.init();
    return __this;
  end
  def init()
    •••
  end
end

There are some rules concerning new constructor (it has to be static, it has to return Self/!Self type, it cannot have name, it cannot be generic), but because its body is completely repetitive the compiler synthesizes it for every non-partial init constructor there is.

For truly immutable types like Int we can do better though — take a look at copy constructor:

static def (copy Self) Self
  return copy;
end

Instead of init constructor we defined new constructor which returns the original object — this way we prevented creating new object (think: memory allocation) and for free we got new reference.

There is only one constructor left — companion constructor (anonymous factory). How many times when you wrote code in C# you were annoyed you couldn’t write such line ¹:

return new Tuple(3,4);

and you had to painfully instruct C# compiler:

return new Tuple<Int,Int>(3,4);

Skila has special syntax for creating tuple values, but faces the same problem — this is a constructor call and arity of the typename tells which type we are referencing. In the first snippet it would be a type Tuple and the problem is there is no such type. Companion constructors fit just right in:

interface Tuple
  new static def <T0,T1,out C>(_0 T0,_1 T1) Tuple<T0,T1,C>
    where
      C base T0;
      C base T1;

    return (_0,_1);
  end
end

This particular example is an overkill in Skila, it serves only as an illustration. Note the differences, you can place companion constructor in any type, the result type does not have to be Self, the method can be generic and you have to mark such constructor with modifier new, otherwise compiler would assume it is indeed new constructor. In other words you are marking anonymous factory method with new modifier to be treated as new constructor when called — yet, under the hood it is a regular method.


¹ Apparently I am not alone — see: Why can’t the C# constructor infer type? I am curious about history of resolving this issue in C# compiler, because targeting all possible types at the same time adds a lot of complexity.

Tagged

The object initialization

Writing constructors by hand is so tedious that I am happy C# has object initializers. Well, sort of happy, because they are not really object initializers (they are just member assignments) and because of that they often collide with the configuration of the members (private or readonly). One thing I cannot deny — they offer really compact form of setting up the object:

new Point() { X = 5.3, Y = 7.2 };

Scala and Kotlin address the same problem providing also compact form, true initialization, however in not very pleasing manner:

class Point(var x: Double, 
            var y: Double) 
{
  ...
}

Without such constructor the structure of type definition is pretty clear, with constructor added all of the sudden part of the type is moved as parameters, so it looks like a method which is, and which is not at the same time. Different taste I assume.

Let’s write bare type Point in Skila:

class Point
  var x = Double(13.2);
  var y Double;
end

Some things worth noting — both fields are private by default, you cannot omit the typename unless you initialize the field (or property) with constructor, which is the case here. Type inference is useful feature to have but it is best served in moderate ratios.

Our Point type has default constructor, but we cannot initialize Point object with custom values. Let’s change it:

class Point
  in var x = Double(13.2);
  in var y Double;
end

And that’s it — the keyword in says ”add named parameter to constructor and initialize the given field with it”. In other words such constructor is added behind the scenes:

  def init(x : Double = 13.2, y : Double)
    this.x = x;
    this.y = y;
  end

Because of the named parameters (note the colon) the compiler can add default values wherever it wants. Named parameters also mean user has to provide the names:

Point(x : 3, y : 15.5);
Point(y : 7, x : 1); // the order does not matter
Point(y : 1.5);
Point(2, 3.5); // error, no names
Point(x : 2); // error, missing `y` parameter

What can I say — I honestly like this design. It is as clear as C# code, but you don’t lose any benefit of real constructor. What’s more, you can use in keyword as a parameter and an argument as well:

base class Animal
  in let weight Double;
end

class Human : Animal
  in let iq Double;
  let label String;

  def init(label String = "Joe", in)
    super(in); // calling base constructor
    this.label = label;
  end
end

// `label` is anonymous parameter
Human("Jane",iq:130,weight:60); 

The only requirement is in parameter has to come last, it is small price to pay if you ask me.

Tagged , , , , ,

C++ const – how to make it happen?

The latest list of changes (not done yet) includes regular constructor (not returning anything), variadic syntax as in Go (“x ...Int”) and “procs” (for mutating methods) and “funcs” (not mutating, can be prefixed with “|”).

This is related to C++-like “const” ¹ — I am that guy who loves this feature (maybe not execution), however I am both a bit clueless how to implement it correctly and I am a bit afraid if I understand the concept (considering almighty MS gave up on this having so many smart people). I think there could be only two constants — constant pointer to some data (constant or not) and deep constant data (immutable view of data).

It might sounds funny but I don’t even have good names for them — say “lnk” for fixed pointer (“ptr” for regular one), but what for data? If possible I would like avoid “const” (to avoid naysayers with standard “it does not guarantee the object is constant after all”, and to keep good keyword for constants like mathematical Pi). “view”?


¹ Interesting posts at SO: Why there is no const member method in C# and const parameter?, Why const parameters are not allowed in C#? and “const correctness” in C#.

Tagged , , , , , ,

Generics — just around the corner

The last few posts were about NLT only but Skila things were move forward as well. I added value and reference types with control of data mutability. So for example:

func getconst() const Foo = new Foo();

func readconst()
do
  var x = getconst();
end

It will work if “Foo” is value type (because all data from the function “getconst” will be copied) but it won’t work if “Foo” is reference type, because in such case only a reference is passed — one could still alter the data obtained from “getconst”.

I am aware that I missed a lot of cases but I will fix the bugs as I will implement next, and probably the last major feature before I make first upload of Skila — generics. I need it to provide arrays, tuples and IEnumerable interface. Those in turn will be required when implementing macro constructors.

My schedule looks like this:

  • think over the constructor naming — maybe instead ”func Init” it would be better to have just “constructor”,
  • polish “const/var/!” syntax — the mutable methods are denoted by “!” in front of their names, but objects are marked with ”var”,
  • add shuffle feature to NLT parser,
  • implement true generator for NLT,
  • add generics to Skila,
  • toss arrays, tuples and IEnumerable,
  • finish with macro constructors.
Tagged , , , , , , , ,

SELF — one factory to rule them all

Another promise fulfilled — having pinned constructors in hand I could add “SELF” which behaves like implicit generics. Or you can think of it as virtual static feature.

Probably the best way to present it is using factory pattern:

struct Foo
  // constructor
  def pinned init() Foo 
  do
    return self // "this" in C++ family
  end

  def static Create() SELF
  do
    return new SELF();
  end
end

struct Bar : Foo
  def pinned init() Bar
  do
    return self 
  end
end  

The “SELF” which interests us sits in “Create” method. When you call it as “Foo.Create” you will get instance of “Foo”, but when you call it as “Bar.Create” you will get “Bar” object. Please note that such call does not cause an error:

var obj Bar = Bar.Create();

The above snippet would be erroneous if “Create” was defined differently, namely:

  ...
  def static Create() Foo
  do
    return new SELF();
  end

forcing you to write:

var obj Foo = Bar.Create(); 
// Bar is created nevertheless

But since it was defined with result type as “SELF”, the actual result type changes from call to call and compiler knows about it.

To summarize — “self” is a polymorphic reference to an object, “SELF” is a polymorphic reference to a type. You can create new instances using “SELF” as long as the used constructor is marked as pinned.

Tagged , , , ,

Pinned constructors — served as promised

Exactly as I wrote previously, I added pinned constructors feature into Skila. Let me show you the syntax:

struct ClassModifier 
  def pinned init(coords NodeCoords)
  do
    ...

The novelty is “pinned” keyword after “def” (“init” is Skila constructor).

Once you add pinned constructor you have to redefine it (or allow compiler to do it for you) in every descendant class. Compare this to regular methods — when you add one you know it will stay in every derived class. It is not true with constructors though, you can have elaborate constructor and it is only good for the class you define it for. So you can think of pinned constructors as an aid for bringing symmetry between methods and constructors.

If you don’t define any constructors compiler will redefine pinned constructors for you with simple field initialization and calling base constructor. Please note that unless parameterless constructor (the default one) is pinned in base class, it won’t be redefined by compiler along with pinned ones.

Tagged ,

All the noise about static

Who would thought that adding “SELF” can cause so much fuss — obviously I needed “static” notion in Skila, which I hadn’t have and when I added it appeared NLT parser is not suitable for new set of parsing rules.

The last problem came as no surprise — so far NLT forking parser executed all user actions, even in multiple branches. This had to lead to problems and hit me this weekend. So instead of doing fancy stuff with pinned constructors, I sat down and changed executing user actions into logging parser actions. On successful parse, all commands are played back and then user actions are executed.

No rocket science, nevertheless I was one day short, and after adding exposing field’s methods feature plus fixing PHP backend a bit I ran out of time. I plan to squeeze error reporting on static misuse into workdays so I will be able to come fresh to implementing pinned constructor and “SELF” next weekend.

Tagged , , , ,

Implicit generics and pinned constructors

It is preliminary step of enhanced generics we know from C# and I hope all things finally clicked in for implementing this feature. Consider such code:

public class ClassModifier : TreeNode
{
  public bool IsAbstract { get; private set; }
  public bool IsVirtual { get; private set; }
  public bool IsStatic { get; private set; }

  private ClassModifier(NodeCoords coords)
    : base(coords)
  {
  }

  public static ClassModifier Abstract(NodeCoords coords)
  {
    return new ClassModifier(coords) 
      { IsAbstract = true };
  }
  ...

and

public class MethodModifier : TreeNode
{
  public bool IsAbstract { get; private set; }
  public bool IsVirtual { get; private set; }
  public bool IsStatic { get; private set; }
  public bool IsNew { get; private set; }
  public bool IsOverride { get; private set; }

  private MethodModifier(NodeCoords coords)
    : base(coords)
  {
  }

  public static MethodModifier Abstract(NodeCoords coords)
  {
    return new MethodModifier(coords) 
      { IsAbstract = true };
  }
...

Factory methods as usual, nothing special except the code is highly redundant. In PHP it can be expressed nicely because it has static constructor with late binding — it works like static polymorphism. It can be shortened in C# too, but with ugly twists.

However Skila is meant to be expressive and compiled language.

So I came up with idea of pinned constructor for the beginning. Once added to any class such constructor has to be overridden in every descendant class (or automatically upgraded). Secondly special keyword to express static polymorphism is needed — “SELF” sounds just right. With those two enhancements the code becomes much shorter (it is not Skila yet):

public class ClassModifier : TreeNode
{
  public bool IsAbstract { get; protected set; }
  public bool IsVirtual { get; protected set; }
  public bool IsStatic { get; protected set; }

  protected pinned ClassModifier(NodeCoords coords)
    : base(coords)
  {
  }

  public static SELF Abstract(NodeCoords coords)
  {
    return new SELF(coords) 
      { IsAbstract = true };
  }
  ...

public class MethodModifier : ClassModifier
{
  public bool IsNew { get; private set; }
  public bool IsOverride { get; private set; }
  ...
}

Thanks to pinned constructor it is safe to write “new SELF(coords)” — every class has to support such call. And because “SELF” works as implicit generics when I call “MethodModifier.Abstract()” I will get “MethodModifier”, not “ClassModifier” despite the fact the method is static and it is defined in “ClassModifier” class.

Tagged , , , , , , ,

Modern constructor — how does it look?

For sure the way the constructors are written in C++ has to go — starting from naming constructor not by a name of the class, but simply “__construct” (like in PHP) or “init” (I would also like to add ability to return a value, but it is a minor thing as well). The real problem is how to initialize object fields in a constructor — briefly, yet in informative way?

Scala integrated constructor went too far — the code is very concise, true, but at the expense of the readability. Entire body of a class becomes a constructor and this means constructor parameters are leaking directly into all class methods.

C# is much better in this regard, I love its syntax:

new Person()
  {
    FirstName = "Joe",
    LastName = "Doe"
  };

The problem? It is not a constructor really (just the first line is). It is not only the matter of the name though, there are technical implications as well — “FirstName” and “LastName” cannot be readonly properties for example. But the clarity is hard to beat.

So the question for Skila is really this — how to bring C# syntax and make it real constructor? So far I came up only with an idea of macro constructor…

Mark the fields of the class which can be initialized by simple assignment and call constructor as usual — all parameters for marked fields are passed via magical “ini” tuple and initialized in one assignment.

class Foo
  var FirstName <- String("John");
  var LastName <- String;
  var BirthYear Int;

  def init(birthYear Int, $ini)
  do
    this.BirthYear = birthYear;
    this.$ini = $ini;
  end
end

new Foo(1918, FirstName : "Joe",
              LastName : "Doe");

Some of the features of macro constructor:

  • field pseudo-initialization serves as indication of optional argument, i.e. you could omit “FirstName” here when creating “Foo” object; it is not field initilization like in C#
  • when passing arguments via “ini” you have to name all arguments — in other words “ini” expands to a list of forced named parameters, and thanks to that it can always be safely placed as the last (pseudo) parameter,
  • because assignment in constructor is explicit you can decide when to call it.

Is this the best what can be done in 2013? Do you have better ideas?

Tagged , , , , ,