我正在编写表示一组整数的类。这是我的方法:
var Tabs = React.createClass({
displayName: 'Tabs',
propTypes: {
selected: React.PropTypes.number,
children: React.PropTypes.oneOfType([
React.PropTypes.array,
React.PropTypes.element
]).isRequired
},
getDefaultProps: function () {
return {
selected: 0
};
},
getInitialState: function () {
return {
selected: this.props.selected
};
},
shouldComponentUpdate(nextProps, nextState) {
return this.props !== nextProps || this.state !== nextState;
},
handleClick: function (index, event) {
event.preventDefault();
this.setState({
selected: index
});
},
_renderTitles: function () {
function labels(child, index) {
var activeClass = (this.state.selected === index ? 'active' : '');
return (
<li key={index}>
<a href="#"
className={activeClass}
onClick={this.handleClick.bind(this, index)}>
{child.props.label}
</a>
</li>
);
}
return (
<ul className="tabs__labels">
{this.props.children.map(labels.bind(this))}
</ul>
);
},
_renderContent: function () {
return (
<div className="tabs__content">
{this.props.children[this.state.selected]}
</div>
);
},
render: function () {
return (
<div className="tabs">
{this._renderTitles()}
{this._renderContent()}
</div>
);
}
});
var Pane = React.createClass({
displayName: 'Pane',
propTypes: {
label: React.PropTypes.string.isRequired,
children: React.PropTypes.element.isRequired
},
render: function () {
return (
<div>
{this.props.children}
</div>
);
}
});
var App = React.createClass({
render: function () {
return (
<div>
<Tabs selected={0}>
<Pane label="Tab 1">
<div>This is my tab 1 contents!</div>
</Pane>
<Pane label="Tab 2">
<div>This is my tab 2 contents!</div>
</Pane>
<Pane label="Tab 3">
<div>This is my tab 3 contents!</div>
</Pane>
</Tabs>
</div>
);
}
});
ReactDOM.render(<App />, document.querySelector('.container'));
然后我定义两组:
Uncaught TypeError: Cannot read property 'number' of undefined
并尝试在它们上调用abstract class IntSet {
def incl(x: Int): IntSet
def union(x: IntSet): IntSet
def union1(x: IntSet): IntSet
}
class Empty extends IntSet {
def incl(x: Int) = new NonEmpty(x, new Empty, new Empty)
def union(x: IntSet) = x
def union1(x: IntSet) = x
}
class NonEmpty(var elem: Int, var left: IntSet, var right: IntSet)
extends IntSet {
def incl(x: Int) = {
if (x < elem) new NonEmpty(elem, left incl x, right)
else if (x > elem) new NonEmpty(elem, left, right incl x)
else this
}
def union(x: IntSet) = ((left union right) union x) incl elem
def union1(x: IntSet) = ((left union1 x) union1 (right union1 x)) incl elem
}
:
调用 val one = new NonEmpty(2, new Empty, new Empty).incl(5).incl(12)
val two = new NonEmpty(1, new Empty, new Empty).incl(17).incl(12)
效果很好,但是union()
会导致StackOverflow异常。
我知道递归函数必须导致非递归定义的值是有限的。在第一种情况(联合)中这些值是什么?为什么在第二种情况(联合1)中程序不能达到那些定义的值?
一般的问题更多是关于数学理论而不是Scala,但是在编写递归函数以使其有限时是否有任何技巧(规则)要坚持?
答案 0 :(得分:1)
通常,您需要减少一个参数才能得出基数
案件。您的示例有点复杂,但是union1
本质上有两个
参数:x
和this
(出于我们的目的,this
可被视为
“参数”)。您的基本情况是this
为Empty
时,让我们看看是否
您减少了this
。
现在,您对union1
进行了三个递归调用。让我们看一下两个简单的
一个:left union1 x
和right union1 x
。在这些中,您绝对是
在this
上减少。 left
和right
必须小于this
,因为它们
不包含elem
。这样很好,您肯定会遇到以下情况:
this
是Empty
。
第三个(left union1 x) union1 (right union1 x)
是另外一个故事。
由于它还包含左侧的所有x
,因此不会
this
时this == x
减少。例如,考虑采取
简单集合与自身的并集。让\/
代表union1
,+
代表
incl
。这是代码计算{1} \/ {1}
的基本概念:
{1} \/ {1}
(({} \/ {1}) \/ ({} \/ {1})) + 1
({1} \/ {1}) + 1
...
我们现在需要再次计算{1} \/ {1}
,因此我们将无限重复此操作。
因此,通常,请确保至少有一个参数具有基准
的情况正在减少。要完全避免堆栈溢出,您还应该使用
使用@tailrec
annotation进行尾部递归以处理非常大的
设置,或者找到一种方法来使用现有的高阶函数而不是递归。