# Creating prolog clauses with prolog\_load\_file/2

**URL:** <https://swi-prolog.discourse.group/t/creating-prolog-clauses-with-prolog-load-file-2/2745>\
**Category:** Predicate\
**Created:** [August 4, 2020, 3:52pm UTC](https://swi-prolog.discourse.group/t/creating-prolog-clauses-with-prolog-load-file-2/2745 "2020-08-04T15:52:07Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![remy.s](https://avatars.discourse-cdn.com/v4/letter/r/54ee81/32.png) [@remy.s](https://swi-prolog.discourse.group/u/remy.s)\
**Post date:** [August 4, 2020, 3:52pm UTC](https://swi-prolog.discourse.group/t/creating-prolog-clauses-with-prolog-load-file-2/2745/1 "2020-08-04T15:52:07Z")

</div>

Hi,  
How can I create one or more prolog clauses using hook “prolog\_load\_files”?  
According to the documentation, prolog\_load\_file/2 is used to

> …deal with Prolog code that is not represented as a Prolog source text…

However, I could not find any documentation how to create the clauses I would need.  
Example: I have the following file test.pl:

```prolog
:- multifile mydata/1.

user:prolog_load_file(Spec, _Options) :-
	strip_module(Spec, Mod, File)
	, atom(File)
	, file_name_extension(_Base, mydat, File)
	, writeln(creating_clauses_from_file(Mod, File))
	
	**% here we want to parse File and create facts in the form "mydata(a)."**
	.

:- load_files('test.mydat').

```

Which I then call with “ **swipl test.pl** ”, with the following result:

```plaintext
*swipl test.pl*
**creating_clauses(user,test)**

Welcome to SWI-Prolog (threaded, 64 bits, version 8.3.4)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.
For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).
?-

```

My question is: Once I have parsed my file, how can I add the resulting clauses to my program?  
Thanks for any support

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [August 4, 2020, 4:23pm UTC](https://swi-prolog.discourse.group/t/creating-prolog-clauses-with-prolog-load-file-2/2745/2 "2020-08-04T16:23:11Z")

</div>

Not an exact answer but maybe of use.

In searching the GitHub SWI-Prolog repositories for prolog\_load\_file/2 found one example.

> <https://github.com/SWI-Prolog/packages-http/blob/4d5ff5575fba6df849e57caa1ef815993c0377ea/http_load.pl#L56-L82>

---

<div class="post-metadata">

**Author:** ![remy.s](https://avatars.discourse-cdn.com/v4/letter/r/54ee81/32.png) [@remy.s](https://swi-prolog.discourse.group/u/remy.s)\
**Post date:** [August 5, 2020, 8:47am UTC](https://swi-prolog.discourse.group/t/creating-prolog-clauses-with-prolog-load-file-2/2745/3 "2020-08-05T08:47:56Z")

</div>

Thanks for this feedback.  
I came across this example, too, but in the end, this one does nothing more than open an http-stream, then load\_file from this stream…  
Not really what I am looking for.

> …  
> setup\_call\_cleanup(  
> http\_open(FinalURL, In,  
> [ cert\_verify\_hook(ssl\_verify)  
> ]),  
> **load\_files(Module:FinalURL, [stream(In)|Options]),**  
> close(In)).

---

<div class="post-metadata">

**Author:** ![Boris](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/boris/32/7486_2.png) [@Boris](https://swi-prolog.discourse.group/u/Boris)\
**Post date:** [August 5, 2020, 9:01am UTC](https://swi-prolog.discourse.group/t/creating-prolog-clauses-with-prolog-load-file-2/2745/4 "2020-08-05T09:01:47Z")

</div>

Before I try to answer your question, I need to ask something:

Is there a particular reason why you are _writing_ text to a text file? Without understanding the issue you are solving, there are at least two other things you could try:

1. Directly use assertz/1 (also works with modules I think);
2. Use term\_expansion/2.

From what I see (correct me if I am wrong) it seems that you are writing text to a file and then loading the contents as if it were Prolog code; this feels like an overkill for most use cases (and it will be not easy to debug either…)

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [August 5, 2020, 9:13am UTC](https://swi-prolog.discourse.group/t/creating-prolog-clauses-with-prolog-load-file-2/2745/5 "2020-08-05T09:13:58Z")

</div>

> [@remy.s](#):
>
> However, I could not find any documentation how to create the clauses I would need.

That is completely up to you. Most of the implementations of this hook use it to get a handle to a stream containing Prolog source and than call load\_files/2 using the `stream(Input)` option to do the actual loading. This is typically used to load code from (web)servers, databases, etc. You can do anything you want in the hook though.

You do not need this hook if your only problem is the file name extension. You can load any file containing Prolog code simply by adding the file name extension or use prolog\_file\_type/2 to define your extension as a valid alternative extension. There is an extensive example on tweaking input in `library/dialect/xsb` to read XSB’s `.P` files.

---

<div class="post-metadata">

**Author:** ![remy.s](https://avatars.discourse-cdn.com/v4/letter/r/54ee81/32.png) [@remy.s](https://swi-prolog.discourse.group/u/remy.s)\
**Post date:** [August 5, 2020, 9:30am UTC](https://swi-prolog.discourse.group/t/creating-prolog-clauses-with-prolog-load-file-2/2745/6 "2020-08-05T09:30:12Z")

</div>

Well, my file does not contain prolog code at all. It has some structured data from an external source, that I can easily transform into prolog code.  
So I could actually do the following:

1. read my external file “test.mydat”,
2. transform it into a corresponding prolog file eg: “test\_mydat.pl”, and
3. load “test\_mydat.pl” in my prolog application.

The problem with this approach is that I would have to update “test\_mydat.pl” each time the underlying source would change.

But if I understand you well, 1 could do the following within my “prolog\_load\_file” hook:

1. read my external file “test.mydat”,
2. transform it into a corresponding prolog code and write this to some temporary file,
3. open the temporary file
4. and give this stream to load\_files with the stream(In) option

I would have thought there is something less convoluted to add the clauses to the program but I will give this a try.  
Thanks

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [August 5, 2020, 9:45am UTC](https://swi-prolog.discourse.group/t/creating-prolog-clauses-with-prolog-load-file-2/2745/7 "2020-08-05T09:45:57Z")

</div>

> [@remy.s](#):
>
> But if I understand you well, 1 could do the following within my “prolog\_load\_file” hook:

That should work. You do not really need to create a file, you can also put it in a memory file or string and open that. You can also parse the data to clauses and assert them, but that skips all the source administration and thus makes reloading the modified original file less obvious. You probably also want to use the modified(Time) option when loading the temporary file.

---

<div class="post-metadata">

**Author:** ![remy.s](https://avatars.discourse-cdn.com/v4/letter/r/54ee81/32.png) [@remy.s](https://swi-prolog.discourse.group/u/remy.s)\
**Post date:** [August 5, 2020, 11:58am UTC](https://swi-prolog.discourse.group/t/creating-prolog-clauses-with-prolog-load-file-2/2745/8 "2020-08-05T11:58:36Z")

</div>

Tested this approach, and is working well.  
However, loading a bunch of files (using load\_files with option expand(true)) seems very slow.  
But anyway, thanks for your valuable input

---

<div class="post-metadata">

**Author:** ![swi](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@swi](https://swi-prolog.discourse.group/u/swi)\
**Post date:** [August 5, 2020, 12:15pm UTC](https://swi-prolog.discourse.group/t/creating-prolog-clauses-with-prolog-load-file-2/2745/9 "2020-08-05T12:15:59Z")

</div>

> [@remy.s](#):
>
> However, loading a bunch of files (using load\_files with option expand(true)) seems very slow.

Perhaps it is loading them sequentially, try using the new concurrent\_forall/2 and see if you can load them in different threads.

EDIT: What I mean is something like this:

```prolog
parallel_load(ListOfFiles) :-
   concurrent_forall( member(File,ListOfFiles),
                       load_files([File])).

```

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [August 5, 2020, 12:35pm UTC](https://swi-prolog.discourse.group/t/creating-prolog-clauses-with-prolog-load-file-2/2745/10 "2020-08-05T12:35:19Z")

</div>

For concurrent usage, combine with directory\_member/3. First step I’d try is to do the load under profile/1 and see why it takes so long.

---

<div class="post-metadata">

**Author:** ![remy.s](https://avatars.discourse-cdn.com/v4/letter/r/54ee81/32.png) [@remy.s](https://swi-prolog.discourse.group/u/remy.s)\
**Post date:** [August 5, 2020, 1:40pm UTC](https://swi-prolog.discourse.group/t/creating-prolog-clauses-with-prolog-load-file-2/2745/11 "2020-08-05T13:40:11Z")

</div>

I can’t reproduce the slowness anymore!  
So the following now seems to work for me:

In “ **load.pl** ”

```prolog
 :- use_module(lib/mydat).
 :- load_files('mydata/*/*.mydat', [expand(true), if(changed)]).

```

and in **module mydat** :

```prolog
:- multifile fact/4.
 
user:prolog_load_file(Spec, _Options) :-
 	strip_module(Spec, _Mod, File)
 	, atom(File)
 	, file_name_extension(_Base, mydat, File)
 	, time_file(File, TimeStamp)
 	, read_mydat(File, Facts)
 	, setup_call_cleanup(
 		new_memory_file(Handle)
 		, (
 			setup_call_cleanup(
 				open_memory_file(Handle, write, MemOut)
 				, maplist(write_fact(MemOut), Facts)
 				, close(MemOut)
 			)
 			, open_memory_file(Handle, read, MemIn)
 			, load_files(Spec, [stream(MemIn), modified(TimeStamp)])
 		)
 		, free_memory_file(Handle)
 	)
 	.

```

---

<div class="post-metadata">

**Author:** ![EricGT](https://avatars.discourse-cdn.com/v4/letter/e/f1d935/32.png) [@EricGT](https://swi-prolog.discourse.group/u/EricGT)\
**Post date:** [August 5, 2020, 1:59pm UTC](https://swi-prolog.discourse.group/t/creating-prolog-clauses-with-prolog-load-file-2/2745/12 "2020-08-05T13:59:38Z")

</div>

While you can use ![image](https://global.discourse-cdn.com/free1/uploads/swiprolog/original/2X/3/374e3da7e1e4d79284bd17498e2f9e3dd297646e.png) to make source code appear different, a better way with Discourse and most sites that use [Markdown](https://www.markdownguide.org/) is to use ````` fences, e.g.

This is the raw code

```plaintext
lines([H|T]) :-
   line(H),
   lines(T).
lines([]).

```

This is the code as it appears using ![image](https://global.discourse-cdn.com/free1/uploads/swiprolog/original/2X/3/374e3da7e1e4d79284bd17498e2f9e3dd297646e.png)

> lines([H|T]) :-  
> line(H),  
> lines(T).  
> lines().

This is the code as it appears using ````` fences,

```prolog
lines([H|T]) :-
   line(H),
   lines(T).
lines([]).

```

This is how it is entered into the Discourse editor using `````.

```
```
lines([H|T]) :-
   line(H),
   lines(T).
lines([]).
```
```

😃

---

<div class="post-metadata">

**Author:** ![remy.s](https://avatars.discourse-cdn.com/v4/letter/r/54ee81/32.png) [@remy.s](https://swi-prolog.discourse.group/u/remy.s)\
**Post date:** [August 5, 2020, 2:03pm UTC](https://swi-prolog.discourse.group/t/creating-prolog-clauses-with-prolog-load-file-2/2745/13 "2020-08-05T14:03:47Z")

</div>

happy you told me. Next time I will do  
Thanks
