I’ve seen this question but it doesn’t help me because I’m writing functional code (Standard ML) and the answers there are heavily focused towards OOP (the OP is advised to use the Facade pattern, to use inheritance, etc — answers that are not relevant to an SML programmer).
In two separate, largely unrelated modules, Foo
and Bar
, I need to accomplish the same task: given functions equal
and equals
with the signatures:
val equal: t * t -> bool
val equals: t list * t list -> bool
make two new functions with the following signatures:
val equal': t * t -> t option
val equals': t list * t list -> t list option
Here, t
stands for either Foo.t
or Bar.t
. The natural solution is to use a higher order function:
local
fun boolToOpt (comparison: ('a * 'a) -> bool) (left, right) =
if comparison (left, right) then
SOME left
else
NONE
in
val equal' = boolToOpt equal
val equals' = boolToOpt equals
end
I need to repeat exactly this code snippet in both modules.
Now, this is a tiny, minor implementation detail, and it would be a bad idea to let it be publicly visible from either Foo
or Bar
. At the same time, it seems too small — and too tightly coupled to the two equal(s)
functions — to be factored out in to a module of its own. Maybe in another language, the equals'
functionality would merit its own class, say, ComparisonDecorator
, that overrides equal(s)
to give me functions with the return type t option
, but that’s not an option here.
I run in to situations like these at least once per day. Is there a sane way to avoid just copy+pasting here?
4
If you have absolutely no idea of a good abstraction for a module, put the function in a generic utility module, at least temporarily. And after you found several utility functions, you will probably identify some of them “belonging together”. That will give you a hint for a common module name for these group of functions, so you can finally move them from the utility module into a module with a better name.
Just be careful not to let your utility module grow arbitrarily – from time to time, you have to clean up things there, otherwise you will reach a point where you don’t know what’s in there and what’s not.