Home   Archive   Permalink

Slicker way to check a field value

I want to check a data entry field for validity. It is the score of a sporting event. The scores can go only into the single digits, so a score has a very limited range of possibilities, and will be entered as the winner's points, a hyphen, and the loser's points, as in 6-1 or 6-0 or maybe 6-6 for a tie.    
I know one way to check the field, which would be to extract the first character and check that it is a number, extract the second character and make sure it is a hyphen, and extract the third character and make sure it is a number. BUT, I have a feeling there is a slicker, REBOL-like, parsey way to do that, but I can't quite imagine how.    
Not an urgent problem. I probably will go ahead and write the 'brute force' method outlined above and encapsulate it in a function, and then replace that function if anyone has any ideas for me.
Thank you.

posted by:   Steven White     18-Aug-2015/13:54:15-7:00

parse-score: func [
     {Returns a block with 2 scores or none on invalid string.}
     score-string [string!]
     /local digit score1 score2
] [
     digit: charset [#"0" - #"9"]
     unless parse score-string [
         copy score1 digit
         copy score2 digit
     ] [return none]
     score1: to integer! score1
     score2: to integer! score2
     either score1 >= score2 [reduce [score1 score2]] [none]

posted by:   point     18-Aug-2015/14:38-7:00

PARSE doesn't have any innate recognition of INTEGER! when looking at STRING! (It could recognize them in a BLOCK! of values, but the process of "transcoding" the individual characters to make a number is not a feature of today's PARSE. Though that might be interesting.)
So you'll only get minor benefit (if any) from PARSE over your brute force solution, because what parse will do is recognize digits and a dash and more digits... then you'll still have work to do.
A simpler solution would be to just take out the dash and LOAD it:
     >> load replace/all "6-0" #"-" space
     == [6 0]
At that point, PARSE can be useful for making sure you got what you expected, processing the Rebol values instead of a string:
     either parse [6 0] [
         set team1/score integer!
         set team2/score integer!
     ] [
         print ["Team1 score:" team1/score]
         print ["Team2 score:" team2/score]
     ] [
         print "Bad input!"
Your job is made easier any time you can convince people to give you input in a form Rebol can natively read. It would have been able to load "6 - 0" no problem, then you could have accounted for it in the Parse as:
     either parse [6 - 0] [
         set team1/score integer!
         set team2/score integer!
     ] [
It's not always possible or desirable to constrain one's UI that much for typing interfaces for users, to make them type legal Rebol input into every field. But for oneself or a certain audience of coders, thinking that way is the right avenue for getting the most mileage out of it.

posted by:   Fork     18-Aug-2015/14:47:08-7:00

valid-score: "0123456789"
raw-scores: ["4-" "0x5" "6-2"]
foreach raw-score raw-scores [
     prin [raw-score " ...."]
     either all [find validscore raw-score/1 raw-score/2 = #"-" find validscore raw-score/3][print "ok"][print "bad"]
4- ....bad
0x5 ....bad
6-2 ....ok

posted by:   Tigger     19-Aug-2015/10:07:47-7:00

Thank you all for the ideas. For completeness, I will show what I finally did. I still am trapped in third-generation thinking. If the number of score combinations is so small, just don't let the operator enter a wrong one in the first place, as follows:
R E B O L [
view layout [
     SCORE: drop-down 100 data ["6-0" "6-1" "6-2" "6-3" "6-4" "6-5" "6-6"]
     box 100x200 ;; so drop-down has room to drop down
     button 150 "Show selection" [print SCORE/text]

posted by:   Steven White     20-Aug-2015/11:56:19-7:00