Using \numexpr
from the eTeX-extensions one can easily implement a tail-recursive loop.
\documentclass[a4paper]{article}
\begingroup
\makeatletter
\@firstofone{%
\endgroup
\newcommand\PassFirstToSecond[2]{#2{#1}}%
\newcommand{\folieloop}[2]{%
\expandafter\PassFirstToSecond\expandafter{\number#2}%
{\expandafter\folieloopnormalizednumbers\expandafter{\number#1}}%
}%
\newcommand{\folieloopnormalizednumbers}[2]{%
\ifnum#1>#2 %
\expandafter\@gobble\else\expandafter\@firstofone\fi
{%
\begin{frame}%
\begin{center}%
\includegraphics[scale=.5]{#1}%
\end{center}%
\end{frame}%
% Testing tail recursion without frames:
% Folie #1.\par
\expandafter\folieloopnormalizednumbers\expandafter{\number\numexpr#1+1\relax}{#2}%
}%
}%
}%
\begin{document}
\folieloop{1}{4} %from 1 to 4
\folieloop{\numexpr1+3-2}{4} %from 2 to 4
\newcounter{mycounter}
\setcounter{mycounter}{10}
\folieloop{\numexpr2+5}{\value{mycounter}} %from 7 to 10
\folieloop{14}{14} %only 14
\end{document}
In case you don't have eTeX-extensions, expandable incrementing can be implemented:
\documentclass[a4paper]{article}
\begingroup
\makeatletter
\@firstofone{%
\endgroup
%% \UD@increment{<non-negative integeral number k as sequence of
%% catcode-12(other)-character-tokens
%% from the set 0123456789>}
%% ->
%% <non-negative integeral number (k+1) as sequence of
%% catcode-12(other)-character-tokens
%% from the set 0123456789>
%%
%% Emptiness is interpreted as "0".
%%
%% !! There is no check implemented on the argument being a proper
%% digit sequence !!
%%
%% Leading zeros are not removed but the least significant leading zero
%% may get replaced by a carry-over "1".
%%
%% Examples:
%% \UD@increment{725} -> 726
%% \UD@increment{999} -> 1000
%% \UD@increment{00999} -> 01000
%% \UD@increment{00001} -> 00002
%% \UD@increment{0} -> 1
%% \UD@increment{} -> 1
%%
%% The result is delivered after two expansion-steps.
\newcommand\UD@increment[1]{%
\romannumeral0\UD@reverse{\UD@incrementfork{}}{\relax}{}#1\relax
}%
%%.........................................................................
%% \UD@reverse reverses \relax-delimited list of undelimited arguments.
%% From each undelimited argument the outermost level of surrounding
%% braces will removed if present.
%% #1 - Tokens to put in front of reversed list.
%% #2 - Tokens to put behind reversed list.
%% #3 - list elements collected in reversed order so far.
%% #4 - Current element of to-be-reversed list.
\newcommand\UD@reverse[4]{%
\ifx\relax#4%
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{#1#3#2}{\UD@reverse{#1}{#2}{#4#3}}%
}%
%%.........................................................................
%% \UD@incrementfork replaces the leading digit of a \relax-delimited
%% digit-sequence by the next higher digit. The leading digit that is
%% to be replaced is #2. #1 contains carryover-zeros in case
%% \UD@incrementfork is called recursively due to leading digits
%% being "9"s.
\newcommand\UD@incrementfork[2]{%
\UD@incrementselect
#2123456789\relax{\UD@reverse{ }{}{}#11}% <- replace leading digit 0 by 1
0#223456789\relax{\UD@reverse{ }{}{}#12}% <- replace leading digit 1 by 2
01#23456789\relax{\UD@reverse{ }{}{}#13}% <- replace leading digit 2 by 3
012#2456789\relax{\UD@reverse{ }{}{}#14}% <- replace leading digit 3 by 4
0123#256789\relax{\UD@reverse{ }{}{}#15}% <- replace leading digit 4 by 5
01234#26789\relax{\UD@reverse{ }{}{}#16}% <- replace leading digit 5 by 6
012345#2789\relax{\UD@reverse{ }{}{}#17}% <- replace leading digit 6 by 7
0123456#289\relax{\UD@reverse{ }{}{}#18}% <- replace leading digit 7 by 8
01234567#29\relax{\UD@reverse{ }{}{}#19}% <- replace leading digit 8 by 9
012345678#2\relax{\UD@incrementfork{#10}}% <- leading digit is 9, so add a carryover-0 and look at the next digit as leading digit.
0123456789#2{\UD@reverse{ }{}{}#11\relax}% <- No more digits left as
% either all digits were 9, thus as many carry-overs occurred as digits were present,
% or the digit-sequence was empty and thus considered 0.
0123456789\relax{\UD@reverse{ }{}{}#11#2}% <- The thing is not a digit. Thus put it back and end.
% Outermost level of braces surrounding the thing get removed.
% A better way of handling the situation would be checking whether
% \UD@increment's argument is a proper digit sequence.
% But is it worth the efforts?
% What about spaces within the argument? In case checking
% is to be implemented by means of undelimited arguments, beware
% in mind that space-tokens in front of undelimited arguments
% get silently discarded by (La)TeX. Also need to cope with single digits being nested in braces...
\relax\relax
}%
\newcommand\UD@incrementselect{}%
\long\def\UD@incrementselect#10123456789\relax#2#3\relax\relax{#2}%
%%-------------------------------------------------------------------------
\newcommand\PassFirstToSecond[2]{#2{#1}}%
\newcommand{\folieloop}[2]{%
\expandafter\PassFirstToSecond\expandafter{\number#2}%
{\expandafter\folieloopnormalizednumbers\expandafter{\number#1}}%
}%
\newcommand{\folieloopnormalizednumbers}[2]{%
\ifnum#1>#2 %
\expandafter\@gobble\else\expandafter\@firstofone\fi
{%
\begin{frame}%
\begin{center}%
\includegraphics[scale=.5]{#1}%
\end{center}%
\end{frame}%
% Testing tail recursion without frames:
% Folie #1.\par
\expandafter\folieloopnormalizednumbers\expandafter{\number\UD@increment{#1}}{#2}%
}%
}%
}%
\begin{document}
\folieloop{1}{4} %from 1 to 4
\folieloop{2}{4} %from 2 to 4
\newcounter{mycounter}
\setcounter{mycounter}{10}
\folieloop{7}{\value{mycounter}} %from 7 to 10
\folieloop{14}{14} %only 14
\end{document}