On Sat 28 Dec 2013 at 12:21:22AM -0800, Mark Engelberg wrote:

> You have to thread your shared state through all the functions (what
> I described as "Solution 2"), and if you don't want the difficulty of
> refactoring to that way of doing things, you better just do it that
> way from the beginning.

I agree that the approach outlined by Component is essentially your
Solution 2 + "stop complaining and just do it this way".

You stated earlier:

> Solution 2 is irritating because if you use a map for shared-info, you
> end up having to repeat the destructuring in every single function.
> Also, you need to thread this information through all the functions,
> not only the functions that directly use, but also the functions that
> call other functions that use it.

This is where one could argue that passing the entire local context to
every function to approximate the convenience of OO is sloppy design. I
have found that carefully writing functions in terms of very specific
input has resulted in very modular, reusable, and testable code.

Of course, this is no surprise; these are the rewards of FP. Writing
programs in this fashion often feels difficult because it demands more
design up front, whereas writing closures/methods in the environmental
soup of the namespace/global configuration/instance is really quite easy
because all the necessary data is at hand.

> Furthermore, it would be absurd to have to thread some precision
> variable as the first input to every single arithmetic operation. Can
> you imagine how annoying Clojure would be if it made you do that?
…
> So we have a dilemma -- it's awkward to thread decimal precision
> through all operations, and binding isn't good enough.

It would be annoying if it were mandatory, but it is easy to make it
optional.

Alternately, you could create versions that take an explicit precision
argument, then write a macro that takes a precision and rebinds the
these arithmetic fn symbols with partially applied versions within the
body:

    (defn +. [precision & xs] …)
    (defn *. [precision & xs] …)
    …
    (defmacro with-precision [precision & body]
      `(let [~'+ ~(partial +. precision)
             …]
         ~@body))

The amount of magic in this macro can be adjusted to taste, but it will
work with lazy-seq, and is also pretty convenient.

> Can we do better?

Overall, it seems to me that you are looking for a better way to
manage implicit parameters¹. However, I imagine a sizable part of this
community is here precisely because of negative experiences with systems
with large amounts of implicit data. To the extent this is true, you're
likely to get the same "don't do that" as a response.

    guns

¹ Perhaps with something akin to an instantiable namespace? :)

Attachment: pgpoYxal8Gnkm.pgp
Description: PGP signature

Reply via email to