Number_codes/2 which returns difference list

Is there a variation of number_codes/2 that can return a difference list instead of a closed list?

I found that number_codes/2 is implemented with C (src), but further digging lead to xchars (src) and while my C++ is quite rusty, I don’t see any option for a return type of a difference list.

Since I learned how to transform input using DCGs for parsing and difference list for reconstructing the transformed data, I am running into many predicates that would be nice if they returned difference list instead of closed list. One major example of this is all of the predicates in library DCG/basics that return closed list but would be nice if they also returned difference list.

However a hint of returning difference list was found with format/3 which uses with_output_to/2

I know the following simple predicate can easily transform any closed list into an open list, but this is just a band-aid that cost a performance penalty.

% Create open list and hole given closed list
open_closed_list(Open_list,Hole,Closed_list) :-
    is_of_type(proper_list,Closed_list),
    is_of_type(var,Open_list),
    is_of_type(var,Hole),
    open_closed_list_prime(Closed_list,Hole,Open_list),
    must_be(partial_list,Open_list).

open_closed_list_prime([],Hole,Hole).
open_closed_list_prime([H0|T0],Hole,[H0|T]) :-
    open_closed_list_prime(T0,Hole,T).

Personal Notes

References:

codesio.pl – I/O on Lists of Character Codes (src)
format.pl (Prolog src) (C src)

Wouter Beek has a nice implementation of DCG parsing using closed list and difference list.

See: digit*

Notice that your open_closed_list_prime/3 is just append/3. :wink:

I would just write this as append(Closed_list, Hole, Open_list), without any auxiliary predicate.

2 Likes
format(codes(List,Tail), '~w', [Number])

Or, with @michaelby and fully portable

number_codes(Number, Codes),
append(Codes, Tail, List).

I don’t know how the performance compares, The format/3 route is probably faster, especially if the number gets large.

1 Like

That statement threw me off balance because for years with other programming languages I grew to learn that anytime an internal value went through a format operation for external presentation it was very expensive.

In looking at the C source code for format/N (src) I am seeing that it does a lot behind the scenes and my reasoning as to why it would be faster is that because it crosses the Prolog-C interface once as opposed to many times as would be the case with a recursive Prolog clause and that is the reason it is faster. Is that reasoning correct?

That was more or less my reasoning, but I may well be wrong. Using ~d is probably faster than ~w as the latter calls generic write. The only way to know is to try. But, in many cases it won’t matter too much and the best choice is about clarity and, if important, portability. Using number_codes and append is surely more portable. I’m have no clear opinion on clarity here.

1 Like