Skip to content

Static Constructor

Problem

You want to construct an object or return a meaningful error message if the object can’t be constructed. For example, if a parameter is supposed to be in the range of 1 to 10, but 12 was passed. You’d like to return an error that “12 is out of range” instead of constructing the object. Unfortunately, in Pony there’s no way to do that. Pony constructors always return an initialized instance of their class unless the constructor is partial in which case nothing is returned as we jump to the nearest error handler.

class Foo
  // Always returns a foo
  new create() => None

  // Sometimes returns a foo
  new perhaps(a: Bool) ? =>
    if not a then
      error
    end

What you would like to do instead is:

class Error
  let msg: String

  new create(m: String) =>
    msg = m

class Foo
  // return a Foo or Error message
  new create(a: Bool): (Foo | Error) =>
    if not a then
      Error("Can't build Foo that way")
    else
      this
    end

Solution

Use a primitive.

class Error
  let msg: String

  new create(m: String) =>
    msg = m

class Foo
  new create() => None

primitive FooConstructor
  fun apply(a: Bool): (Foo | Error) =>
    if not a then
      Error("Can't build a Foo that way")
    else
      Foo
    end

Discussion

Static constructor is the Global Function pattern applied to object construction. As we discussed in Global Function, Pony’s primitives are a great way to group together stateless “like functions”. If you are looking to do anything that might be classified as a static function or a utility function in another language, you probably want to use a primitive in Pony.

If you have an background in ML type languages, you can think of primitives as similar to modules in OCaml and F#.

Finally, here’s our static constructor in action:

actor Main
  new create(env: Env) =>
    match FooConstructor(true)
    | let f: Foo =>
      // ToDo: do something with Foo
      None
    | let e: Error =>
      env.err.print(e.msg)
    end