此编程语言功能的名称是什么,并且有任何支持它的现实语言吗?

问题描述 投票:1回答:1

让树数据结构这样定义:

一棵树以一个节点为根。一个节点可以是叶子,也可以是一个内部节点,其一个或多个节点作为其子节点。

在某种伪OO编程语言中,我们可以这样定义一棵树:

Node := InnerNode | Leaf

Leaf {

    isLeaf() : TRUE

}

InnerNode {

    isLeaf() : FALSE
    children() : List<Node>

}

Tree {
    root() : Node
}

现在我们可以定义两个函数,'bad_code'和'good_code'。函数'bad_code'无法编译,其他函数可以编译:

function bad_code(Node anyNode) : void {

    // this will give a compile time error "type Node does not define method children()"
    anyNode.children();
}

function good_code(Node anyNode) : void {

    // the compiler understands that all Nodes must have a method called isLeaf() which 
    // returns a boolean
    let b : boolean <- anyNode.isLeaf();

    if (b == FALSE) {

        // this will not give a compile time error because the compiler can deduce that 
        // anyNode must be of type InnerNode which has the method children()
        anyNode.children();
    }
}

问题:

  1. 以上是通过某种正式方式定义/描述的语言功能的示例吗?
  2. 如果是这样:此语言功能正式称为什么?
  3. 有没有实现该语言功能的现实世界编程语言?
  4. 可以在运行时以零成本将这种语言功能实现为编译时检查吗?
programming-languages pseudocode language-theory
1个回答
2
投票

您正在描述的是编译器使用控制流图来缩小变量的类型,因此,当if语句测试与变量类型相关的条件时,可以为if语句的主体推断出相同的变量。]​​>

这称为控制流类型变窄

,例如Typescript。它纯粹是静态检查,在编译时完成,没有运行时的损失;实际上,Typescript中的类型在运行时根本不可用。
type TreeNode = InnerNode | Leaf

interface Leaf {
    isLeaf: true
}

interface InnerNode {
    isLeaf: false
    children: Node[]
}

function bad_code(anyNode: TreeNode): void {
    // type error: Property 'children' does not exist on type 'TreeNode'.
    console.log(anyNode.children);
}

function good_code(anyNode: TreeNode): void {
    if (!anyNode.isLeaf) {
        // narrowed type to anyNode: InnerNode
        console.log(anyNode.children);
    }
}

请注意,打字稿要求您以特定方式执行此操作;我们直接测试anyNode.isLeaf而不是先将其存储在变量b: boolean中,因为Typescript不会跟踪两个变量banyNode之间的关系:

function bad_in_typescript(anyNode: TreeNode): void {
    let b: boolean = anyNode.isLeaf;

    if (!b) {
        // type error: Property 'children' does not exist on type 'TreeNode'.
        console.log(anyNode.children);
    }
}

此外,在以上代码中,isLeaf是属性而不是方法。 Typescript确实具有一个名为user-defined typeguards]的相关功能,该功能允许方法的返回类型类似于this is Leaf,表示仅当调用类型为true的事物时,该方法才返回Leaf: >

type TreeNode = InnerNode | Leaf

interface BaseNode {
    ifLeaf(): this is Leaf
    isInner(): this is InnerNode
}

interface Leaf extends BaseNode {}

interface InnerNode extends BaseNode {
    children(): Node[]
}

但是,打字稿仍然比您的示例要受限制;我们必须测试anyNode.isInner(),因为!anyNode.isLeaf()不一定会进行同样的缩小。 (Typescript使用结构类型,因此,实际上LeafInnerNode的超类型,这会导致并集类型出现一些问题。如果给Leaf一个类似value: number的属性,而InnerNode则没有,然后!anyNode.isLeaf()会按照您的期望进行工作。)

© www.soinside.com 2019 - 2024. All rights reserved.