Факториал Scala на больших количествах иногда разрушает и иногда не делает

Порядок, в котором указываются взаимозависимые связанные библиотеки, неверен.

Порядок, в котором связаны библиотеки, имеет значение, если библиотеки зависят друг от друга. В общем, если библиотека A зависит от библиотеки B, то libA ДОЛЖНЫ появляться перед libB в флагах компоновщика.

Например:

// B.h
#ifndef B_H
#define B_H

struct B {
    B(int);
    int x;
};

#endif

// B.cpp
#include "B.h"
B::B(int xx) : x(xx) {}

// A.h
#include "B.h"

struct A {
    A(int x);
    B b;
};

// A.cpp
#include "A.h"

A::A(int x) : b(x) {}

// main.cpp
#include "A.h"

int main() {
    A a(5);
    return 0;
};

Создать библиотеки:

$ g++ -c A.cpp
$ g++ -c B.cpp
$ ar rvs libA.a A.o 
ar: creating libA.a
a - A.o
$ ar rvs libB.a B.o 
ar: creating libB.a
a - B.o

Скомпилировать:

$ g++ main.cpp -L. -lB -lA
./libA.a(A.o): In function `A::A(int)':
A.cpp:(.text+0x1c): undefined reference to `B::B(int)'
collect2: error: ld returned 1 exit status
$ g++ main.cpp -L. -lA -lB
$ ./a.out

Итак, повторить еще раз, порядок DOES важно!

10
задан Liran Orevi 27 July 2009 в 12:53
поделиться

2 ответа

Tail- Оптимизация вызова будет работать в Scala только в том случае, если рекурсивный вызов является последним оператором в функции. Это очень ограничено. В книге Scala говорится:

[...] оптимизация хвостового вызова - это ограничивается ситуациями, в которых метод или вложенная функция вызывает себя непосредственно как его последняя операция, не проходя через значение функции или какой-либо другой посредник.

В вашем случае рекурсивный вызов является частью более крупного выражения и сам по себе не является самой последней операцией - последней операцией здесь является умножение.

В этой статье показано, как это сделать заставить его работать:

class Factorial {
  def factorial(n: Int): Int = {
    def factorialAcc(acc: Int, n: Int): Int = {
      if (n <= 1) acc
      else factorialAcc(n * acc, n - 1)
    }
    factorialAcc(1, n)
  }
}
13
ответ дан 3 December 2019 в 18:35
поделиться

В Scala 2.8 вы можете использовать аннотацию @tailrec, когда ожидаете, что должна использоваться оптимизация хвостового вызова, и получить предупреждение, если компилятор не может это сделать.

7
ответ дан 3 December 2019 в 18:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: