1

It is not uncommon to see data in Prolog written with a functor, e.g.

note("This is a note")

but Prolog can also process the data with the name moved to an argument, e.g.

(note,"This is a note")

When moving the data name from the functor into an argument, is there a name used to describe this process?

I have some code that will have the data converted as such and would like to include in the documentation a standard name to describe this change if it exist.


EDIT

The current specific reason for doing this is so I don't have to use =../2 and can also make comparison on many datum with anonymous variable, e.g.

(_,A,B,C) 

or write more general predicates, e.g.

do(_)
do(_,A)
do(_,A,B)

instead of

do(note(A))
do(note(A,B))
do(note(A,B,C))
do(comment(A))
do(comment(A,B))
do(comment(A,B,C))
do(text(A))
do(text(A,B))
do(text(A,B,C))

EDIT

Below is a comment by @repeat with reasons not to do what is demonstrated in this question by changing a compound term note(A,B) into a comma list (A,B), as opposed to a regular list [A,B]. It is good advise but sometimes there are reasons for breaking such advise. I can not say at present for my current need if doing this in Prolog is one of those cases, but as the question asks, it would be nice to have a name for the process so that it can be searched for research.


@repeat You can edit this and add notes as it is all Creative Commons.


Guy Coder
  • 24,501
  • 8
  • 71
  • 136
  • Of interest: [Partial application](https://en.wikipedia.org/wiki/Partial_application) - This is not what is being done here. Added this reference because it is in the same brainstorming of words that might lead to an answer. – Guy Coder Mar 19 '19 at 13:04
  • Of interest: [Functor](https://en.wikipedia.org/wiki/Functor) - Not to be confused with Prolog functor. Another word for brainstorming. – Guy Coder Mar 19 '19 at 13:41
  • Of interest: [Hygienic macro](https://en.wikipedia.org/wiki/Hygienic_macro) - macros whose expansion is guaranteed not to cause the accidental capture of identifiers. Another word for brainstorming. – Guy Coder Mar 19 '19 at 13:58
  • Of interest: [Quasi-category](https://en.wikipedia.org/wiki/Quasi-category) - is a generalization of the notion of a category. Another word for brainstorming. – Guy Coder Mar 19 '19 at 16:55
  • 1
    Comma lists, again:) Each comma term is has exactly two arguments. If the number of items is reasonably low, you should use some structures `f/N` instead. (constant access time, as opposed to linear with "comma lists") – repeat Mar 19 '19 at 19:35
  • @repeat `Comma list, again` :) Yes I know. In this case it has to do with that large file and creating facts from it. If I tag all of the data with a functor the code to write would be almost as big as the DCG itself with is also rather large. By tossing out the data name the code is much simpler, but some of the data still needs specific tags for comparison, but there are many redundant patterns, thus the change. I don't think the final data store will be a file of facts as they alone will also be in the gigabytes. Any way, need to experiment to learn. – Guy Coder Mar 19 '19 at 19:41
  • Of course I do not know the actual details of your use case, but... my point is this: **"comma lists" are almost always the wrong data structure to use.** (1) If you have a constant number or arguments then compound terms are best. Tuples in functional languages fall in this category. Keep in mind that Prolog does not have tuples like `(1,2,3)`. OTOH "adding" an argument in front usually does not make sense then, as the meaning of each argument is determined by its position. (2) If you have a variable number of items and order is important, use lists---not comma lists. Why not use lists? – repeat Mar 19 '19 at 19:54
  • If you use "comma lists" in facts, save 50% memory by switching to compounds. – repeat Mar 19 '19 at 19:57
  • There's one advantage though: you can pattern match on comma lists: ` (f,a,b) = (f,Y)` unifies but `s(f,a,b) = s(f,Y)` doesn't. In case you have functors of different arity, the lists are a better way to go about it. – lambda.xy.x Mar 20 '19 at 18:32
  • @lambda.xy.x. Why not simply use *lists* in these cases? Lists give you two functors for the two cases 'empty' and 'non-empty', so indexing works and there's no need for using `dif/2` (or, worse, `(\=)/2`). – repeat Mar 20 '19 at 19:21
  • I'm fine with lists (see my answer) - it would be nice to enforce non-empty lists by more than convention though. You could make it a little ugly and define `app(Fun, Arg1, Args2toN)` where `Arg1` is a proper argument and `Args2toN` is a list of additional arguments. That would avoid the ambiguity of constants vs. zero argument applications. – lambda.xy.x Mar 20 '19 at 19:28
  • To profit from argument indexing I would probably unfold the outermost structure and define a predicate `fun_transformed(F, FArg0, FArgs, G, GArg0, GArgs)`. – lambda.xy.x Mar 20 '19 at 19:46

2 Answers2

5

Actually, (note, "this is a note") is a term with functor , and arity 2 (first argument note, and second argument "this is a note").

You can see this issuing the following queries:

?- write_canonical(note("This is a note")).
note("This is a note")

?- write_canonical((note,"This is a note")).
','(note,"This is a note")

So what you are doing by "moving" the principal functor of a term of arity N to a term of arity N+1 with principal function , adding the previous functor name as the first argument and shifting the other arguments is some sort of generalization, though I don't know if there is a more suitable name for this.

gusbro
  • 22,357
  • 35
  • 46
2

You could see it as a restricted way to write an applicative encoding of a higher-order logic fragment into first order logic. An applicative encoding uses constants to represent functions and uses a binary function symbol app to express that f is applied to an argument list. For example, the applicative encoding of f(g(a),b) is app(f, [app(g,[a]),b ]). In your case, the ,/N operator plays this role but as you have probably noticed, without an argument list you need to know the number of arguments when you are matching against such a term.

An example where this encoding is used in a Prolog context is the higher-order automated theorem prover input format TPTP THF. They use an infix operator @ to represent application. There, they also use the standard encoding which uses nested apps. The term representation is not as beautiful (the example term is written (f @ (g @ a))) @ b) but it has the advantage that constants only have one representation. With the list encoding, you have to take into account that c = app(c, []).

lambda.xy.x
  • 4,918
  • 24
  • 35
  • Nice info. Since I am not sure if there is or is not a real name for the process, I can't accept this at the moment. I just hate giving accept votes then later finding there was a definitive answer. I would like to let this sit for a few weeks before deciding, and may even decide to wait more. If on the other hand this or another answer gives an answer that cites a reference to a significant Prolog book, ISO standard, etc. then that will most likely get the answer. – Guy Coder Mar 20 '19 at 13:14
  • I just clicked the link and see that it is to a Journal; reading it now. :) – Guy Coder Mar 20 '19 at 13:16
  • The more I read the more I am convinced this is not correct. Not saying it is wrong, just at present moving away from thinking the terminology fits. – Guy Coder Mar 20 '19 at 14:18
  • The article itself is about a higher-order language, but the way they write it has explicit application. I assume you do less and only encode the outermost application: `f(g(a),b)` becomes `(f, g(a), b)` not `(f, (g,a), b)`. When I write the latter with proper parenthesis, we arrive at the applicative encoding: `((f, (g,a)), b)`. Now replace `,` with `@` and that's it. – lambda.xy.x Mar 20 '19 at 18:28
  • This is wrong. In the question the name `note` is not a predicate like `dif` but a name for data in a compound term. There is no corresponding predicate `note` to be called. If I understand how Prolog is working in the background then `,` becomes the name of the function after the change, but from a syntactic sugar view, it doesn't matter for what is needed. – Guy Coder Mar 20 '19 at 20:05
  • What matters is what you allude to in another comment is the unification. `?- (f,a,b) = (f,Y). Y = (a,b).` , `?- f(a,b) = g(a,b). false.` and `?- (_,a,b) = (_,a,b). true.` with the second case being what I have which doesn't unify and the third case being the change that does unify. – Guy Coder Mar 20 '19 at 20:06
  • Not sure if you answered in the right thread... HOL has function and predicate quantifiers, there's no difference in the representation. Prolog also does not differentiate between function and predicate symbols, for instance `X = member(_,_), X` works fine even though formally, member is a function symbol in here. – lambda.xy.x Mar 20 '19 at 20:25
  • @repeat's comment was about `,` being a defaulty operator: there is no proper way to designate the end of a comma-list because everything apart from `,/2` is allowed there, requiring a `dif(Tail,',')`. That's the difference to the list representation `[f, [g, a], b]`. – lambda.xy.x Mar 20 '19 at 20:28
  • What I would like to do in Prolog is `match(F(A,B)) :-` or `match(_(A,B)) :-` but both are syntax errors. While either of these are not `match(F,A,B) :-` or `match(_,A,B) :-` . If what you are saying is that the answer you gave is correct because I asked a general question and using specifics of Prolog is a fallacy in this case, then I need to go back and better understand what the paper is saying. Let me read some more. – Guy Coder Mar 20 '19 at 20:37
  • Just as a remark: the paper is not Prolog, even though the language they define is compatible with Prolog (+ some operator definitions). But it's just a data format. – lambda.xy.x Mar 20 '19 at 21:22
  • Are you aware of `call/N` with `N` ≥ 2? Where is this app/2 from? – false Mar 24 '19 at 16:20
  • app/2 is just a function symbol to represent an application but it is just a data-structure (not too much different from using `,/2` except it is less ambiguous), not a predicate. It allows a first-order encoding of the function quantifier `∃F.p(F(c))` as `∃F. app(p, app(F,c))` - only the second one is valid first-order syntax. – lambda.xy.x Mar 25 '19 at 09:08