foreach over split string

JS js.mdnq at gmail.com
Wed Jul 17 23:39:25 PDT 2013


On Thursday, 18 July 2013 at 05:57:48 UTC, H. S. Teoh wrote:
> On Thu, Jul 18, 2013 at 07:23:57AM +0200, JS wrote:
> [...]
>> Thanks, this has made it much clearer.
>> 
>> Something like
>> 
>> foreach(a; StrSplit!(s))
>>    foreach(b; StrSplit !(a))
>> 
>> does work because the second StrSplit uses a "ctfe-time 
>> variable"
>> instead of a "template-time variable".
>> 
>> My logic was:
>> 
>> 1. first StrSplit resolved
>> 2. first foreach evaluated
>> 3. second StrSplit resolved
>> 4. second foreach evaluated
>> 
>> while it actually is
>> 
>> 1. first StrSplit resolved
>> 2. second StrSplit resolved
>> 3. foreach's resolved
>> 
>> because template expansion happens before any ctfe expansion.
>> 
>> I guess I was thinking the compiler would be smart enough to
>> interleave template expansion and ctfe code(which would be 
>> much more
>> powerfull).
>> 
>> Effectively template expansion is a sort of pre-processing to 
>> ctfe
>> code and must be static as far as ctfe's go.
> [...]
>
> That's one way to think of it, yes.
>
> As for interleaving template expansion vs. ctfe evaluation, the 
> compiler
> *does* do that to some extent.  For example, this code does 
> work:
>
> 	// Function that can be evaluated by CTFE
> 	int func(int x) pure {
> 		int sum;
> 		foreach (i; 0..x) {
> 			sum += i;
> 		}
> 		return sum;
> 	}
>
> 	// Force CTFE evaluation
> 	enum myConst = func(10);
>
> 	// Template that requires an int parameter.
> 	template MyTemplate(int x) {
> 		enum MyTemplate = x+10;
> 	}
>
> 	// Instantiate template with enum produced by CTFE.
> 	pragma(msg, MyTemplate!myConst);
>
> 	void main() {}
>
> The reason this works is because the compiler is smart enough 
> to figure
> out that myConst requires func, so it first compiles func far 
> enough to
> be CTFE-evaluable, then it evaluates func to produce the value 
> of
> myConst, and then myConst is used to instantiate MyTemplate. 
> You could
> think of it as the compiler compiling different parts of the 
> program at
> different rates, so func has been compiled into a runnable 
> state, but
> the pragma(msg) line is still at the template expansion state.
>
> Note, however, that the template-before-CTFE limitation still 
> applies:
> func can't require template expansion while it's running; it 
> must be
> entirely compilable into runnable state before CTFE can 
> evaluate it.
> Other parts of the program can still remain at the 
> template-expansion
> stage, so they can take some CTFE-produced values as template
> parameters. But you can't make any reverse dependencies / 
> loops.  You're
> OK if you already have runnable code that can then produce 
> template
> parameters for other code, but you can't run CTFE and template 
> expansion
> simultaneously in the *same* code.
>
> So the compiler is actually pretty smart about reordering these 
> things,
> but the fundamental limitation of template-before-CTFE still 
> applies to
> each individual code unit. After all, you can't run code that 
> hasn't
> been fully expanded by the template system yet.
>
>
> T

Thanks. Your reply was extremely helpful and I think I'll have 
less pms over ctfe's.




More information about the Digitalmars-d-learn mailing list