ponyc icon indicating copy to clipboard operation
ponyc copied to clipboard

Should object literals be lifted to actors when their subtyping includes behaviors?

Open patternspandemic opened this issue 6 years ago • 2 comments

Should object literals resulting in an anonymous class or primitive be promoted to actor literals when they are sub-typed with an interface or trait including a behavior? As it is now, the literal must also include a behavior to be considered an actor literal. Note that it does not matter whether the trait or interface includes a default implementation for such behaviors.

I would expect such literals to be lifted to an actor, given any trait or interface requiring any behaviors also intends to categorize an actor. Then again, I'm unsure what kind of consequences this entails with union or intersected sub-typing.

ponyc version:

0.24.4 [release]
compiled with: llvm 3.9.1 -- cc (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609
Defaults: pic=false ssl=openssl_0.9.0

source (run in playground):


trait WithBehavior
  be bar() => None

actor Main
  new create(env: Env) =>
  
    let actor_literal =
      object is WithBehavior
        // Inclusion of behavior lifts to actor literal
        be other() => None
      end
  
    // Error: cannot add a behaviour (bar) to a primitive
    let primitive_literal =
      object is WithBehavior end

    // Error: cannot add a behaviour (bar) to a class
    let class_literal =
      object is WithBehavior
        var some: String = "field"
      end

patternspandemic avatar Aug 10 '18 17:08 patternspandemic

The straightforward solution is to look in all declared interfaces and traits for behaviours when deciding whether the literal should be an actor/object/primitive.

However I do find it surprising that the kind of "entity" being created is implicit. I would prefer if a different keyword was used, eg:

actor Main
  new create(env: Env) =>
    let actor_literal = actor is WithBehavior end
    let primitive_literal = primitive is WithBehavior end

This unfortunately makes parsing ambiguous, since the actor keyword could be either a literal, or the start of a new actor definition. It can be disambiguated by looking at the next token (if it's an identifier then it's a definition, if it's is/let/var/fun/be/end it's a literal, but that might be too confusing.

(I've always disliked how "actor" refers to both the definition and the runtime entity, unlike the existing distinction between class/object, but I was never able to come up with a better name for either).

plietar avatar Aug 13 '18 22:08 plietar

The straightforward solution is to look in all declared interfaces and traits for behaviours when deciding whether the literal should be an actor/object/primitive.

Yeah, I think that's what we should do for now.

Regarding other syntax suggestions, I think stuff like that would have to be tackled in a separate RFC outside this scope.

jemc avatar Aug 22 '18 20:08 jemc