ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Jose Alberto Fernandez" <>
Subject RE: What is a 'declarative' language [ was Re: [VOTE] vote on general direction ...]
Date Mon, 26 Mar 2001 23:30:59 GMT
Well, I did not want to start the battle of the technicalities but I think
we need to make some things clear.

Prolog is NOT a declarative programming language. It imposes a particular
well defined procedural execution model to the programs expressed using
Horn-clauses are a declarative way to define what you want to be solved.

Now, Horn-clauses are declarative because they do not tell you how to
execute your program, it just specifies what needs to be done, but not how.
A program written in Horn-clauses can be executed by PROLOG using the Depth
First Search order rule; or it can be executed by some other engine
implementing a Breath First Search algorithm, or its multiple choices can be
executed in parallel, or distributed over a network or whatever.

That is what declarative boils down to, freedom for the execution engine to
be implemented in whatever way it wants.

In the case of a language like ANT's, a declarative model means that as long
as the dependency restrictions are satisfied, the order in which tasks are
executed should be completely unspecified. And no construct should depend on
whether two independent tasks are executed on a particular order or not.

Usually these requirement when looked closely imply things like single
variable assignment (i.e., properties set only once) and so on. Now in
reality, I am not sure if current ANT is completely declarative, because we
assume some top to bottom relationships outside of the dependency
definitions. For example, properties get evaluated and set from top to
bottom of the file (or at least they were at some point).

You can see that there are some declarative constructs that we do not have
in ANT, although we could. For example there is no way to specify unordered
dependencies (depends="A:B:C") meaning these three targets need to be
executed but the order is not important; or to specify possible dependencies
(depends="A;B;C") meaning if any one of these three targets is successful
assume the dependencies are satisfied. They are all declarative, any the
engine could implement them in parallel or selecting randomly or whatever.

But in particular if one has ";" then one need to be able to undo work if
you tried the wrong thing. Which is all what backtracking was all about.

This is becomming too long,

good bye

Jose Alberto

> From: Steve Loughran []
> >
> > The stuff I did find was about Prolog, so I'm in the
> process of reading it
> > all. I'll report back when I have something concrete and
> useful to add to
> > the discussion.
> okay, I have to own up as to having done a fair bit of Prolog
> in the mid/lat
> eighties, first as an undergrad at Edinburgh Uni, later on in
> cube land when
> we still all thought that natural language and AI would solve
> everyone's
> problems. I've been avoiding joining in the discussion so
> far, as it was as
> amusing as watching VB programmers trying to explain the concept of
> 'inheritance' to each other, having nothing but VB as a
> common language.
> Prolog is declarative. And it's a representation of logic (First order
> predicate calculus, horn clause subset). And it's a resolution process
> (depth first searching).
> The resolution process is the key -in prolog, if a
> declaration proves false,
> the system backtracks to its last choice point and tries the next path
> So you could have some declaration like (I think I've
> forgotten some of the
> syntax, but things starting with capital letters are
> variables which are
> bound to when needed.)
> delivers :- builds, tests, deploys.
> builds :- compiles([source,tests])
> %% compile a file passing in a list of options
> compiles([H]) :- javac(H, flags([optimise(true)|debug(false)])).
> compiles([H|T]) :- compiles([H]),compiles(T).
> tests :- junit(options).
> deploys :- deploys-internal, deploys-staging.
> deploys:- failure-handler(deployment).
> deploys-staging:- is-reachable("http:/staging/"),
> ftp-put("staging","./dist").
> deploys-staging:- echo("staging not reachable), fail.
> deploys-internal:- is-reachable("http:/internal/"),
> ftp-put("internal","./dist").
> deploys-internal:- is-reachable("http:/internal:8080/"),
> ftp-put("internal","./dist").
> failure-handler(Stage) :- page("my-pager",["failure in",Stage]);
> So, this looks very like an ant build file, with build test and deploy
> targets. And the execution process is similar -we wont deploy
> unless the
> tests suceed. But look at the deployment process, where I
> have two targets
> (clauses) of the same name for deploys-staging. If anything
> goes wrong with
> the first one, the one where we upload stuff, the system
> backtracks to the
> last choice point -in this case the second clause. so it runs
> down there
> instead. And if deployment completely goes pear shaped I
> would get paged
> So, here is a declarative language with decision making
> 'implicit in the
> code'
> Then look at the compile task(s). There I am using list
> recursion as an
> alternative to direct iteration. So you can pass a list of
> sub-actions to
> 'compile' and it will do them one by one.
> So even though it is declarative it still supports iteration -in a
> predictable order, and branching. And it also has a very
> wierd way of going
> wrong -where a single typo is enough to send the engine into reverse,
> backtracking and then heading off down some obscure path. That and the
> maintenance grief it could cause is why I am not proposing a
> Prolog like
> language as the build tool language. Where prolog would be good is in
> letting you specify the 'when things go wrong' process, but,
> outside of
> deployment, where can things go wrong that you can handle gracefully?
> Actually the list based invocation is nice. We need more list aware
> languages :-)
> -steve

View raw message