Hacker News new | ask | show | jobs
by wruza 1317 days ago
This is also not declarative vs imperative. It is declarative with a functionalty vs imperative without it. A shell script could also check which parts are missing or outdated and do incremental build. I’m not any good at shell scripting so here is a similar pseudocode:

  import cc, ld, glob, make

  // make defined as:
  fn make(to, from, how) {
    if (exists(to) && mtime(from) <= mtime(to) {
      return
    }
    how(to, from)
  }

  make("foo.o", "foo.c", cc)
  …
  make("a.out", glob("*.o"), ld)
It’s basically the same as Makefile, except that out “make script” doesn’t know about goals anymore, only steps to take. Do we need that goal-knowledge in a declarative format is an open question, because you can wrap these make() calls in a function named aout() and that becomes your declarative goal. However declarative your config/data is, you still pass it to some evaluator like `make` at the end of the day.
1 comments

An important difference here is that your shell script executes the steps in the order you defined. Make performs a topological sort on the required rules, so in the general case, a Makefile doesn't explicitly define the ordering of the steps, but instead the make runtime figures out an order on its own based on the dependencies.

The Makefile is a (default) goal and a sea of possible actions from which make creates a plan of action.

The shell script steps are manually ordered by the programmer.