Home   Archive   Permalink

comparing characters in a string with pick

Hi guys!
I'm having trouble understanding how Rebol is interpreting this instruction.
Let's say that I have two strings:
c: "rrrr" ;and
g: "rrrg"
I want to see if the last characters match or not using pick. So if I go...
either pick c 4 = pick g 4 [print "match"] [print "no match"]
I'm expecting a no match, because "r" does not equal "g". But I get a match. I also get a match if I try...
either (pick c 4 = pick g 4) [print "match"] [print "no match"]
How come pick c 4 = pick g 4 resolves to true? Only if I do
either (pick c 4) = (pick g 4) [print "match"] [print "no match"]
do I get the expected 'no match' result.
I thought that the parentheses were not really neccesary, yet I see that they change the interpretation in a way I don't understand.
Any insights?
The Little Rebol Rat

posted by:   The Little Rebol Rat     7-Sep-2019/13:55-7:00

Here's something to know about that's a bit odd about historical Rebol: PICK with a LOGIC! will give you the first item of something if true, and the second if false.
     >> block: [a < b > #c]
     >> pick block true
     == a
     >> pick block false
     == < b >
(I always thought that was questionable semantics. Why wouldn't false pick the last item? If this is a good idea at all, I'd think it should give some protections by erroring if the series had anything other than two items to pick from...)
But since it doesn't error, you are seeing this situation. This is because when the evaluator is grinding across an expression, infix operators like `=` only see one element to their left...and run greedily. What you're actually running is thus:
     either pick c (4 = pick g 4) [print "match"] [print "no match"]
That greedy equals concluded that the INTEGER! 4 was not equal to the CHAR! #"g". So you got `pick c false`, the second character of c, which was an #"r". All values but NONE! or logic FALSE! are conditionally truthy...hence you get the match branch running.
> The Little Rebol Rat
:-) If you're willing to stick around to grow to be a larger Rebol Rat despite oddities like this case, you'll perhaps see what makes Rebol addictive. Some camps (e.g. me) think addressing its "unsafe" aspects can be accomplished without compromising the fun parts...and it can be made even more fun:
Feel free to join the discourse forum, which focuses on "Ren-C":

posted by:   Fork     7-Sep-2019/14:45:59-7:00

Argh, I forgot that this forum can't have TAG! types in it without a problem. Let's try closing the tag I used:
Then change my example to
     >> block: [a "b" #c]
     >> pick block true
     == a
     >> pick block false
     == "b"
(While Nick's forum has its benefits by being a quite small script, it's not under development and has some unaddressed quirks!)

posted by:   Fork     7-Sep-2019/14:49:04-7:00

Thank you, Mr. Fork!
I truly appreciate the help. The information was very useful. Now I know why the code would go to true so quickly. Amazing how many different things worked together to produce this result.
Your information about infix operators was jaw-dropping. I rally though that Rebol was strict about evaluating from left to right. I changed the “=” for “equal?” and it worked like a charm without having to add parentheses:
>>either equal? pick g 4 pick c 4 [print "Match!"] [print "No match..."]
==No match...
I see now that pick can also use logic, which is very helpful with learning how this little bug came to be.
I’m really motivated to learn some more Rebol. I find it much more fun than the boring Scratch stuff we were doing at school. I don’t mind the quirks as long I can find explanations like yours.
Thank you for the help!
The Little Rebol Rat

posted by:   The Little Rebol Rat     8-Sep-2019/17:30:50-7:00

Glad to help...!
Infix is different in our "Ren-C" branch, and if you would like to read about what we call "enfix" it is here:

posted by:   Fork     11-Sep-2019/15:30:37-7:00

Infix equals is syntactic sugar. This is owing to eval rules:
1. Left to right, usually
2. but Rebol must gobble arguments for words that function first
Notice that prefix equals works as expected!
>> = pick c 4 pick g 4
== false
That is because of this:
1. equals takes two arguments
2. but its eval needs to be put on hold (i.e., on the eval stack) because
3. each pick takes two arguments, so
4. the second pick gets evaluated first
5. then the first pick gets evaluated second
6. then the = gets evaluated with its fully evaluated two arguments
>> = pick c 4 pick g 3
== true
Notice all comparing words work as expected:
>> equal? pick c 4 pick g 4
== false
>> same? pick c 4 pick g 4
== false
>> same? pick c 4 pick g 3
== true
>> equal? pick c 4 pick g 3
== true
Carl knows how the internals work.
Likely, infix = takes as its args, pick and evaluated g first and does not do the pick on g, i.e,. does not return == #"g"
Why it does not throw an error is likely to preserve the illusion of being infix.
Keep in mind: REBOL returns something always. So in this case, REBOL returns the result of pick c 4, i.e., == #"r"
>> pick c 4 = pick g 4
== #"r"
>> (pick c 4) = (pick g 4)
== false

posted by:   Stone Johnson     20-Sep-2019/13:10:15-7:00

Also see: http://www.rebol.com/faq.html#056
If you study that little FAQ response, you will understand it better.

posted by:   Stone Johnson     20-Sep-2019/13:23:26-7:00



Type the reverse of this captcha text: "t e n - t e s"