> this acts to insert all lines of the named procedure into the executing program at the point where the call occurred
...is quite dubious, perhaps it works in Logo, but in many languages it would raise scoping issues at the very least. Procedures calls are not in general the equivalent of textually cutting and pasting the procedure's code. Given that Logo has dynamic scoping, perhaps it works - but that's an issue in itself, dynamic scoping is hard to reason about in general.
Aside from the dynamic scope issue I mentioned (which someone else has expanded on), this doesn't work for languages that support closures. "Fully qualifying" names doesn't help there. And OO languages would have similar issues for much the same reason.
Most programming languages today don't have dynamic scoping. Here's something you could do in a language that had it.
print_x() {
print(x);
}
foo(msg) {
let x = msg;
print_x();
}
main() {
let x = "Hello!";
print_x();
foo("Goodbye!");
print_x();
}
In a language with dynamic scoping, this would print:
Hello!
Goodbye!
Hello!
With lexical scoping, most dynamically scoped code would either be a compilation error, or it wouldn't work. In this case, the language would complain that x wasn't defined in the scope of "print_x()". With lexical scope, you'd have to make x a global variable, and then the function foo() would just be equivalent to calling print_x().
> this acts to insert all lines of the named procedure into the executing program at the point where the call occurred
...is quite dubious, perhaps it works in Logo, but in many languages it would raise scoping issues at the very least. Procedures calls are not in general the equivalent of textually cutting and pasting the procedure's code. Given that Logo has dynamic scoping, perhaps it works - but that's an issue in itself, dynamic scoping is hard to reason about in general.