How to? Just verification for what I think I know regarding "Function"...

  • This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.
#1
It seems to me that there is no way to have a function recursively call itself either directly or indirectly (i.e., through an "intermediate" function of some kind). Am I right about that?

- Dan
 

Charles Dye

Super Moderator
Staff member
May 20, 2008
3,383
39
Albuquerque, NM
prospero.unm.edu
#2
It seems to me that there is no way to have a function recursively call itself either directly or indirectly (i.e., through an "intermediate" function of some kind). Am I right about that?
There is some mechanism in ExpandVariables() to detect, and I assume prevent, recursion.

Batch files can call themselves recursively. I don't know what the maximum depth is -- in 4DOS days it was pretty sharply limited by the size of the stack, but that may not be true in TCC.
 
#3
Charles, you pretty much confirmed what I thought, but the reason is actually a bit "deeper" than that, I think. The only way that I know of that even has the possibility of a function selectively either calling itself recursively or not to is to use the "@If" function, and it is my understanding/recollection that "@If " fully evaluates both the "true" expression and the "false" expression regardless of whether the "condition" itself is true or false. If both "string1" and "string2" are always evaluated (similar to the way "&" vs. "&&" work in C and C++) then recursion is inherently impossible; and ultimately the question was whether on not both "string1" and "string2" are always evaluated, and again, I believe that they are.

And the implication of this is that there are situations where you always have to use a subroutine (which can call itself recursively (somewhat dangerous because there is a maximum subroutine "depth" limit of 22 in the simple tests that I've done but that may vary based on other factors related to what's on the stack) or do what it needs to done in a loop (a far better idea!)), or use something like "@ExecStr" (which has a maximum recursion depth of 32, it would appear), for example. But none of those are as convenient as a function calling itself recursively, and that is far more "elegant" in my opinion (I strive for "elegance" in my code, I must admit) then any of the first three "solutions".

- Dan
 
#5
Vince, you are, of course strictly speaking, correct; I was trying to illustrate a "concept" with the only example I could think of "off the top of my head", as the saying goes. (And the fact that "condition2" is not evaluated for "&&" if "condition1" is false was exactly point I was trying to make because for the "&" operator both operands are "fully" evaluated.) If there's another language with the equivalent of the "@If" function - and I seem to dimly remember that there is but I can't think of it at the moment - I would imagine that its parser would be able to unambiguously identify both "string1" and "string2" such that only the "appropriate" "string" would be evaluated (if it's an interpreter; code generated if it's a compiler). That is clearly not the case for Rex's parser for whatever reason (and if you read this Rex, that's not a criticism, just an observation); and again I was just looking for absolute verification of that fact because it is clearly not, for whatever reason, what I would have expected.

And, after I originally wrote the above, it dawned on me exactly what the issue is: I was essentially thinking about @If as an operator (just as + and - and .OR. and .AND., etc., are operators), and not as an actual function, and if you carefully read the above you will see that that is the case. And that's exactly the point. If it really is a "function" (which it seems to be in the TCC batch-file language), then of course all its arguments are fully evaluated before actually executing the "body" of the function, whatever that may be. However, my experiences with such a "concept" in the past have almost, if not always, been in the context of a preprocessor of one kind or another in a compiled language, where the preprocessor essentially generates code that is/is not executed based on whether the "condition(s)" evaluate to "true" or "false" and therefore this "problem" is not at all an issue. However, in the context of TCC it would seem that it clearly is a function in the "traditional" sense, and hence it behaves the way it does. (And, I will add as two side notes here that, number 1, a very large proportion the code I have written in the past has been preprocessor code; I think my ability to do that was one of my major "strengths" as a programmer. In fact, I think that it can be fairly said that, in some instances, the total "collection" of my (domain-specific) preproccessor code was almost a language in and of itself. And, number 2, an interpreter could also certainly be written to "emulate" the way preprocessor functions are written in compiled languages when those "functions" are an inherent part of the language (as @If is as opposed to a user-written function) because the bottom line is that, in many ways, an interpreter is a preprocessor at a very "deep" level.) (And again, Rex, this is just an "observation" and not a criticism.)

- Dan