names.forEach(print); implements a pattern called first-class functions. This pattern dictates that functions can be treated just like any other variable. They can be stored as closures or even passed around to different functions.
The forEach() function expects a function with the following signature:
void Function<T>(T element)
The print() function has the following signature:
void Function(Object object)
Since both of these expect a function parameter and the print function has the same signature, we can just provide the print function as the parameter!
// Instead of doing this
data.forEach((value) {
print(value);
});
// We can do this
data.forEach(print);
This language feature can make your code more readable.