proposition: declarative computation is one that is compiled or interpreted into something with lower control flow. consider lisp: your DSL can have control flow if the macros process the control flow forms (if, lambda) into some lower thing (that lower thing often being lisp itself but after all macroexpansion). I.e. reactive DSL is declarative with respect to when recomputation happens and when memoization happens, the programmer does not specify these aspects they are implied. however the same DSL can still be imperative with respect to effect sequencing.
another is programming with DAGs, the DAG captures control flow schematics as a value, abstracting away the actual evaluation rules (maybe the DAG is meant to be async, or reactive, or distributed). The DAG is declarative with respect to the abstracted evaluation rules, yet if there are effects in DAG nodes, we are not declarative with respect to those. We are however declarative with respect to how effects with a lifecycle are maintained and garbage collected, as that behavior is given by certain runtimes for the DAG.
another is programming with DAGs, the DAG captures control flow schematics as a value, abstracting away the actual evaluation rules (maybe the DAG is meant to be async, or reactive, or distributed). The DAG is declarative with respect to the abstracted evaluation rules, yet if there are effects in DAG nodes, we are not declarative with respect to those. We are however declarative with respect to how effects with a lifecycle are maintained and garbage collected, as that behavior is given by certain runtimes for the DAG.