I think streams+lambdas sometimes violate the single responsibility principle and sometimes don't. Sequencing of other operations is a "single thing" for the purposes of SRP. That's what streams do. If you mix that too much with defining the other operations, which is what lambdas do, you can get into a situation where you are no longer doing a "single thing."
Consider the following function from this question:
const getPctSameXs = (getX, filter = vals => vals) =>
(objA, objB) =>
filter(getXs(objB, getX))
.reduce(
(numSame, x) =>
getXs(objA, getX).indexOf(x) > -1 ? numSame + 1 : numSame,
0
) / Object.keys(objA).length * 100;
Here the lambdas make it really difficult to determine the sequencing. Consider my response that accomplishes the same task:
function getPctSameXs(obj1, obj2, f) {
const mapped1 = mapObj(obj1, f);
const mapped2 = mapObj(obj2, f);
const same = mapped1.filter(x => mapped2.indexOf(x) != -1);
const percent = same.length / mapped1.length * 100;
return percent;
}
SRP purists would probably want to move some of this into separate functions, but this is roughly at the same level of abstraction, and the sequencing is easy to see.
In other words, a syntactic construct like a stream neither fulfills nor violates a principle on its own. It's about how you use it.
I feel like Lambdas, in general, have single responsibilities however when we use streams we use many lambda expressions chained,together (map, iterate etc). So streams violate SRP according to my understanding.
But each of these functions (map, iterate, etc) has a single purpose, and they all operate on the same Stream type. You don't see the value and elegance in that?