About having separate features `item` and `remove` is class STACK,
I think that they deserve to be there. If I just want to get the
last inserted element in the stack, I prefer to write:
v := stack.item
rather than:
v := stack.pop
stack.push (v)
Likewise, if I just want to remove the last inserted element in
the stack, I prefer to write:
stack.remove
rather than:
stack.pop.do_nothing
Now, if people want to have more complex routines like `pop`,
or `pop_and_push_and_push_and_pop_again_and_call_f_on_it`,
so be it.
Note that I'm not a strick defenser of the CQS principle. You
will certainly find code in Gobo Eiffel violating this principle.
It's just that when I saw the example using Fluent, I was not
convinced that the code looked cleaner.
On 27/12/2025 12:31, Liberty Lover wrote:
> Eric,
>
> One additional data point worth noting: Martin Fowler, in his https://
>
martinfowler.com/bliki/CommandQuerySeparation.html <https://
>
martinfowler.com/bliki/CommandQuerySeparation.html>, directly addresses
> Meyer's own pragmatism on this:
>
> "Meyer likes to use command-query separation absolutely, but there
> are exceptions. Popping a stack is a good example of a query that
> modifies state. Meyer correctly says that you can avoid having this
> method, but it is a useful idiom."
>
> So even Meyer himself acknowledges that pop (which both returns a value
> AND modifies state) is a "useful idiom" - a pragmatic exception to his
> own principle.
>
> The fluent builder pattern falls into this same category: a transparent,
> predictable deviation that provides ergonomic value. Like pop, you could
> avoid it (separate set_* procedures + a final query), but the fluent
> form is a useful idiom that clearly communicates intent.
>
> I also note that your Gobo library takes the strict approach (separate /
> item /and /remove/), which is a valid choice. The simple_* libraries
> make a different valid choice. Both are defensible - CQS is a principle
> to be interpreted, not a law to be mechanically enforced.
>
> On Sat, Dec 27, 2025 at 6:18 AM Liberty Lover <
rix....@gmail.com
> <mailto:
rix....@gmail.com>> wrote:
>
> Hey Eric,
>
> On CQS "Violations"
>
> I agree that CQS is a valuable design principle, and I think it is
> interesting for anyone else reading (including myself) to note that
> CQS violations cannot be statically detected by a compiler. I think
> the reason for that is that in order to detect "does this function
> modify state?", the compiler would need to solve the Purity Analysis
> Problem - tracing through all transitive calls, handling
> polymorphism, external code, etc. This is undecidable in the general
> case.
>
> So, this leaves CQS as a human-interpreted guideline, not one that
> can be a mechanically compiler-enforced rule, which means or may mean:
> - Developers must use their own judgment about when violations
> are acceptable
> - The Eiffel ecosystem has always had pragmatic exceptions
> (iterators, certain container operations)
> - A /transparent/, /obvious /violation isn't the same as a /
> dangerous /one
> -
https://dl.acm.org/doi/10.1145/161494.161501 <https://
>
dl.acm.org/doi/10.1145/161494.161501>
> - Proves static analysis problems are undecidable via reduction
> to the halting problem
>
> 2. Purity Analysis Research
>
> Sălcianu, A. & Rinard, M. "Purity and Side Effect Analysis for
> Java Programs" - VMCAI 2005, Springer
> -
https://link.springer.com/chapter/10.1007/978-3-540-30579-8_14
> <
https://link.springer.com/chapter/10.1007/978-3-540-30579-8_14>
> - Defines purity analysis and shows it requires sophisticated
> pointer/escape analysis
> - Even their advanced analysis can only determine purity "when
> mutation affects only objects created after method invocation"
>
> 3. Side Effect Detection in Compilers
>
> Spuler, D. & Sajeev, A. "Compiler Detection of Function Call Side
> Effects"
> mailto:
er...@gobosoft.com <mailto:
er...@gobosoft.com>
>
http://www.gobosoft.com <
http://www.gobosoft.com>