Domain
уже представлена как крайняя левая таблица в объединении: FROM domains JOIN ...
, поскольку она является первой таблицей, выбранной вами в списке выбора вашего запроса. Явное несвязанное соединение не является необходимым и приводит к вашей ошибке. Просто опустите его:
query = session.query(Domain.domain_name, Subdomain.subdomain_name, Title.title, Title.status, Title.response_len, Title.created_on, Title.updated_on)
query = query.join(Title).join(Subdomain)
Вы главным образом правы, если Вы говорите о CALL/JMP в x86 блоке или чем-то подобном. Основное различие:
Обычно, ВЫЗОВ является просто реализованным использованием функции удобства JMP. Вы могли сделать что-то как
movl $afterJmp, -(%esp)
jmp location
afterJmp:
вместо ВЫЗОВА.
Вы точно правы относительно различия между переходом и вызовом.
В демонстрационном случае единственной функции с хвостовой рекурсией, затем компилятор может снова использовать существующий стековый фрейм. Однако это может стать более сложным со взаимно рекурсивными функциями:
void ping() { printf("ping\n"); pong(); }
void pong() { printf("pong\n"); ping(); }
Рассматривают случай, где ping () и вонь () является более комплексными функциями, которые берут различные числа параметров. статья Mark Probst переговоры о реализации хвостовой рекурсии для GCC в мельчайших подробностях.
Я думаю, что Вы в общих чертах поняли.
Это зависит от архитектуры, но в целом, на аппаратном уровне:
команда перехода А изменится счетчик команд для продолжения выполнения в другой части программы.
команда вызова А продвинет текущее местоположение программы (или текущее местоположение + 1) к стек вызовов и перейдет к другой части программы. Инструкция по возврату затем вытолкает местоположение прочь стека вызовов и перейдет назад к исходному местоположению (или orignal местоположение + 1).
Так, команда перехода близко к GOTO
, в то время как команда вызова близко к процедурному / вызову функции.
кроме того, по причине, что стек вызовов используется при создании вызовов функции, продвижении слишком многих обратных адресов к стеку вызовов рекурсией, вызовет переполнение стека .
При изучении блока, я нахожу это легче при контакте с процессоры RISC, чем x86 процессоры, поскольку это имеет тенденцию иметь меньше инструкции и более простых операций.