but then 36 unit tests failed…they all are failing because now that the operators are defined in the “utils” module, when the operator does the call/1 it is saying that the callable is not found in the module… does this mean I have to explicitly provide the module name as well? I would have thought it knew where to call back to but maybe not?!
Here is the debugger error:
basically Callable is in module “ast” and the operator is in module “utils”. one_term_value/3 is define in module “ast”.
Thanks again Jan, I can probably figure it out…this is a first moment for me and Prolog, I felt cool enough defining the operators in the first place and now I go and get all fancy by trying to re-use them in other modules! That’ll teach me!
This has nothing to do with operators. You need meta_predicate declarations if you put
a meta predicate in a module and export it. Traditionally the declaration must be before the code, typically after the module header and imports. SWI-Prolog execution doesn’t care, but the development tools only scan modules upto the first non-directive.
A meta predicate is a predicate that accepts one or more arguments that must be resolved to a predicate in the module of the caller. You’ll find lots of them in the library.
0…9
The argument is a term that is used to reference a predicate with N more arguments than the given argument term. For example: call(0) or maplist(1, +).
How do I know what value to use if I don’t know ahead of writing the code what I will be doing with it? I feel dumb today…
It depends what the meta predicate does with the argument. If it uses call/1 on it, the argument must be declared as 0. If it uses call/2, 1, etc. If it doesn’t call at all, but for some other reason wants to know the module to which the argument must be resolved, use :. If no module is involved for an argument, use *, ?, + or -. They are mode annotations that have traditional documentary value. The system does nothing with this.
Actually, the implementation only distinguishes meta from non-meta arguments. If the argument is a meta argument, the provided (Arg) value is transformed into a term SourceModule:Arg. Otherwise it is left untouched. The 0…9 argument tells the cross-referencer what happens. If it sees foo##bar(x), both annotated with 0, it knows this calls foo/0 and bar/1. If these would be annotated as 1, it knows this calls foo/1 and bar/2, etc.
I am nearly there…the ## and ### are fine now it is the << and =<< that are giving me errors still. I am reading my code -closely- to see what I have is what the mode declarations said.
Warning: The predicates below are not defined. If these are defined
Warning: at runtime using assert/1, use :- dynamic Name/Arity.
Warning:
Warning: ast:<<</1, which is referenced by
<<< was <<, I didn’t realise it was a shift operator so I renamed for clarity in my own head, anyway the code for it…
<<< is thus called from within a DCG rule so the arity is 3 because of the DCG lists on the end but the error message says <<</1 not <<<//1 so I still can’t see what’s wrong!
changed ## and ### to // for their arguments, that has reduced my error count…I guess this is all part of the rich tapestry of learning something new,…sorry for the noise
While I am aware that meta predicates exist, I know next to nothing about them in Prolog. Oh I do see them often when reviewing the source code for SWI-Prolog or in some other packs or packages but they are mostly nebulous.
It is @EricGT but I am fundamentally thick I guess and so some days it feels like I am banging my head harder than usual…I have made it work now and I think I understand why too which is always a bonus.
When I first learned Haskell it was hard as I am no mathematician. Same with Prolog, I am no logician either. Out of the two though I think Prolog has it for sheer beauty of appearance!
This is a no-op. Doesn’t do any harm, but as none of the arguments is a true meta argument it does nothing.
The // is indeed correct. Forgot than call(Callable) is in a DCG body and thus effectively call/3. You should need the same for the 2nd argument though as that is handled the same. Higher order DCG is a rather tricky thing. I think you should not be using call(Callable), but simply Callable to allow for arbitrary DCG body terms. See library(dcg/high_order) for examples.
TBH Jan I am beginning to think that “Golden Hammer” may have applied…I am seriously looking at a way to make it simpler…now that I “understand” meta-predicates I feel like the guy who first discovered TNT but didn’t realise it’s volatility and potency for trouble