kcl-lang / kcl-lang.io

KCL Website and Documentation Repo: https://kcl-lang.io
https://kcl-lang.github.io
Apache License 2.0
13 stars 34 forks source link

[FAQ] Is it possible to check that an object can be cast to the type (something like `"test" is B`)? #433

Open bozaro opened 2 months ago

bozaro commented 2 months ago

General Question

I want to check that an obkect can be cast to the type. Currently I found only one method: get type name with typeof and compare with target type name and all of childs target type names.

For example:

schema A:
    name: str

schema B(A):
    foo: str

schema B1(B):
    foo = "1"

schema B2(B):
    foo = "2"

is_B = lambda o: A {
    # Is it possible make this expression without compare with all child type names?
    typeof(o) == "B" or typeof(o) == "B1" or typeof(o) == "B2"
}

a = A {name = "a"}

b = B {name = "b", foo = "3"}

b1 = B1 {name = "b1"}

b2 = B2 {name = "b2"}

check_a = is_B(a)
check_b = is_B(b)
check_b1 = is_B(b1)
check_b2 = is_B(b2)
Peefy commented 2 months ago

KCL currently supports two types of type assertions: typeof(foo) == "B" or foo as B. Your requirement seems to be to directly obtain the reflection ability of subclasses of B?

As an aside, although implementing complex reflections for KCL is not that difficult, perhaps we can increase the ability of runtime.subclasses(). However, even in languages such as Go and Rust, obtaining a subtype of a type is not an easy task.

bozaro commented 2 months ago

In finally I wan create some logic for type B and all subtypes.

Something like:

is_B = lambda o: A {
    # Is it possible make this expression without compare with all child type names?
    typeof(o) == "B" or typeof(o) == "B1" or typeof(o) == "B2"
}
to_B = lambda o: A -> B {
    # Is it possible make this expression without compare with all child type names?
    _x: B = Undefined
    if typeof(o) == "B":
        _x = o as B

    if typeof(o) == "B1":
        _x = o as B1

    if typeof(o) == "B2":
        _x = o as B2

    _x
}

bar = lambda a: A {
    _x: B = Undefined
    if is_B(a):
        _x = to_B(a)

    {
        if _x:
            test: _x.foo

    }
}

In my current task type hierary is something like: endpoint declaration -> endpoint declaration with chart deploy info -> endpoint declaration with chart deploy info with project-specific default

Peefy commented 2 months ago

I see.

To achieve this, there is currently no great way in KCL. Possible solutions in the future: