Re: more version 7 woes re phrase/3

Jan Wielemaker <[email protected]>
Newsgroups gmane.comp.ai.prolog.swi
Message-ID <[email protected]>
On 01/13/2014 03:33 AM, Richard A. O'Keefe wrote:
>
> On 21/12/2013, at 11:01 PM, Jan Wielemaker wrote:
>> This was added (as you may have guessed) to trap strings that are passed
>> to phrase/3.
>
> We've already seen that this could be better handled by a static
> tool; breaking working code seems a high price to pay.

I still don't know.  Traditional DCGs used 'C'/3 as you well know.
This theoretically had some possibility to process something else
than a list, except that 'C'/3 was (in most systems) a statically
defined built-in.  As I recall, attempts to standardize DCGs
(ISO) work on the assumption that 'C'/3 is not needed and e.g.,
literals may do direct list matching (that is also what SWI-Prolog
does).

A just as sensible alternative is to define that phrase/3 works
on lists and then there are two options:

   - Use DCGs for threading state as Markus showed us.
   - Have an alternative to phrase/3 that works on anything and
     -preferably- does not allow for list terminals.

>> Nothing changed to the compilation though.  My first impression is that
>> phrase/3 is designed to deal with lists.
>
> phrase/3 is designed to work with whatever it is that the
> DCG rules it calls happen to work with.  Fair to say, however,
> that the Quintus documentation explicitly called the second
> argument "List".
>
>> What about inventing another name for phrase/3,
>
> Would it not have been much more useful to define
>
> phrase(NT, S0, S) :-
>      (    string(S0) ->
>           string_codes(S0, C0),
>           old_phrase(NT, C0, C),
>           string_codes(S, C)
>      ;    old_phrase(NT, S0, S)
>      ).

This looks like a bad idea.  Not only is it seriously
inefficient, but it also breaks the clean bi-directional
semantics of phrase/3, as phrase in `generative' mode
would return a list (of codes).

I think adding a phrase_string/2,3 is a more promising
route.  That can either use the technique below or use
the same technique as library(pure_input): a lazy
code-list.

> What would be even better would be if the DCG translation
> did something like
>
> 	[X],S0,S =>
> 	    (   S0 = String+I0,
> 	        S  = String+I ->
> 	        succ(I0, I),
> 	        string_char(I, String, X)
> 	    ;   S0 = [X|S]
> 	    )
>
> so that DCGs just worked with strings.
>
>> or even, simply go back to the basics and rely
>> on call/3:
>>
>> 	call(ruleset, StateIn, StateOut).
>
> which does not transform the rule body correctly.

Right :-(  Provided the ruleset is sufficiently
instantiated, one could use:

:- meta_predicate
	my_phrase(//, ?, ?).

user:goal_expansion(my_phrase(Rule, In, Out), Goal) :-
	expand_phrase(phrase(Rule, In, Out), Goal).

At this moment, I think that Markus' technique is the most
sensible proposal that I have seen.  It allows using DCGs
for threading state and does not break the assumed typing
of phrase/3.  Note that my long-term aim is to provide more
(soft) typing.

	Cheers --- Jan
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.