Predicate ordering when using current_predicate/1

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Predicate ordering when using current_predicate/1

emacstheviking
Hi,

There is no mention of the actual order of returned predicates, recently I created a testing framework and it has this line of code thanks to Daniel,

findall(Name,(current_predicate(Name/0), atom_concat('test_', _, Name)),AllTests)

I am writing tests now that rely upon them being executed in the order that they are defined in the source file i.e. the temporal order in which they were added to the database I presume.

However, they do not seem to come out in the expected order unless I have done something wrong but the above line of code is what dictates the order of execution.

Sean.


_______________________________________________
Users-prolog mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/users-prolog
Reply | Threaded
Open this post in threaded view
|

Re: Predicate ordering when using current_predicate/1

Paulo Moura-2

On 21/11/2013, at 15:48, emacstheviking <[hidden email]> wrote:

> Hi,
>
> There is no mention of the actual order of returned predicates,

For a good reason. That's not something that you should rely upon.

> recently I created a testing framework and it has this line of code thanks to Daniel,
>
> findall(Name,(current_predicate(Name/0), atom_concat('test_', _, Name)),AllTests)
>
> I am writing tests now that rely upon them being executed in the order that they are defined in the source file i.e. the temporal order in which they were added to the database I presume.
>
> However, they do not seem to come out in the expected order unless I have done something wrong but the above line of code is what dictates the order of execution.

An alternative could be to use an identifier per test that you can compare and sort. An example from the Logtalk's "ack" example unit tests:

test(ack_1) :-
        ...
test(ack_2) :-
        ...
test(ack_3) :-
        ...

Cheers,

Paulo

-----------------------------------------------------------------
Paulo Moura
Logtalk developer

Email: <mailto:[hidden email]>
Web:   <http://logtalk.org/>
-----------------------------------------------------------------





_______________________________________________
Users-prolog mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/users-prolog
Reply | Threaded
Open this post in threaded view
|

Re: Predicate ordering when using current_predicate/1

emacstheviking
I really don't want to go down that road but I guess if there is no choice I will have to... originally I had a predicate that explicitly returned the tests... I think I will do both... I will have a predicate that if it exists, can return a bunch of tests and they will be executed in order.

OK, I can live with that,
thanks again Paulo!
:)



On 21 November 2013 15:56, Paulo Moura <[hidden email]> wrote:

On 21/11/2013, at 15:48, emacstheviking <[hidden email]> wrote:

> Hi,
>
> There is no mention of the actual order of returned predicates,

For a good reason. That's not something that you should rely upon.

> recently I created a testing framework and it has this line of code thanks to Daniel,
>
> findall(Name,(current_predicate(Name/0), atom_concat('test_', _, Name)),AllTests)
>
> I am writing tests now that rely upon them being executed in the order that they are defined in the source file i.e. the temporal order in which they were added to the database I presume.
>
> However, they do not seem to come out in the expected order unless I have done something wrong but the above line of code is what dictates the order of execution.

An alternative could be to use an identifier per test that you can compare and sort. An example from the Logtalk's "ack" example unit tests:

test(ack_1) :-
        ...
test(ack_2) :-
        ...
test(ack_3) :-
        ...

Cheers,

Paulo

-----------------------------------------------------------------
Paulo Moura
Logtalk developer

Email: <mailto:[hidden email]>
Web:   <http://logtalk.org/>
-----------------------------------------------------------------





_______________________________________________
Users-prolog mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/users-prolog


_______________________________________________
Users-prolog mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/users-prolog
Reply | Threaded
Open this post in threaded view
|

Re: Predicate ordering when using current_predicate/1

Paulo Moura-2

On 21/11/2013, at 16:04, emacstheviking <[hidden email]> wrote:

> I really don't want to go down that road but I guess if there is no choice I will have to... originally I had a predicate that explicitly returned the tests... I think I will do both... I will have a predicate that if it exists, can return a bunch of tests and they will be executed in order.

Can't you simply sort the list resulting from the findall/3 call or use setof/3?

Cheers,

Paulo

> OK, I can live with that,
> thanks again Paulo!
> :)
>
>
>
> On 21 November 2013 15:56, Paulo Moura <[hidden email]> wrote:
>
> On 21/11/2013, at 15:48, emacstheviking <[hidden email]> wrote:
>
> > Hi,
> >
> > There is no mention of the actual order of returned predicates,
>
> For a good reason. That's not something that you should rely upon.
>
> > recently I created a testing framework and it has this line of code thanks to Daniel,
> >
> > findall(Name,(current_predicate(Name/0), atom_concat('test_', _, Name)),AllTests)
> >
> > I am writing tests now that rely upon them being executed in the order that they are defined in the source file i.e. the temporal order in which they were added to the database I presume.
> >
> > However, they do not seem to come out in the expected order unless I have done something wrong but the above line of code is what dictates the order of execution.
>
> An alternative could be to use an identifier per test that you can compare and sort. An example from the Logtalk's "ack" example unit tests:
>
> test(ack_1) :-
>         ...
> test(ack_2) :-
>         ...
> test(ack_3) :-
>         ...
>
> Cheers,
>
> Paulo

-----------------------------------------------------------------
Paulo Moura
Logtalk developer

Email: <mailto:[hidden email]>
Web:   <http://logtalk.org/>
-----------------------------------------------------------------





_______________________________________________
Users-prolog mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/users-prolog
Reply | Threaded
Open this post in threaded view
|

Re: Predicate ordering when using current_predicate/1

emacstheviking
I *used* to sort them but that destroys the order I want to have them execute in. I wanted them to execute in the order they are declared in the file... the only other alternative I thought about was manually parsing the file and finding all lines starting with "test_" and doing it that way... maybe I will!

I will find a way that is simple.

No worries.



On 21 November 2013 16:08, Paulo Moura <[hidden email]> wrote:

On 21/11/2013, at 16:04, emacstheviking <[hidden email]> wrote:

> I really don't want to go down that road but I guess if there is no choice I will have to... originally I had a predicate that explicitly returned the tests... I think I will do both... I will have a predicate that if it exists, can return a bunch of tests and they will be executed in order.

Can't you simply sort the list resulting from the findall/3 call or use setof/3?

Cheers,

Paulo

> OK, I can live with that,
> thanks again Paulo!
> :)
>
>
>
> On 21 November 2013 15:56, Paulo Moura <[hidden email]> wrote:
>
> On 21/11/2013, at 15:48, emacstheviking <[hidden email]> wrote:
>
> > Hi,
> >
> > There is no mention of the actual order of returned predicates,
>
> For a good reason. That's not something that you should rely upon.
>
> > recently I created a testing framework and it has this line of code thanks to Daniel,
> >
> > findall(Name,(current_predicate(Name/0), atom_concat('test_', _, Name)),AllTests)
> >
> > I am writing tests now that rely upon them being executed in the order that they are defined in the source file i.e. the temporal order in which they were added to the database I presume.
> >
> > However, they do not seem to come out in the expected order unless I have done something wrong but the above line of code is what dictates the order of execution.
>
> An alternative could be to use an identifier per test that you can compare and sort. An example from the Logtalk's "ack" example unit tests:
>
> test(ack_1) :-
>         ...
> test(ack_2) :-
>         ...
> test(ack_3) :-
>         ...
>
> Cheers,
>
> Paulo

-----------------------------------------------------------------
Paulo Moura
Logtalk developer

Email: <mailto:[hidden email]>
Web:   <http://logtalk.org/>
-----------------------------------------------------------------





_______________________________________________
Users-prolog mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/users-prolog


_______________________________________________
Users-prolog mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/users-prolog
Reply | Threaded
Open this post in threaded view
|

Re: Predicate ordering when using current_predicate/1

Daniel Diaz-3
In reply to this post by emacstheviking
Hi,

here is a piece of code doing what you want

get_tests(L) :-
    setof(t(File, Line, Name), get_one_test(File, Line, Name), L).


get_one_test(File, Line, Name) :-
    current_predicate(Name/0),
    atom_concat('test_', _, Name),
    predicate_property(Name, prolog_file(File)),
    predicate_property(Name, prolog_line(Line)).


This returns a list containing triplets t(File, Line, Name) where File is the file pathname of the test, Line is the line number in the source file and Name the test name (beginning by test_). The list is sorted on File and then on Line.

I keep the File in case your tests reside in different files, if it is not the case you simplify the code by removing everything related to File (including predicate_property(..., prolog_line(Line))).

If you only need the list of test names (and don't want the File and Line), you can define

get_tests_name(AllTests) :-
    get_tests(L),
    findall(Name, member(t(_,_,Name), L), AllTests).


Then get_test_names does the job.

Daniel



Le 21/11/2013 16:48, emacstheviking a écrit :
Hi,

There is no mention of the actual order of returned predicates, recently I created a testing framework and it has this line of code thanks to Daniel,

findall(Name,(current_predicate(Name/0), atom_concat('test_', _, Name)),AllTests)

I am writing tests now that rely upon them being executed in the order that they are defined in the source file i.e. the temporal order in which they were added to the database I presume.

However, they do not seem to come out in the expected order unless I have done something wrong but the above line of code is what dictates the order of execution.

Sean.



--
Ce message a été vérifié par MailScanner pour des virus ou des polluriels et rien de suspect n'a été trouvé.
_______________________________________________
Users-prolog mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/users-prolog
Reply | Threaded
Open this post in threaded view
|

Re: Predicate ordering when using current_predicate/1

emacstheviking
Daniel,

Your answers always leave me wondering why I didn’t see the “obvious” for myself…sigh. Well, I immediately went and read the relevant documentation and so I am sure I would have figured it out had I the intelligence to find predicate_property/2 myself!

I smell a good “meta-level” application coming on god dammit. I am never gong to finish my main project at this rate as I keep getting side-tracked by other shiny possibilities!

Armed with this then I will attempt now to re-jig my test framework and then complete the Redis client and put it out there for public consumption… I will probably make it compatible with SWI as well as it is pretty simple.

Thanks again,
All the best.
Sean.


On 22 Nov 2013, at 16:53, Daniel Diaz <[hidden email]> wrote:

Hi,

here is a piece of code doing what you want

get_tests(L) :-
    setof(t(File, Line, Name), get_one_test(File, Line, Name), L).


get_one_test(File, Line, Name) :-
    current_predicate(Name/0),
    atom_concat('test_', _, Name),
    predicate_property(Name, prolog_file(File)),
    predicate_property(Name, prolog_line(Line)).


This returns a list containing triplets t(File, Line, Name) where File is the file pathname of the test, Line is the line number in the source file and Name the test name (beginning by test_). The list is sorted on File and then on Line.

I keep the File in case your tests reside in different files, if it is not the case you simplify the code by removing everything related to File (including predicate_property(..., prolog_line(Line))).

If you only need the list of test names (and don't want the File and Line), you can define

get_tests_name(AllTests) :-
    get_tests(L),
    findall(Name, member(t(_,_,Name), L), AllTests).


Then get_test_names does the job.

Daniel



Le 21/11/2013 16:48, emacstheviking a écrit :
Hi,

There is no mention of the actual order of returned predicates, recently I created a testing framework and it has this line of code thanks to Daniel,

findall(Name,(current_predicate(Name/0), atom_concat('test_', _, Name)),AllTests)

I am writing tests now that rely upon them being executed in the order that they are defined in the source file i.e. the temporal order in which they were added to the database I presume.

However, they do not seem to come out in the expected order unless I have done something wrong but the above line of code is what dictates the order of execution.

Sean.



--
Ce message a été vérifié par MailScanner pour des virus ou des polluriels et rien de suspect n'a été trouvé.


_______________________________________________
Users-prolog mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/users-prolog
Reply | Threaded
Open this post in threaded view
|

Re: Predicate ordering when using current_predicate/1

emacstheviking
In reply to this post by Daniel Diaz-3
Danieal,

Mission accomplished!

I ran with what you gave me and I now have a process that executes tests in the same order as they are declared in the source text. I had to learn (very quickly) about the A-B pair notation, something I had not seen before but as with the predicate indicator thing, once you know how it works the rest is easy…easier.

Here’s what I ended up with:
run_tests :-
        get_all_tests(AllTests),
        keysort(AllTests, SortedTests),
        maplist(exec_test, SortedTests),

The get_all_tests/1 predicate and the supporting acts look like this:
get_all_tests(Tests) :-
setof(Line-Name, get_one_test(Name, Line), Tests).


get_one_test(Name, Line) :-
current_predicate(Name/0),
atom_concat('test_', _, Name),
predicate_property(Name, prolog_line(Line)).


exec_test(_-TestFunction) :- /* omitted for brevity! */

Essentially I get all the test_ predicates then keysort/2 them into line number order and then maplist/2 over the exec_test/1 function which is now modified to accept a pair. Damn that’s useful to know!

So, once again, thank you very mud for your support in helping me out.

I am going to try to finish my Redis tests over the weekend and then I am going to update my “main” project with this improved code. in fact, I might even create a little github project and then include it as a dependency or something like that later on.

Have a great weekend!
:)
Sean.





_______________________________________________
Users-prolog mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/users-prolog
Reply | Threaded
Open this post in threaded view
|

Re: Predicate ordering when using current_predicate/1

Daniel Diaz-3
Hi Sean

Well done ! However, I don’t understand why you added the call to keysort/2 since setof/3 already sorts the list (this is the only difference between setof/ and bagof/3). You can remove it.

Daniel

PS: about sockets: I have put a version in the git which adds the SO_REUSEADDR option at socket creation. To get it:

git clone <a href="git://git.code.sf.net/p/gprolog/code">git://git.code.sf.net/p/gprolog/code gprolog-code

BTW: if you write on the socket, you may to call flush_output(SO) to be sure the data is sent (and thus accessible on the other side).

Le 22 nov. 2013 à 23:43, Sean Charles <[hidden email]> a écrit :

Danieal,

Mission accomplished!

I ran with what you gave me and I now have a process that executes tests in the same order as they are declared in the source text. I had to learn (very quickly) about the A-B pair notation, something I had not seen before but as with the predicate indicator thing, once you know how it works the rest is easy…easier.

Here’s what I ended up with:
run_tests :-
        get_all_tests(AllTests),
        keysort(AllTests, SortedTests),
        maplist(exec_test, SortedTests),

The get_all_tests/1 predicate and the supporting acts look like this:
get_all_tests(Tests) :-
setof(Line-Name, get_one_test(Name, Line), Tests).


get_one_test(Name, Line) :-
current_predicate(Name/0),
atom_concat('test_', _, Name),
predicate_property(Name, prolog_line(Line)).


exec_test(_-TestFunction) :- /* omitted for brevity! */

Essentially I get all the test_ predicates then keysort/2 them into line number order and then maplist/2 over the exec_test/1 function which is now modified to accept a pair. Damn that’s useful to know!

So, once again, thank you very mud for your support in helping me out.

I am going to try to finish my Redis tests over the weekend and then I am going to update my “main” project with this improved code. in fact, I might even create a little github project and then include it as a dependency or something like that later on.

Have a great weekend!
:)
Sean.





--
Ce message a été vérifié par MailScanner pour des virus ou des polluriels et rien de suspect n'a été trouvé.


--
Ce message a été vérifié par MailScanner pour des virus ou des polluriels et rien de suspect n'a été trouvé.
_______________________________________________
Users-prolog mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/users-prolog
Reply | Threaded
Open this post in threaded view
|

Re: Predicate ordering when using current_predicate/1

emacstheviking

On 23 Nov 2013, at 11:28, Daniel Diaz <[hidden email]> wrote:

Hi Sean

Well done !

Thanks. Praise indeed. Sadly lacking in the day job lately!

However, I don’t understand why you added the call to keysort/2 since setof/3 already sorts the list (this is the only difference between setof/ and bagof/3). You can remove it.

I wasn’t sure about that either because I am returning a pair with Line-Name i.e. line-number and test function and I wasn’t sure *how* the default sort would handle that so I rolled my own. Basically I was not sure what the collation order would be for my list. I don’t think the documentation says what it does to determine the ordering so I took no chances!

 I *will* take it out and see what happens though. In the documentation it says that it uses "sort(I,Instances)” but I couldn’t seem to relate that to my code. I will re-visit and try to understand again. One thing I know, it is worth getting good with the debugger which I am quite familiar with now.

PS: about sockets: I have put a version in the git which adds the SO_REUSEADDR option at socket creation. To get it:

git clone <a href="git://git.code.sf.net/p/gprolog/code">git://git.code.sf.net/p/gprolog/code gprolog-code

That’s nice to know… I will do a build today to get the “~” fix you did too. Getting the dreaded “address already in use” can be really irritating when you are rapid fire developing some server or client stuff.


BTW: if you write on the socket, you may to call flush_output(SO) to be sure the data is sent (and thus accessible on the other side).

I have done enough with sockets over the years to know flush() is your friend! I will add a flush to be safe.

Lunch beckons, that some basketball with my son but tonight I hack for England. Having learned Lisp, Erlang, Haskell I am starting to think that Prolog is what I have been “yearning for” all my life! Oh my god, did I just say that! Yes, you did, no go out and get a life 
:)

All the best,
Sean.






Le 22 nov. 2013 à 23:43, Sean Charles <[hidden email]> a écrit :

Danieal,

Mission accomplished!

I ran with what you gave me and I now have a process that executes tests in the same order as they are declared in the source text. I had to learn (very quickly) about the A-B pair notation, something I had not seen before but as with the predicate indicator thing, once you know how it works the rest is easy…easier.

Here’s what I ended up with:
run_tests :-
        get_all_tests(AllTests),
        keysort(AllTests, SortedTests),
        maplist(exec_test, SortedTests),

The get_all_tests/1 predicate and the supporting acts look like this:
get_all_tests(Tests) :-
setof(Line-Name, get_one_test(Name, Line), Tests).


get_one_test(Name, Line) :-
current_predicate(Name/0),
atom_concat('test_', _, Name),
predicate_property(Name, prolog_line(Line)).


exec_test(_-TestFunction) :- /* omitted for brevity! */

Essentially I get all the test_ predicates then keysort/2 them into line number order and then maplist/2 over the exec_test/1 function which is now modified to accept a pair. Damn that’s useful to know!

So, once again, thank you very mud for your support in helping me out.

I am going to try to finish my Redis tests over the weekend and then I am going to update my “main” project with this improved code. in fact, I might even create a little github project and then include it as a dependency or something like that later on.

Have a great weekend!
:)
Sean.





--
Ce message a été vérifié par MailScanner pour des virus ou des polluriels et rien de suspect n'a été trouvé.


--
Ce message a été vérifié par MailScanner pour des virus ou des polluriels et rien de suspect n'a été trouvé.


_______________________________________________
Users-prolog mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/users-prolog