Decision diagram for the SWI-Prolog "pseudo-types"

Why pseudo-types? Because they are not really types! But that won’t stop us from drawing a decision tree:

(Large image!)

I’m a bit unsure about the dict with the functor C'dict'. Can use that functor to build a dict using ..=? (I haven tried pulling it out of term using ..= and using it when recomposing actually; I have tried to type it directly, which leads to failure).

Note the interesting feature of the query var(X), which is both a query on the syntax and on the computational state. IMHO it should really be called freshvar(X). The queries are about syntactic structure except for the ones in the number domain, which are about underlying representation, kind of.


EDIT by EricGT

To get a better view of the image, using your Internet browser: open link in new tab

For Chrome it is a context menu item: Right click - Open link in new tab.

3 Likes

Although incomplete in the implementation, the overall idea is that predicates that require text input accept all text representations and produce the documented type as output.

I’m not seeing this. I think I’m misunderstanding. Why can’t the atom table use Unicode for names? Internally all strings could be pointers into a block of memory for string storage and there’s no reason this couldn’t be Unicode. I use UTF-8 encoding and it works out fine. In a flat system with no modules a functor could be saved in memory like this:

struct wam_functor
{
  wam_val_t *symbol;
  uint8_t arity;
  uint8_t spying;
  wam_val_t *entrypoint;
};

here symbol is a pointer to strings storage, arity is obvious, spying is a flag for the debugger, and entrypoint is either a pointer to bytecode storage or to the clause store.

Then it wouldn’t be char_code/2 though wouldn’t it? Surely your problem is not one of pollution (since you support preallocation of the one character ASCII atoms) but one of dimensioning (since you think it too expensive to preallocate the one character Unicode atoms).

1 Like

I just tried these out in my system and I get L=6 and A=ri. Did you expect those results or not? You’ve got me worried I’ve implemented Unicode support incorrectly. You’ve got me doing this:

| ?- Emote = '\u1f631'.
Emote = 😱 ? 

I can maybe see there being a problem with having a length in characters as Unicode talks about code points (can a codepoint comprise several characters - graphically I mean?).

I’m not surprised it isn’t becuase the output I showed wasn’t from SWI Prolog. I wrote

I just tried these out in my system

And by “my system” I mean a Prolog system I built myself. See page 11 of this manual http://barrywatson.se/download/manual.pdf for my implementation of Unicode escape sequences.

Just to be clear. I’m making no claims about SWI Prolog.

The atomic part should look like this

  • atomic
    • number
      • float
      • rational
        • integer
          • code (character)
    • string
    • blob
      • atom
        • char (1-length atom)
      • special constants ([], dict functor)
      • encapsulated foreign resources
        • stream handle
        • thread handle
        • clause handle
        • … (many more)

Blobs global shared (between threads) objects and are subject to (atom) garbage collection. All the others live on the Prolog (global) stack and are thread-local and subject to traditional Prolog GC. As @dtonhofer says, several of these types have multiple implementation that one could consider sub types. These distinctions are fully transparent to the user, but knowing about them can have some value for minimizing resource usage and designing tests for transformations that cross these borders. In particular

  • integers come in three forms
    • Inlined (min/max_tagged_integer) integers use no (additional storage)
    • 64-bit signed integers use 64-bit + two guard words on the global stack
    • GMP integers for anything larger. This is a serialization of the GMP structure on the global stack, again with two guard words.
  • Atoms and strings come in two forms: those with all characters in the range 0…255 are represented as a char* array
  • The others are a wchar_t* array, USC-2 on Windows, UCS-4 on anything else.

char and code do not use any special implementation.

3 Likes

It’s not open source. As you see floats can be given the precision you want. What you see is pi approximated as a 64 bits of precision. Here’s the same for 8 bits and 800 bits. See the documentation for eval/2 to see how it is encoded. All floating point operations are written in Prolog.

| ?- set_prolog_flag(floating_point_precision, 8).
% yes
| ?- write_canonical(3.14), nl.
'$float'(201,2,8)
% yes
| ?- set_prolog_flag(floating_point_precision, 800).
% yes
| ?- write_canonical(3.14), nl.
'$float'(5234391329810685605152683655716187370758635283017987905911062382234769231686841176144324277684170118233199979815845093750022709298483701588085234501079701586184698699918501428393516454440774009412237537666670982555627237209419022113563643740,2,800)

% yes

I don’t implement that predicate.

I’m not entirely against it. I’m also not very convinced we need it. You get this using rational(X), \+ integer(X) or rational(X), denominator(X) =\= 1. I surely agree this is a bit clumsy, but it works and I only do not see many cases where you would like to use this test. For short, I rather wait for somebody with a real problem for which this would significantly simplify the code. Adding more primitives is not free and primitives that are never used thus make the system worse rather than better.

1 Like

No, I implement my elementary functions using the closest precision that can be found in Computer Approximations by Hart et al. I implement special functions using those special functions.

If the numerators and denominators can be compared using </2, >/2 then I don’t think you want ratios as a subtype of rational, specialised like you have described. It can lead to problems.

What I’m saying is nobody so have ratios as a type where numerator and denominator are integers. Ratios are not the result of division.

That’s rationals, not ratio.

If these were ratios then that would be absurd. As rationals I suppose it is ok.

ps. I edited my previous post before I saw your answer. For everyone else, I asked for those results.

A ratio is not the result of division like a rational. The following results are rational numbers.


?- X is 3/4.
?- X is -3 / 4.
X = -3r4.

?- X is 3 / -4.
X = -3r4.

Equating rationals and ratios turns the above into a claim that the ratio of larger to smaller is equal to the ratio of smaller to larger. Clearly absurd. This is known as Arnauld’s paradox.

1 Like

I agree it is common, very common, but very wrong! Whilst both N and R have arithmos as the ancient Greeks would call it, they didn’t mix them nor should we. There is a difference between multitude ( N ) and magnitude ( R ).

Not shorter in the sense of power though, as both sets are infinite.

I wouldn’t have rationals. They’re messy. Just the term denominator is messy. It can only really be used if it is greater than zero, the numerator is nonzero, and numerator and denominator are relatively prime. There’s too much scope for sinn und bedautung conflation.

Mathematics texts don’t allow it (well mine doesn’t) so why should a programming language?

I updated the original image with the information provided by Jan. Plus additional info from other people’s comments.

Here it is, graphml, svg, png:

2 Likes

Awesome work, thanks for sharing… yet, I’m curious where attributed variables will fit :slight_smile:

1 Like