3

I'm trying to set a condition for evaluating the values of several text-lists. This works, using a SWITCH:

options: ["" "" "" ""]

view layout [
    text-list "one" "two" "three" "four" [poke options 1 value]
    button "test" [switch/default options/1 [
        "one" [alert "first"]
        "two" [alert "second"]
        "three" [alert "third"]
        "four" [alert "fourth"]
        ] [alert "pick a number!"]
    ]
]

But this one doesn't work for some reason:

options: ["" "" "" ""]

view layout [
    text-list "one" "two" "three" "four" [poke options 1 value]
    button "test" [
        either options/1 <> 0 [
          alert "you have picked a number!"
        ][alert "pick a number!"]
    ]
]

The EITHER evaluation always executes the first block if I put options/1 <> 0 as the condition, and always executes the second block if I put options/1 = 0 as the condition, which is obviously not how it should work at all.

What's the matter here?

fadelm0
  • 263
  • 2
  • 9

2 Answers2

3

You are using an empty string to indicate a "nothing" state. As @iceflow19 points out, strings and integers will never compare equal. If you want to know if a string is empty, use EMPTY? or compare literally against "" or {}.

(Note: I usually prefer braced strings myself, and {It's cool that they {nest better} and can do "quotes" and apostrophe's [sic] without escaping.})

Rebol has another possibility for representing nothingness, and that's a value whose type is NONE!. A nice property that a NONE! value has is that it will behave like a LOGIC! false value does as far as IF, UNLESS, and EITHER are concerned.

value: none

if value [print {this won't run}]

unless value [print {this will run}]

Some routines use a NONE! value as their return to indicate a normal "failure" condition. IF and UNLESS are such routines:

>> print if 1 < 2 [{math is working}]
math is working

>> print if 1 > 2 [{math is broken}]
none ;-- Rebol2 prints out the string representation of NONE!

(Note: Rebol3 does not require you to put conditions to IF, UNLESS, or EITHER into a block if they are single values.)

So you could have written:

options: reduce [none none none none]

view layout [
    text-list {one} {two} {three} {four} [poke options 1 value]
    button {test} [
        alert either options/1 [
            {you have picked a number!}
        ][{pick a number!}]
    ]
]

The REDUCE is needed because blocks are not evaluated by default...and you would have the word none four times (vs. a value of type NONE!, to which NONE is bound).

Note also that you can pass the result of a SWITCH or EITHER to alert, and it will be the last evaluation value of the branch that runs. Or none if no branch runs--as shown above.

(Note: Constructs you might be wanting soon--if you haven't discovered already--are CASE and ALL.)

Community
  • 1
  • 1
2

It works fine, the condition itself is the issue. The word 'value is going to refer to a string value. ( "one", "two", "three", or "four" )

When "one" is selected, it will insert the string "one" into the options block in position 1.

>> probe options
== ["one" "" "" ""]

>> probe options/1
== "one"

Your inequality is comparing a value of type string! to the value 0 of type integer! A string will never equal a integer and as such the condition will always evaluate to true. Therefore the first code path on 'either will always be ran.

When you use switch your comparing options/1 (a string!) to the strings "one", "two", "three", and "four". If options/1 = "two" for example, the first case will fail because "two" <> "one", but the second case will succeed because "two" = "two" (both in value and type).

iceflow19
  • 752
  • 4
  • 12