Why does ForEach for tasks instead of targets

  • I have a general question. I'm using ForEach, and it works,  but it seems clumsy because of the way that it requires a target. Is there a reason that it doesn't work more like, for example, the "if" task, so that I can just put tasks in it?

    For example, I'd like:

    <!-- Get an up to date copy of all files -->
    <foreach param="file"">
        <fileset dir="cachedFiles"/>
        <get src="http://sourceHost/${file}" dest="${file}"/>

    It seems like foreach actually creates a sub-version of ant for each iteration, which makes a simple loop like this quite slow. Is this all necessary because of ant's insistence that properties are global and unchangeable? And, is there a way to improve the current foreach so that it will be simpler and faster?


    • Matt Inger
      Matt Inger

      It's a limitation of the way earlier versions of ANT work.  If you were to do the following:

      <foreach list="a,b,c" param="letter">
         <echo message="${letter}" />

      when the "foreach" task instance is created (not evaulated), so is the <echo> task underneath, and the ${letter} is evaluated at that time.  Thus, there is no parameterization, and ${letter} would not even be set to anything.  so you'd end put with the following output:

      [echo] ${letter}
      [echo] ${letter}
      [echo] ${letter}

      There is no workaround for this in earlier versions of ant.  However, in ANT 1.6, the MacroDef facility allows us a way to do it.  But to maintain backward compatibility, we created a seperate task for it:

      <for list="a,b,c" param="letter">
           <echo>Letter @{letter}</echo>

      The taskd are created as a MacroDef instance, and as a result @{letter} is evaluated when the macro itself is evaluated.  So each time through the loop, we can set the macro parameter, and evaluate the macro, thus producing the correct results.