Armin Rigo <arigo(a)tunes.org> wrote:
However, the stream concept of all Prolog implementations I know
seems very old-fashioned to me; doesn't any give the user a way
to define his own streams (i.e. objects that would be usable in
lieu of streams in the built-in predicates, but whose byte-level
read and write operations are user-defined predicates) ? That
would nicely solve this and other problems.
Quintus Prolog has *serious* (but *SERIOUS*) support for just that.
I should know, I designed it. More than 10 years ago.
The main motivation was porting. The IBM mainframe operating systems
MVS and CMS have record-oriented file systems which are different from
each other and very different from UNIX. The Vax & Alpha operating
system VMS has several kinds of file, and UNIX-like streams are not the
normal kind of file. Mapping Prolog I/O -> C stdio -> native I/O was
giving us performance costs you'd have nightmares about; we needed a
reasonably adaptable interface so that you could write just a small
amount of "glue" code for each host file system and then run at native
speeds.
However, this was also used
- to read and write encrypted files
- to read and write compressed files
- to do character code mapping
- to implement string streams
- to implement socket streams
...
And not just by Quintus. The I/O extension interface is fully
documented in the Quintus manuals and is definitely intended for
use by customers.
One difference between this and what Armin Rigo suggests is that
the code you plugged in for your own stream types had to be written
in C. In order to suit the host file system interfaces, we had to
work in terms of packed mutable arrays of bytes (NOT a Prolog data
type); the user functions had to be called from C; and there had to
be no possibility of backtracking or failure.
The point is that unless you want I/O to be so inefficient that
you'd notice it even on a 10GHz machine, you really *REALLY* don't
want to be doing byte-at-a-type operations, especially because quite
a lot of operating systems don't *have* byte-at-a-time interfaces.
You want to work in terms of a BLOCK at a time.
If the underlying system delivers a block at a time,
and if you DON'T pass stream arguments around but always read
from current input and write to current output, it is possible
to implement get_{byte,code,char}/1 and put_{byte,code,char}/1
so that they work at close-to-C speeds, while *still* providing
user extensibility.
==============================================================================
Message: Address: Action:
help majordomo(a)clip.dia.fi.upm.es Info. on useful commands
subscribe ciao-users-request(a)clip.dia.fi.upm.es Subscribe to this list
unsubscribe ciao-users-request(a)clip.dia.fi.upm.es Unsubscribe from this list
<whatever> ciao-users(a)clip.dia.fi.upm.es Send message to list
-----------------------------------------------------------------------------
Archived messages: http://www.clip.dia.fi.upm.es/Mail/ciao-users/
-----------------------------------------------------------------------------
How can I include files or libraries dynamicaly in Ciao-Prolog?
==============================================================================
Message: Address: Action:
help majordomo(a)clip.dia.fi.upm.es Info. on useful commands
subscribe ciao-users-request(a)clip.dia.fi.upm.es Subscribe to this list
unsubscribe ciao-users-request(a)clip.dia.fi.upm.es Unsubscribe from this list
<whatever> ciao-users(a)clip.dia.fi.upm.es Send message to list
-----------------------------------------------------------------------------
Archived messages: http://www.clip.dia.fi.upm.es/Mail/ciao-users/
-----------------------------------------------------------------------------
I know this is going to get me into a lot of trouble.
stringifying 9or atomifying) things is soemthing one needs to do a
lot. Perhaps we should look into the "informal" prolog standard
group. Most implmentatation provide some way to do it so we really
need a simple common name and mode for it.
Jonathan
==============================================================================
Message: Address: Action:
help majordomo(a)clip.dia.fi.upm.es Info. on useful commands
subscribe ciao-users-request(a)clip.dia.fi.upm.es Subscribe to this list
unsubscribe ciao-users-request(a)clip.dia.fi.upm.es Unsubscribe from this list
<whatever> ciao-users(a)clip.dia.fi.upm.es Send message to list
-----------------------------------------------------------------------------
Archived messages: http://www.clip.dia.fi.upm.es/Mail/ciao-users/
-----------------------------------------------------------------------------
Hello,
How can I "print" a term to a string ? In other words, how can I do the
equivalent of (+Term, -String) :-
open(TempFileName, write, S),
write_term(S, Term),
close(S),
file_to_string(TempFileName, String).
without using a temporary file at all ?
Thanks,
Armin.
==============================================================================
Message: Address: Action:
help majordomo(a)clip.dia.fi.upm.es Info. on useful commands
subscribe ciao-users-request(a)clip.dia.fi.upm.es Subscribe to this list
unsubscribe ciao-users-request(a)clip.dia.fi.upm.es Unsubscribe from this list
<whatever> ciao-users(a)clip.dia.fi.upm.es Send message to list
-----------------------------------------------------------------------------
Archived messages: http://www.clip.dia.fi.upm.es/Mail/ciao-users/
-----------------------------------------------------------------------------
I really have better things to do than to respond to provocation,
but here goes.
Richard has been advocating for ages the writing of steadfast
predicates: he could be named the prophet of steadfastness.
That does not mean that I have lost all vestiges of common sense.
I repeat: I have advocated that *exported* predicates be steadfast.
So, when Richard writes in a public forum a predicate that does not
look steadfast, he should expect remarks.
I was explicitly *sketching* an implementation of *one* predicate,
namely between/3. It was obvious to any reader with kindergarten-level
reading and conversational skills that between1/3 was part of that sketch.
Some trouble was in fact taken to ensure that the predicate which was the
topic of the message was steadfast.
# Bart, as usual, you make such fuzz out of nothing, but actually,
# you are right, between_aux/3 is not steadfast. Here is a
# steadfast version:
The thing is that for a predicate which is intended to be called in only
one place, there is no *point* in adding overheads just to satisfy a
criterion which isn't really relevant.
It never occurred to me that Bart Demoen was yanking my chain.
His second answer uses the "official definition of steadfastness".
That definition was written at a moment that there was no standard
about Prolog modules and where Prolog systems with modules typically
allowed to bypass the intended hiding of non-exported predicates:
Well, no. between/3 goes back to DEC-10 Prolog. Now in old DEC-10
compiled Prolog a predicate really was not visible outside its module
unless you explicitly said so. (Old DEC-10 Prolog basically had the
"assembler" model of name control.) Unfortunately, the file system where
I keep some of this stuff suddenly disappeared this morning, so I can't
quote chapter and verse.
What is more, even when "The Craft of Prolog" was written, it was written
in the context of Dave Bowen's XREF program (which he had adapted to
Quintus Prolog), so that despite the module overriding that had been
provided for the sake of the debugger, one could be quite sure that there
were no *static* calls to a private predicate. (XREF goes back to DEC-10
Prolog.) To be sure, one could not be sure about dynamic calls using
call/1 (although XREF did quite a good job of tracing those too), but
then a dynamic call using call/1 could replace the entire module with
anyone you please, as could a static call to compile/1.
One of the key steps that should have been required as part of the
standardisation process for ISO Prolog (and even more so for ISO Prolog
modules) is the production of a version of XREF (or XREF-like functionality)
working with ISO syntax and semantics.
If I were rewriting The Craft of Prolog, I think that "how to use XREF"
and "how to build an XREF" would not just deserve mention (as, to my
regret, they were not mentioned), they would deserve an entire chapter.
==============================================================================
Message: Address: Action:
help majordomo(a)clip.dia.fi.upm.es Info. on useful commands
subscribe ciao-users-request(a)clip.dia.fi.upm.es Subscribe to this list
unsubscribe ciao-users-request(a)clip.dia.fi.upm.es Unsubscribe from this list
<whatever> ciao-users(a)clip.dia.fi.upm.es Send message to list
-----------------------------------------------------------------------------
Archived messages: http://www.clip.dia.fi.upm.es/Mail/ciao-users/
-----------------------------------------------------------------------------
Bart Demoen made a petty criticism of between_aux/3 in my sample
implementation of between/3. He continues:
Conclusion: between_aux/3 is _not_ steadfast.
The invariant that _your_ code imposes, can be violated by others in
the same module.
Steadfastness is all about the INTERFACE seen by USERS of modules.
The point is that to the extent practical, users of Prolog modules
should see predicates that act logically; when that doesn't make
sense (predicates that are supposed to change the state, for example)
they should still see predicates that are "clean" in whatever sense
is appropriate.
It is entirely commonplace for modules in all sorts of languages to
have internal operations which *could* do bad things but *don't*
because the rest of the module ensures that they are never called
in bad ways.
It is important that beween/3 should be steadfast, because it is
an exported predicate.
It is important that between_aux/3 should be steadfast-in-context.
For this purpose, it is idle chatter to talk about what other
predicates in the module COULD do; they don't. Yes, a change to
the module could introduce a bad call. But a change to the module
could erase all the files on your disc.
The module this is drawn from is 99 SLOC. between_aux/3 (actually
called between1/3 in the code) is *documented* as being an internal
part of between/3 and aside from recursive calls is called in
precisely one place. It is precisely as steadfast as it needs to be.
One thing I've often wished for in Prolog generally is the ability
to make one or more predicates private to another predicate or
predicates. In my early days at Edinburgh, I used to indent my code
to depict the nesting that I would have liked.
In a functional language, I'd write
let <local defs>
in <public defs>
end
so let's rewrite between/3 like this:
:- let.
between_aux(L, U, X) :-
( L =:= U -> X = L
; X = L
; M is 1 + M, between_aux(M, U, X)
).
:- in.
between(L, U, X) :-
( integer(L), integer(U) ->
( integer(X) ->
L =< X, X =< U
; var(X) ->
L =< U,
between_aux(L, U, X)
; <<diagnose and report type failure in X>>
)
; integer(L), var(U), integer(X), X < L -> fail
; integer(U), var(L), integer(X), X > U -> fail
; <<diagnose and report type error or instantiation fault>>
).
:- end.
Think of the :-let part as a "mini module" which can only be
imported by the :-in part.
Let's look at the official definition of steadfastness,
on page 96 of The Craft of Prolog:
'We want our predicates to be "constant, firm, unwavering" about
giving the right answers; we call the property of refusing to
give wrong answers even when the query has an unexpected form
(typically, as here, supply values for what we normally think
of as [outputs]) _steadfastness_ and say that a good predicate
is _steadfast_.'
Yes, there's a typo in there. [outputs] reads 'inputs', which doesn't
make sense. 'outputs' is what it _should_ say.
Now, since between_aux/3 is a private predicate of a module,
ALL THE CALLS TO IT ARE KNOWN. Queries of "unexpected form" do not
arise, so on a strict construal between_aux/3 is trivially steadfast.
If someone wants to get picky about whether an encapsulated predicate
with only one call is "steadfast" according to some other definition,
well, let them. It doesn't matter. The *point* of encapsulating things
in modules is to give us the freedom to concentrate interface issues
(like argument checking and steadfastness in general) in interface
predicates, and to strip purely internal predicates to just the aspects
they need to do their highly constrained job.
==============================================================================
Message: Address: Action:
help majordomo(a)clip.dia.fi.upm.es Info. on useful commands
subscribe ciao-users-request(a)clip.dia.fi.upm.es Subscribe to this list
unsubscribe ciao-users-request(a)clip.dia.fi.upm.es Unsubscribe from this list
<whatever> ciao-users(a)clip.dia.fi.upm.es Send message to list
-----------------------------------------------------------------------------
Archived messages: http://www.clip.dia.fi.upm.es/Mail/ciao-users/
-----------------------------------------------------------------------------
> > between_aux(L, L, L) :- !.
>
> what happened to steadfast code ?
>
> It _is_ steadfast. Or rather, it's a private _part_ of a steadfast predicate.
Conclusion: between_aux/3 is _not_ steadfast.
The invariant that _your_ code imposes, can be violated by others in
the same module.
Bart Demoen
==============================================================================
Message: Address: Action:
help majordomo(a)clip.dia.fi.upm.es Info. on useful commands
subscribe ciao-users-request(a)clip.dia.fi.upm.es Subscribe to this list
unsubscribe ciao-users-request(a)clip.dia.fi.upm.es Unsubscribe from this list
<whatever> ciao-users(a)clip.dia.fi.upm.es Send message to list
-----------------------------------------------------------------------------
Archived messages: http://www.clip.dia.fi.upm.es/Mail/ciao-users/
-----------------------------------------------------------------------------
Bart Demoen <Bart.Demoen(a)cs.kuleuven.ac.be> asked:
> between_aux(L, L, L) :- !.
what happened to steadfast code ?
It _is_ steadfast. Or rather, it's a private _part_ of a steadfast predicate.
between_aux/3 is not an exported predicate, it's only called by
between/3, which ensures that the 3rd argument is a variable
before the call.
==============================================================================
Message: Address: Action:
help majordomo(a)clip.dia.fi.upm.es Info. on useful commands
subscribe ciao-users-request(a)clip.dia.fi.upm.es Subscribe to this list
unsubscribe ciao-users-request(a)clip.dia.fi.upm.es Unsubscribe from this list
<whatever> ciao-users(a)clip.dia.fi.upm.es Send message to list
-----------------------------------------------------------------------------
Archived messages: http://www.clip.dia.fi.upm.es/Mail/ciao-users/
-----------------------------------------------------------------------------