Skip to content

Sketch of: constant variables/members, some publicity modifiers #62

@HoneyPony

Description

@HoneyPony

Now that we have a readonly flag on our variables, almost the only thing missing from PonieScript to have constant (not reassignable) variables is the syntax to do so.

Right now I am thinking of using let as the keyword for this, as opposed to var for reassignable variables.

fun my_fun() -> int {
    let myval = 10;
    let myval = myval + 20; // shadow
    myval + 30
}

class MyClass {
    // Can only be assigned on class construction
    let identity: int = 30;
}

fun do_something() {
    let me = new MyClass { identity: 20 };
    //me.identity = 22; // invalid
}

class MyOtherClass {
    var something: int = 30;
}

fun do_something_else() {
    let me = new MyOtherClass { something: 45 };
    me.something += 20; // valid because only me is not reassignable
}

However, the obvious question this brings up (at least in my mind) is: What do we do when we want a readonly class member, that you CAN'T assign a different value to during construction?

Such a value would still be "public," but would be prevented from appearing in new{} expressions.

I think ultimately we will want GDScript or Rust style "annotations," which we might also use for plain visibility. Something like:

class MyClass {
     // You can change this one
     let otherval: int = 10;

    // You can't change this one
    @restrict_construction
    let val: int = otherval + 5;

    // Private and constant
    @private
    let something: int = 20;
}

// Members in this class default to private (the LSP should show you which ones are public/private?)
@default_visibility(private)
class OtherClass {
    @public
    var my_val: int = 30;

    @public
    @restrict_construction
    let something: int = 23;
}

The question, then, of course is what do "private" and "public" actually mean. I think in general I will want "private" to mean private to the file that the class is defined in -- this (sort of) matches what Rust does, which tends to be pretty convenient.

We could, however, also have something like @private(file) versus @private(class), or even @private(.my_fun) to restrict the variable's access to a single function. That is something fun to consider... eventually.

One other thing that would be "fun" but is maybe not worth considering right now is having some sort of "constant reference" type. This type is definitely useful in the case of Arrays, for example, where we would like to be able to pass an Array[Dog] as a const Array[Horse], or something along those lines.

I'm not sure exactly the best syntax (or even semantics) for that. It is important to note that these are reference modifiers, so they don't actually change the underlying type of the data, only how a specific pointer is allowed to interact with that data.

The main idea is you would have something like

class Array[T] {
    @const
    fun operator[] -> T {
          ...
    }
}

But I feel like annotating every function that can be safely used with a const reference is very annoying.

These could be inferred by the compiler, but that would mean that changing a function's implementation can be a breaking change if it makes the function non-@const.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions