I have a database of facts that has entries like this snippet
symptom(shingles,headache).
symptom(shingles,fever).
symptom(shingles,malaise).
symptom(shingles,headache).
symptom(shingles,itching).
symptom(shingles,hyperesthesia).
symptom(shingles,paresthesia).
test(shingles,blood).
test(shingles,pcr).
locale(shingles,all).
treatment(shingles,calamine).
treatment(shingles,aciclovir).
treatment(shingles,valaciclovir).
treatment(shingles,famciclovir).
treatment(shingles,corticosteroids).
I then have a predicate that gets a list of symptoms from the user.
getSymptoms(Symptoms) :-
write('Please enter symptoms now, enter "Done" when finished: ' ),
read_string(user, "\n", "\r", _, Response),
(
Response == "Done"
->
Symptoms = []
;
getSymptoms(Symptoms0),
Symptoms = [Response|Symptoms0]
).
My question is how do I compare the lists of user symptoms to the symptoms fact second atom, and then add the disease to another list?
For example, the user enters fever. Since fever is in the symptom fact for shingles, it would add shingles to a list.
This will work, but allows for duplicate symptoms to be entered. I am posting it now so you can see the first part of the transformation and will post the part without the duplicates when I get that working.
getSymptoms(Symptoms) :-
write('Please enter symptoms now, enter "Done" when finished: ' ),
read_string(user, "\n", "\r", _, Response),
(
Response == "Done"
->
Symptoms = []
;
atom_string(Symptom,Response),
valid_symptom(Symptom,Symptoms)
).
valid_symptom(Symptom,Symptoms) :-
(
symptom(_,Symptom)
->
% Symptom was valid
% so get next symptom and
% add to list on backtracking
getSymptoms(Symptoms0),
Symptoms = [Symptom|Symptoms0]
;
% Symptom was invalid
% so warn user of invalid symptom and what they input
% and get next symptom.
% Do not add invalid Symptom to list on backtracking.
format('Invalid symptom: `~w''~n',[Symptom]),
getSymptoms(Symptoms0),
Symptoms = Symptoms0
).
Since the values entered are strings and the symptoms are atoms in symptom/2 facts, the input needs to be converted to an atom for comparison. This is done using atom_string/2
atom_string(Symptom,Response)
To give a user feedback if the symptom is invalid format/2 is used. It is better to use than write/1 since it gives you more control over the output.
format('Invalid symptom: `~w''~n',[Symptom])
If an invalid value is entered for as a symptom it should not be added to the list. This is a classic if/then type of scenario and in Prolog is done with ->/2. Here is the standard template
(
<conditional>
->
<true branch>
;
<false branch>
)
the conditional is
symptom(_,Symptom)
Notice also with the conditional, that it reads the symptom/2 facts and ignores the first part of the compound structure, i.e. _, and matches the input symptom with a symptom in the facts. This is were the comparison is done, but it is done via unification and not with a compare predicate such as ==/2.
The true branch is the same as before
getSymptoms(Symptoms0),
Symptoms = [Symptom|Symptoms0]
however the false branch is
format('Invalid symptom: `~w''~n',[Symptom]),
getSymptoms(Symptoms0),
Symptoms = Symptoms0
Notice that the invalid Symptom is not added to the list with [Symptom|Symptoms0] and also that both branches (true and false) should update the same variables, Symptoms, which in the false branch is done with Symptoms = Symptoms0 which is not assignment but =/2 (unification).
The code for valid_symptom/2 could have been inlined with getSymptoms/1 but I pulled it out so you could see how it is done in case you need to do that in the future.
Example run:
?- getSymptoms(Symptoms).
Please enter symptoms now, enter "Done" when finished: wrong
Invalid symptom: `wrong'
Please enter symptoms now, enter "Done" when finished: headache
Please enter symptoms now, enter "Done" when finished: malaise
Please enter symptoms now, enter "Done" when finished: headache
Please enter symptoms now, enter "Done" when finished: Done
Symptoms = [headache, malaise, headache].
Here is the next variation that removes duplicates while building the list.
getSymptoms(Result) :-
getSymptoms_helper([],Result).
getSymptoms_helper(Symptoms,Result) :-
write('Please enter symptoms now, enter "Done" when finished: ' ),
read_string(user, "\n", "\r", _, Response),
(
Response == "Done"
->
Result = Symptoms
;
atom_string(Symptom,Response),
valid_symptom(Symptom,Symptoms,Result)
).
valid_symptom(Symptom,Symptoms,Result) :-
(
memberchk(Symptom,Symptoms)
->
% Symptom was a duplicate
% Do not add duplicate Symptom to list.
getSymptoms_helper(Symptoms,Result)
;
(
symptom(_,Symptom)
->
% Symptom was valid
% so get next symptom and
% add to list.
getSymptoms_helper([Symptom|Symptoms],Result)
;
% Symptom was invalid
% so warn user of invalid symptom and what they input
% and get next symptom.
% Do not add invalid Symptom to list.
format('Invalid symptom: `~w''~n',[Symptom]),
getSymptoms_helper(Symptoms,Result)
)
).
The major change here is that an accumulator Symptoms is threaded through the predicates so that the list of valid symptoms can be built and used for testing the next input value. Since the accumulator needs to be initialized at the start, the previous predicate renamed to getSymptoms_helper so that the accumulator can be initialized with
getSymptoms_helper([],Result)
Notice [] that passes to
getSymptoms_helper(Symptoms,Result)
thus setting the initial value of Symptoms to [].
When Done is entered, the list is unified with Result and passed back upon back-chaining. Normally the variables would be named Symptoms0 and Symptoms but I kept them this way so they are easier to follow. Other wise there would be variables Symptom, Symptoms and Symptoms0, but once you get use to them are easier to follow.
The check for duplicates is done using memberchk/2 which is better than using member/2 for checking. Again this adds another conditional to the mix.
Example run:
?- getSymptoms(Symptoms).
Please enter symptoms now, enter "Done" when finished: headache
Please enter symptoms now, enter "Done" when finished: malaise
Please enter symptoms now, enter "Done" when finished: headache
Please enter symptoms now, enter "Done" when finished: Done
Symptoms = [malaise, headache].
The issue is: I cannot figure out what the error is refering to when it diplays
Here is the error:
source_file.fs(10,5): error FS0010: Unexpected keyword 'if' in binding. Expected '=' or other token.
And I've been researching this error and proper syntax for a good while.
Now what I want to do, I hope, is obvious from the general look of the program.
Knowing the correct syntax would be great as microsofts docs are not great.
Seeing as this is case, I just don't understand what could be wrong.
open System
let one = "one"
let two = "two"
if oneortwo one then printfn one + " 1"
else printfn two + " 2"
let oneortwo(a : string)
if a = "one" then return true
elif a = "two" then return false
return false
F# is an expression based language, which means that everything has a value (returns something). F# is also statically typed, so everything returned is of a specific type.
Since everything is an expression, the return keyword is not used. The final expression in a function body is the returned value.
This goes also for if ... then ... else: every branch must return a value and be of the same type.
The correct syntax for your function is
let oneortwo a =
if a = "one" then true
else false
An excellent source of learning F# is Scott Wlaschin's site F# for fun and profit
I would like to calculate the amount of 2 fields, and ordering the results by.
The querybuilder ends like this:
$qb->orderBy('(e.likesCnt + e.additionalLikes)', 'DESC')
and I got this error:
An exception has been thrown during the rendering of a template
("[Syntax Error] line 0, col 264: Error: Expected end of string, got
'e'")
Last try was when:
$qb->select('e, (e.likesCnt + e.additionalLikes) AS totalLikes')
$qb->orderBy('totalLikes', 'DESC')
but it brings an error too
An exception has been thrown during the rendering of a template
("[Semantical Error] line 0, col 290 near 'totalLikes DESC,': Error:
'totalLikes' is not defined.")
Any solutions gratefully accepted :-)
Update:
Well, alias is not allowed in the "orderby" statement. Also, if one of your field is null then the amount will be null too, that's cause the semantical error. My solution is:
$qb->orderBy('((e.likesCnt + e.additionalLikes)+0)', 'DESC')
In this case, the ordering will be applicated without semantical error and gets the correct results.
The select method is getting parameter as array, for example:
$qb->select('e', '(e.likesCnt + e.additionalLikes) AS totalLikes')
$qb->orderBy('totalLikes', 'DESC')
Experimenting with the language I've found that select is defined in the global scope and its precedence is higher than local variables.
def example(select)
puts select
end
example 3
# Syntax error in eval:3: unexpected token: end (expecting when, else or end)
So experimenting with select step by step I get this:
select 1 end
# Syntax error in eval:3: unexpected token: end (expecting when, else or end)
and then
select when 1 end
# Syntax error in eval:1: invalid select when expression: must be an assignment or call
then
select when x = 1 end
# Syntax error in eval:1: invalid select when expression: must be an assignment or call
then
select when x
# Syntax error in eval:1: unexpected token: EOF (expecting ',', ';' or '
I'll skip ahead a few steps as you should have an idea of how I've come to my question…
select when x;
else y
end
# Error in line 1: undefined local variable or method 'x_select_action'
and lastly
x_select_action = 4
select when x;
else y
end
# Error in line 3: undefined method 'x_select_action' (If you declared 'x_select_action' in a suffix if, declare it in a regular if for this to work. If the variable was declared in a macro it's not visible outside it)
So there is this keyword in the language which precedes local variables precedence and I don't know what it's for. But apparently it looks for x_select_action when x is given as a when clause. What is this select for and how is it meant to be used?
Searching online I see select defined on Enumerable, Hash, Channel, and Array… but at first glance these don't seem to be it.
Thanks for the help!
It's similar to Go's select: https://tour.golang.org/concurrency/5
But it still needs some tweaks to be finished, that's why there are no docs about it yet.
I have a simple example in GNU Smalltalk 3.2.5 of attempting to group match on a key value setting:
st> m := 'a=b' =~ '(.*?)=(.*)'
MatchingRegexResults:'a=b'('a','b')
The above example works just as expected. However, if there is no match to the second group (.*), an exception is generated:
st> m := 'a=' =~ '(.*?)=(.*)'
Object: Interval new "<-0x4ce2bdf0>" error: Invalid index 1: index out of range
SystemExceptions.IndexOutOfRange(Exception)>>signal (ExcHandling.st:254)
SystemExceptions.IndexOutOfRange class>>signalOn:withIndex: (SysExcept.st:660)
Interval>>first (Interval.st:245)
Kernel.MatchingRegexResults>>at: (Regex.st:382)
Kernel.MatchingRegexResults>>printOn: (Regex.st:305)
Kernel.MatchingRegexResults(Object)>>printString (Object.st:534)
Kernel.MatchingRegexResults(Object)>>printNl (Object.st:571)
I don't understand this behavior. I would have expected the result to be ('a', nil) and that m at: 2 to be nil. I tried a different approach as follows:
st> 'a=' =~ '(.*?)=(.*)' ifMatched: [ :m | 'foo' printNl ]
'foo'
'foo'
Which determines properly that there's a match to the regex. But I still can't check if a specific group is nil:
st> 'a=' =~ '(.*?)=(.*)' ifMatched: [ :m | (m at: 2) ifNotNil: [ (m at: 2) printNl ] ]
Object: Interval new "<-0x4ce81b58>" error: Invalid index 1: index out of range
SystemExceptions.IndexOutOfRange(Exception)>>signal (ExcHandling.st:254)
SystemExceptions.IndexOutOfRange class>>signalOn:withIndex: (SysExcept.st:660)
Interval>>first (Interval.st:245)
Kernel.MatchingRegexResults>>at: (Regex.st:382)
optimized [] in UndefinedObject>>executeStatements (a String:1)
Kernel.MatchingRegexResults>>ifNotMatched:ifMatched: (Regex.st:322)
Kernel.MatchingRegexResults(RegexResults)>>ifMatched: (Regex.st:188)
UndefinedObject>>executeStatements (a String:1)
nil
st>
I don't understand this behavior. I would have expected the result to be ('a', nil) and that m at: 2 to be nil. At least that's the way it works in any other language I've used regex in. This makes me think maybe I'm not doing something correct with my syntax.
My question this is: do I have the correct syntax for attempting to match ASCII key value pairs like this (for example, in parsing environment settings)? And if I do, why is an exception being generated, or is there a way I can have it provide a result that I can check without generating an exception?
I found a related issue reported at gnu.org from Dec 2013 with no responses.
The issue had been fixed in master after the above report was received. The commit can be seen here. A stable release is currently blocked by the glib event loop integration.
ValidationExpression="[0-9]{2}[(a-z)(A-Z)]{5}\d{4}[(a-z)(A-Z)]{1}\d{1}Z\d{1}"
SetFocusOnError="true" ControlToValidate="txtGST" Display="Dynamic" runat="server" ErrorMessage="Invalid GST No." ValidationGroup="Add" ForeColor="Red"></asp:RegularExpressionValidator>