嵌套开关语句的替代方案

3

在研究自然语言处理时,我遇到了一个小问题:

switch(var1)
{
case Variant1_1:
    if( cond1 )
    {
        if( cond2 )
        {
            if( cond3 )
            {
                switch(var2)
                {
                case Variant2_1:
                    return someExpression;
                // another five-six cases
                default:
                    return;
                }
            }
            else // cond3
            {
                switch(var2)
                {
                case Variant2_1:
                    return someExpression;
                // another five-six cases
                default:
                    return;
                }
            } 
        }
        else // cond2
        {
            if( cond3 )
            {
                switch(var2)
                {
                case Variant2_1:
                    return someExpression;
                // another five-six cases
                default:
                    return;
                }
            }
            else // cond3
            {
                switch(var2)
                {
                case Variant2_1:
                    return someExpression;
                // another five-six cases
                default:
                    return;
                }
            } 
        }
    }
    else // cond1
    {
        // same thing

    }
    break;
case Variant1_2:
    // same gigantic tree
    break;
case Variant1_3:
    // here too
    break;
default:
    return;
}

有哪些替代方案可以用于这种“计算树”?我想到的唯一一件事是使用函数指针作为叶子节点的树容器,并使用许多小函数。


这段代码需要进行大量重构,不仅限于此函数,还包括其他函数。有时候,仅重构一个函数并不能帮助太多,或者说并不容易,但是考虑整个项目的设计(或至少是其他相关函数),会有很大帮助。然后重构就变得容易了,并且你可以期待更好的整体设计。 - Nawaz
每个条件组合的表达式真的都是独立的吗?在我的经验中,这种情况很少见。通常有一些共性可以被提取出来,以减少尝试的个案数。 - Vaughn Cato
考虑到这是自然语言处理,我猜可能会有更多的挑战。 - MadRunner
5个回答

4
每当你在C++程序中遇到一个switch语句时,就会知道你错过了继承的机会。(译者注:这是开玩笑的说法)
我知道两种重构多个并行switch的方法:(1)构建一个多维函数指针数组,和(2)使用访问者模式的变体。

好的,我想我会在多维数组上停下来,谢谢!但是,您能否为这位经验不足的程序员澄清一下在这种情况下使用“访问者模式”的想法? - MadRunner

1
一个好的解决方法是使用矩阵。
如果您知道所有条件都将被评估,则这将很有效。
创建一个多维数组,将真假值映射到处理函数。
Arrayswitch[var1][cond1][cond2][cond3][var2]();

1

当代码开始变得像这样时,我开始寻找一种数据驱动的方法。它可能只是一个简单的表格,或者像你建议的那样,可能是一个带有函数指针的树。

如果这是某种手工编写的解析器,您可能需要查阅一些解析方面的参考资料,以获取如何使用语法定义进行解析的想法(通过按需解释语法,或者使用将语法作为输入的代码生成工具)。

我经常手工编写递归下降解析器。通常,我创建一个保存状态的类,公开一个“Parse”函数,并将每个规则实现为私有成员函数。这些成员函数很小且明确命名,因此代码变得非常易读。对它编写测试也非常容易。


不仅仅是这种情况,这个函数处理弹性布局也是如此,但还是谢谢你的想法!我猜很快就会用到它 :-) - MadRunner

0

0

你所描述的是编译器将从你的代码中生成的内容 :) 因此,你实际上是在提出一种嵌套式编程语言,这会带来格林斯潘定律:“任何足够复杂的 C 或 Fortran 程序都包含了一个特定于应用、非正式指定的、错误丛生的、运行缓慢的 Common Lisp 的一半实现。”

有更好的方法来编写这段代码以表达你的条件。当你有很多嵌套的 if() { if () { if() } } } 时,通常只需编写 if (!condition) break; 或其他跳出方法,就可以简化代码。虽然不总是如此,但大多数情况下都是如此。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接