# Read\_term\_from\_atom requires the option variable\_names to be sorted in order of use

**URL:** <https://swi-prolog.discourse.group/t/read-term-from-atom-requires-the-option-variable-names-to-be-sorted-in-order-of-use/7428>\
**Category:** General\
**Tags:** bug\
**Created:** [May 1, 2024, 5:51am UTC](https://swi-prolog.discourse.group/t/read-term-from-atom-requires-the-option-variable-names-to-be-sorted-in-order-of-use/7428 "2024-05-01T05:51:08Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![DewayneG](https://avatars.discourse-cdn.com/v4/letter/d/838e76/32.png) [@DewayneG](https://swi-prolog.discourse.group/u/DewayneG)\
**Post date:** [May 1, 2024, 5:51am UTC](https://swi-prolog.discourse.group/t/read-term-from-atom-requires-the-option-variable-names-to-be-sorted-in-order-of-use/7428/1 "2024-05-01T05:51:08Z")

</div>

While using **read\_term\_from\_atom** , to construct a string into a callable format. It has a quirk where the order of the variables in either the replacement list or their first use is significant. Below 1,2,4,5 work (s), but 3,6 don’t (f).

```prolog
1. s Repl=['A'=1.05,'B'=0.24], Using='(1+A)*B', read_term_from_atom(Using, TT, [variable_names(Repl)]).
2. s Repl=['A'=1.05,'B'=0.24], Using='(A+A)*B', read_term_from_atom(Using, TT, [variable_names(Repl)]).
3. f Repl=['A'=1.05,'B'=0.24], Using='B*(A+A)', read_term_from_atom(Using, TT, [variable_names(Repl)]).
4. s Repl=['A'=1.05,'B'=0.24], Using='(A*B)+A', read_term_from_atom(Using, TT, [variable_names(Repl)]).
5. s Repl=['A'=1.05,'B'=0.24, 'C'=3], Using='(A*B)+A+B+C', read_term_from_atom(Using, TT, [variable_names(Repl)]).
6. f Repl=['A'=1.05,'B'=0.24, 'C'=3], Using='(A*C)+A+B', read_term_from_atom(Using, TT, [variable_names(Repl)]).

```

A trace of 2 & 3. for reference.

```prolog
?- Repl=['A'=1.05,'B'=0.24], Using='(A+A)*B', trace,read_term_from_atom(Using, TT, [variable_names(Repl)]).
   Call: (11) read_term_from_atom('(A+A)*B', _55030, [variable_names(['A'=1.05, 'B'=0.24])]) ? creep
   Exit: (11) read_term_from_atom('(A+A)*B', (1.05+1.05)*0.24, [variable_names(['A'=1.05, 'B'=0.24])]) ? creep
Repl = ['A'=1.05, 'B'=0.24],
Using = '(A+A)*B',
TT = (1.05+1.05)*0.24.

?- Repl=['A'=1.05,'B'=0.24], Using='B*(A+A)', trace, read_term_from_atom(Using, TT, [variable_names(Repl)]).
   Call: (11) read_term_from_atom('B*(A+A)', _66838, [variable_names(['A'=1.05, 'B'=0.24])]) ? creep
   Fail: (11) read_term_from_atom('B*(A+A)', _66838, [variable_names(['A'=1.05, 'B'=0.24])]) ? creep
false.

```

Performed on HardenedBSD-13.2s and FreeBSD-14.0p5 using swi-pl 9.0.4 and FreeBSD12.4S with swipl 8.4.3.

FYI: I’m using yaml to provide instructions to manage my servers, and noticed this anomoly when I didn’t pay attention to the order of the variables. _Perhaps a flag is required for repeated searches of the subatoms to be replaced, which is likely to reduce performance?_ This is a fantastic and incredibly useful predicate - which has a little quirk at the moment. 🙂

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [May 1, 2024, 7:46am UTC](https://swi-prolog.discourse.group/t/read-term-from-atom-requires-the-option-variable-names-to-be-sorted-in-order-of-use/7428/2 "2024-05-01T07:46:37Z")

</div>

read/2 using the variable\_names(-Vars) option should be called with Vars unbound. The order of the variables is not defined, though for _current_ SWI-Prolog is the lexical order AFAIK. The list `[a,b]` simply does not unify with `[b,a]`. The simplest and most efficient way to deal with this is to sort both `Repl` and the list produced by `read_term_from_atom/3` and then unify them. That should work, provided `Repl` is bound to a proper list and all variable names are already instantiated and (thus) the order is determined.
