Re: Ann: SWI-Prolog 6.5.3

Jan Wielemaker <[email protected]>
Newsgroups gmane.comp.ai.prolog.swi
Message-ID <[email protected]>
On 11/21/2013 04:05 AM, Richard A. O'Keefe wrote:
>
> On 20/11/2013, at 10:43 PM, Jan Wielemaker wrote:

> memchk(X, cons(H,T)) :- ( X = H -> true ; memchk(X, T) ).
>
> If this behaves differently from memberchk/2, you make my
> life as a programmer *HARDER*.

My viewpoint has always been that a predicate behaves sensibly in a
specified domain. In this case that is the domain of cons(H,T) pairs.
Outside that domain, it should basically throw as many errors as
possible because that greatly helps debugging your program. Few things
are as annoying as Prolog programs failing somewhere deep down due to
-for example- a change of the data representation.

Ideally, we'd have static tools for that, but unfortunately these are
still not widespread. So, in practice we are faced with lots of code
that silently fails when faced with data that is outside its domain.

> Can we please consider "getting rid of [a|b]" a *non*-problem?

That is absolutely not a non-problem. This datastructure pops up
regularly by e.g. append(List, Element, NewList) as a typo for
append(List, [Element], NewList) or not being aware that the second
argument you pass to append is not a list. The result is something that
starts nicely as a list, has the desired term in it, but member/2 fails
because the target element is the tail.  If the (non-)list is long and
the elements are complicated structures this is very hard to spot, while
I never encounted such structures being created on purpose.

This is not a hypothetical issue, but a frequent source of frustration.
Sometimes you are lucky and you pass the non-list to a predicate that
throws an exception.

>>   This
>> raises some exceptions on existing code.  Most of the cases I studied
>> should be considered highly dubious code.  I found only one case where
>> one could reasonably state that silent failure was anticipated.
>
> One case is arguably one case too many.

No. Most of the ISO built-ins raise errors and there are enough
situations where need an explicit type-check to avoid that. I'm
generally glad about that. The only exception I'm aware of is
number_codes(N, "abc"). That throws a syntax error, while there are many
applications where you want failure and there is no easy way to prevent
the exception. It is one of the few cases where the usage of catch/3 is
required and the exception may frequently fire in a properly operating
application.

>> I agree here. The only way to make strings cooperate with list
>> predicates is to make strings appear as virtual lists on which you can
>> apply normal (list) unification. You claimed that NU-Prolog does this
>> and that it is far from simple (if I recall correctly).
>
> Well, what counts as "far from simple" in a system that has to fit
> into 4MiB and what counts as "far from simple" in a system that can
> use 4 GiB or more aren't the same thing.  SWI Prolog is a much bigger
> system than NU Prolog ever was and has been for some time.  My
> understanding is that the code required *care* but not great cleverness.
>
>> Even if
>> possible, I still do not like that, as it will imply that strings may
>> silently be transformed into code lists.
>
> Now I am puzzled and confused.  The point of the NU Prolog approach
> was that strings *were* lists, it's just that some strings were stored
> more compactly than others.  It meant, for example, that you could have
> large amounts of text data in static code.
>
> For a rather good analogy, consider dear old CDR-coding.
> The effect of CDR-coding is that some lists are stored rather like
> arrays (with 1 word per element).  Garbage collection might turn
> some 2-word-per-element (parts of) lists into 1-word-per-element ones.
> Some processing might go the other way.  But that's an invisible
> implementation detail.
>
> In the same way, in the NU Prolog approach, a byte-per-element string
> *IS* a code list, just stored differently.
>
> Since SWI Prolog lets you do anything you might ever have wanted to do
> with strings using atoms, it's not clear that SWI Prolog gets any
> benefit any longer from having strings at all.

The main point of strings is that they are *not* lists, so you know "ab"
is a string and not a list of two percentages ([97,98]). The NU Prolog
approach hides this detail, turning it only into an implementation
detail. Yes, you can represent any text as a SWI-Prolog atom. However,
this ignores the conceptual difference as well as the ability to exploit
runtime type information. There is also an important implementation
detail missing: atoms are expensive, in particular as a short-lived
datastructure. Nevertheless, we see that many applications do a lot of
sub_atom/5 and atom_concat/3 calls to do string manipulation with atoms.
Such applications tend to be slow, in particular if it concerns
multi-threaded servers. Most of these applications should be using the
list representation. Apparently many users do no like using lists for
text processing. I think one of the reasons is that it is often hard to
debug.

I think that the technical problem of using atoms could be fixed by
having two types of atoms: interned ones (the current) and temporary
ones (much like the current strings) and hide this detail from the user.
That still does not address the fact that symbols and strings are
different things.

>> For example, calling format("Hello
>> world!~n") is supposed to be fine, but append("hello", Rest, List) is
>> not. It allows declaring additional predicates as `safe'.
>
> Does this mean that _every_ predicate (or rather, every argument
> position of every predicate) is presumed dangerous unless declared safe?

Yes.

> What I _want_ is to be able to declare in a source file what
> syntax settings that file is to be processed with *without* any
> effect on run time.  Is that possible?

The double_quotes flag has no impact on the runtime.  It only
defines the resulting data structures from parsing "text" and it
does so on per-module basis.  So, if you have a module that
processes code lists and uses a lot of list processing predicates
with explicit "text" as arguments, you just declare that module
to parse this into code lists.

> [By the way, typing help(...) to SWI Prolog on a Mac takes AGES.
>   Even with the SWI-Prolog.app, it starts X11, and it can take a
>   couple of minutes of frustration watching the X icon bounce.
>   How do I tell it to display the help text to the terminal,
>   glass TTY fashion?  Seriously, it's quicker for me to telnet
>   over to my Solaris 10 box and fire up SWI there.  I just did
>   exactly that.
> ]

You can add Contents/MacOS of the app to your $PATH and run the swipl
commandline version after unsetting $DISPLAY. That will stop it trying
to contact X11.  There might be something wrong with your Mac.  I've
got a really old iMac.  Sometimes X11 takes long to start the first
time after an upgrade, but otherwise it is just a few seconds.

I always use the manual on the website.  If I'm not connected to the
internet I typically run the website locally (the source is in the
git repo plweb.git).

	Cheers --- Jan

> Here's text from an elderly swipl.
>      double_quotes (codes,chars,atom,string, changeable)
>           This flag  determines  how double-quotes  strings are  read  by
>           Prolog and is ---like  character_escapes--- maintained for  each
>           module.
>
>   help 4 minutes ago and it _just_ settled down and g
>
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.