Page 1 of 1

e504 (Type incompatibility)

Posted: 14 Mar 2018 20:39
by daveplummermd
Can you help?

Compiler gives me error
e504 The expression has type '::string', which is incompatible with the type 'ArgType$*'
pointing to : ReplaceSlist = list::getMember_nd(LSlist),

Code: Select all

facts - similars     similar : (string_list).   predicates     substitute_Phrases : (string*, string*, string*) determ. clauses         substitute_Phrases(TokenList, _Int, _OutToken) :-         similar(LSlist),         ReplaceSlist = list::getMember_nd(LSlist),         stdio:write(ReplaceSlist),         fail.        

Can you help me understand so I can fix?

thanks in advance


Re: e504 (Type incompatibility)

Posted: 15 Mar 2018 3:34
by Harrison Pratt
You need a double colon here: stdio::write(ReplaceSlist)
That won't cause e504, though.

Other than that, it compiles OK after changing facts to class facts and predicates to class predicates.

Did you leave something out of your example code?

Re: e504 (Type incompatibility)

Posted: 15 Mar 2018 10:21
by Thomas Linder Puls
The essential thing in the error message is the * after ArgType$. Something should be a list but it is a string.

You do not indicate exactly where the error is given, and the code you present does not seem to have such a problem.

As s little side comment I suggest you "learn" to use foreach instead of creating fail-loops (and maybe also in instead of getMember_nd).

Code: Select all

clauses     substitute_Phrases(TokenList, _Int, _OutToken) :-         foreach similar(LSlist) and ReplaceSlist in LSlist do             stdio::write(ReplaceSlist)         end foreach,         ...

Re: e504 (Type incompatibility)

Posted: 15 Mar 2018 21:15
by daveplummermd
Thank you both for your replies.

Do you recommend "foreach" over backtracking into nondeterm clause for 1) readability of code or 2) run time efficiency. Or both?


Re: e504 (Type incompatibility)

Posted: 16 Mar 2018 9:20
by Thomas Linder Puls
The runtime efficiency is the same.

Calrity/readability is a heavy reason.
But this foreach[/balso have the great advantage that whatever you put between do and end foreach must be procedure.

This can prevent mistakes where the loop backtracks too early:

Code: Select all

xxx_nd(...),     ... % A     thisCanFailSometimes()     ... % B fail.
You intended the loop to run all the code between xxx_nd and fail for each xxx_nd result.

But thisCalFailSometimes can fail sometimes :-), and when it does the B code will not be run for xxx_nd result.

If you rewrite it using foreach then the compiler will give an error:

Code: Select all

foreach xxx_nd(...)do     ... % A     thisCanFailSometimes() % compiler error thisCanFailSometimes can fail     ... % B end foreach.
If you actually intended the code to work like that you can rewrite it like this:

Code: Select all

foreach xxx_nd(...)do     ... % A     if thisCanFailSometimes() then         ... % B     end if end foreach.
This code is slightly less efficient, but on the other hand it is very clear what the code does and that it is intended to do so.

You should notice that foreach always succeeds, whereas a fail loop always fails. So the "surrounding" code will also have to look different.