在玩NLP的过程中我遇到了一些小问题:
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;
}
这种“计算树”有哪些替代方案?我唯一想到的东西 - 一些带有函数指针作为树叶的树容器以及大量的小函数。
答案 0 :(得分:4)
(舌头)每次在C ++程序中遇到switch
语句时,您都知道自己错过了继承机会。
我知道重构多个并行开关的两种方法是:(1)构建函数指针的多维数组,以及(2)使用visitor pattern的变体。
答案 1 :(得分:1)
一个很好的解决方法是使用矩阵。
如果您知道无论如何都要评估所有条件,这将很有效。
创建一个多维数组,将true-false值映射到处理函数。
Arrayswitch[var1][cond1][cond2][cond3][var2]();
答案 2 :(得分:1)
当代码开始看起来像这样时,我开始寻找数据驱动的方法。它可能像表一样简单,也可能像你建议的那样带有函数指针的树。
如果这是某种手动解析器,您可能需要查看一些关于解析如何使用语法定义进行解析的想法的引用(通过按需解释语法,或者使用使用语法作为输入的代码生成工具。
我经常手动滚动递归下降解析器。通常,我创建一个保存状态的类,公开一个公共“Parse”函数,并将每个规则实现为私有成员函数。这些成员函数很小并且显式命名,因此代码变得非常易读。为它编写测试也很容易。
答案 3 :(得分:0)
答案 4 :(得分:0)
你所描述的是编译器将从你的代码中产生的东西:)所以你基本上提出了一种嵌套的编程语言,它引出了Greenspun定律:“任何足够复杂的C或Fortran程序都包含一个特殊的,非正式指定,错误缠身,一半Common Lisp的缓慢实现。“
有很多方法可以更好地编写此代码来表达您的条件。当你有很多嵌套的if() { if () { if() } } }
时,通常只是编写if (!condition) break;
或其他转义方法,简化了代码。并非总是很多次。