6

I am writing a parser for SPARQL (Semantic Web query language) using DCG. I want to replace SPARQL variable names with Prolog variables. How would I go about this?

I can generate new variables using length([NewVar], 1), but I cannot keep track of existing assignments by simply using a list of name-variable pairs. A member/2 operation on the list will return a new variable, not the one stored in the list.

Is there an easy way for naming variables in Prolog, e.g., '$VAR(Name)'?

Wouter Beek
  • 3,307
  • 16
  • 29
  • 3
    `member/2` *will* yield the one stored in the list (otherwise we would hardly call it "member"). Example: `?- Vs = [a-_,b-_], memberchk(a-V1, Vs), memberchk(a-V2, Vs), V1 == V2.`, succeeding as expected. Notice that I simply use `_` to create a fresh variable on the fly. Of course, you have to thread the list of name-variable pairs through all predicates that need to access it. Consider threading it through implicitly via DCGs for better readability. Also, consider using a balanced tree as in `library(assoc)` to store the correspondence between SPARQL names (= atoms) and Prolog variables. – mat Apr 22 '15 at 19:43
  • 3
    To answer your last question see [`variable_names/1`](http://stackoverflow.com/questions/7947910/converting-terms-to-atoms-preserving-variable-names-in-yap-prolog/7948525#7948525). `'$VAR'/1` is so 1970s. – false Apr 25 '15 at 19:10

1 Answers1

2

member/2 will do what you want. Here is an example:

Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.25)
Copyright (c) 1990-2016 University of Amsterdam, VU Amsterdam

L=[a-X,b-Y,c-Z], member(b-V,L).
L = [a-X, b-V, c-Z],
Y = V 

But you might get problems if you interleave write/1 with member/2, since a variable might change its identity, i.e. the write symbol in the following circumstances:

  • because of garbage collection, if a variable is written as _G<memloc>
  • because of aliasing, in the above example the memloc of V might be shown
    instead of the memloc of Y

Same problem with (@<)/2. One way out is to use attribute variables, which at least puts an end to aliasing, since attribute variables are usually unified last,

so in the above example if Y is an attribute variable and V is an ordinary variable you would never see the memloc of V after calling member/2.

Further you can also mitigate the problem by using ISO core standard variable_names/1 write option, to write out a variablified term. The variable_names/1 write option is immune to garbage collection or aliasing.

Bye

  • This won't replace atoms in nested terms, like `A` in `recursive_term(A,recursive_term(B,A))`. – Anderson Green Feb 10 '19 at 01:44
  • 1
    See here: https://stackoverflow.com/questions/37260614/prolog-replacing-subterms/53145013#53145013 –  Feb 11 '19 at 00:25