I have this Prolog program where I want to match players with players with the same level (newbie, intermediate, or expert) and server:
player(player29, 408, 183, europe).
player(player30, 462, 97, north-america).
player(player31, 25, 22, asia).
player(player32, 481, 248, asia).
player(player33, 111, 37, asia).
player(player34, 424, 359, north-america).
player(player35, 381, 358, asia).
player(player36, 231, 159, africa).
player(player37, 31, 20, africa).
player(player38, 22, 21, africa).
player(player39, 144, 35, oceania).
player(player40, 30, 25, asia).
player(player41, 221, 112, south-america).
player(player42, 344, 292, africa).
player(player43, 183, 148, asia).
player(player44, 62, 40, africa).
player(player45, 281, 23, north-america).
player(player46, 308, 173, south-america).
player(player47, 127, 125, asia).
player(player48, 441, 393, south-america).
player(player49, 213, 48, oceania).
player(player50, 343, 145, africa).
winrate(X):-player(X, T, W, _); (W/T) * 100.
newbie(X):-winrate(X) < 40.
intermediate(X):-winrate(X) >=40; winrate(X) < 80.
expert(X):-winrate(X) > 80.
However, I get a warning saying "Arithmetic: 'winrate(_G1082)' is not a function" when I compile it. Can someone explain to me what that means?
If I could nominate a misconception in Prolog for greatest all-time beginner stumbling block, it would be this: there is no such thing as a return value in Prolog. So the problem comes down to this definition:
winrate(X) :- player(X, T, W, _); (W/T) * 100.
If you type just that into Prolog, you'll get a mysterious looking warning message:
Warning: user://1:9:
Singleton variable in branch: T
Singleton variable in branch: W
I suspect you think that clause says "Look up T and W for player X and return W/T * 100." What Prolog actually thinks you said there is "Look up T and W for player X, or something over something times one hundred <awkward pause>" which is not particularly meaningful. When you ask winrate(player47)
, Prolog will stand in the corner with its hands in its pockets and say "um, true?"
The correction is this:
winrate(X, Rate) :- player(X, T, W, _), Rate is (W/T) * 100.
You have the exact same problem a little further down in newbie/1
et. al.: winrate(X) < 40
does not have intrinsic meaning in Prolog, because there is no "return value" in Prolog. The corrected expression is winrate(X, WinRate), WinRate < 40.
Note that there is nothing special about the last argument in Prolog. It's common for predicates with one-way semantics to use the last arguments for results, but it isn't really a law and Prolog is not enforcing anything there.
Pay close attention to singleton variable errors. Nothing meaningful happens in Prolog without variables appearing more than once, so if you get this error and you immediately replace the named variables with _
, does your clause still seem to have enough information to do its work? If not, you have almost certainly missed something or are confused about Prolog's semantics. Believe me, I learned this one from experience.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With