Question

Problem:

Suppose I have a set of functions f_1 ... f_n that I want to compose at runtime, such that I get for example:

(f_a (f_b (f_c) (f_d)) (f_e))

Therefore I need the types of the parameters and the return value of each function in order to know, which functions I can plug into each other.

First Attempt: Annotate each function

(defn foo [n f]
  ^{:params [Number clojure.lang.Fn]
    :return String}
  (do stuff with f and n, return a string))

I don't like this approach because of obvious reasons, such as if I wanted to use clojure.core as the set of functions I would have to annotate every function, which wouldn't be very desirable.

Questions

  1. How would you attempt to solve this problem?

  2. Could core.typed help me with that?

Was it helpful?

Solution

I do similar things when composing the search query to pass to solr and use a map for the arguments to all the functions and have them all return a map with whatever changes the function decided to make contained in the map, and everything else returned unchanged. So in short i would:

  1. use a map for the input and output of every function
  2. core.typed is not helpful because everything is a map
  3. prismatic.schema is very helpful because you can use it to know what keys are required and to write tests that validate the structure of these maps.

Projects/people with more of an inclination to statically typed functional languages will likely turn to monads in cases like this because they are a powerful tool for describing composition in a type safe way.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top