Just about every language with iterators uses effectively syntactic sugar for them.

Java and C# uses the Iterable interface; C++ uses duck-typing with begin(), end() member functions and a few operator overloads on the iterator object; D also does duck-typing but you need to explicitly give the foreach construct the range object (usually with the opRange operator overload).

With function overloading you can do much of the same

 1 2 3 for el in container { //... } 

could translate to

 1 2 3 4 for it:= iterator(container); finished(it); advance(it) { el := element(it); //... } 

Then it's up to the use code to follow the contracts.

But I don't really like duck-typing because that you rely on overloads not necessarily local to each other. I'll get into that further in another topic.