Page 1 of 1
e504 (Type incompatibility)
Posted: 14 Mar 2018 20:39
by daveplummermd
Guys
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
dave
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?
Thanks
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.