是什么使递归函数有限

时间:2018-07-14 01:05:28

标签: scala recursion

我正在编写表示一组整数的类。这是我的方法:

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,但是在编写递归函数以使其有限时是否有任何技巧(规则)要坚持?

1 个答案:

答案 0 :(得分:1)

通常,您需要减少一个参数才能得出基数 案件。您的示例有点复杂,但是union1本质上有两个 参数:xthis(出于我们的目的,this可被视为 “参数”)。您的基本情况是thisEmpty时,让我们看看是否 您减少了this

现在,您对union1进行了三个递归调用。让我们看一下两个简单的 一个:left union1 xright union1 x。在这些中,您绝对是 在this上减少。 leftright必须小于this,因为它们 不包含elem。这样很好,您肯定会遇到以下情况: thisEmpty

第三个(left union1 x) union1 (right union1 x)是另外一个故事。 由于它还包含左侧的所有x,因此不会 thisthis == x减少。例如,考虑采取 简单集合与自身的并集。让\/代表union1+代表 incl。这是代码计算{1} \/ {1}的基本概念:

{1} \/ {1}
(({} \/ {1}) \/ ({} \/ {1})) + 1
({1} \/ {1}) + 1
...

我们现在需要再次计算{1} \/ {1},因此我们将无限重复此操作。

因此,通常,请确保至少有一个参数具有基准 的情况正在减少。要完全避免堆栈溢出,您还应该使用 使用@tailrec annotation进行尾部递归以处理非常大的 设置,或者找到一种方法来使用现有的高阶函数而不是递归。