Mailing List Archive: 49091 messages
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

[REBOL] Re: using type? with switch

From: joel:neely:fedex at: 1-Oct-2001 18:12

Hi, Gregg, Gregg Irwin wrote:
> Is is possible to use the result of type? with switch? I.e. if > I want to use switch to dispatch based on different data types, > it seems I have to use to-string on the result of type? for use > with switch. Is that the case or am I missing something? >
Consider the fragment below:
>> selblk: [
[ integer! [print "int"] [ string! [print "str"] [ block! [print "blk"] [ ] == [ integer! [print "int"] string! [print "str"] block! [print "blk"] ]
>> foreach item selblk [print type? :item]
word block word block word block This shows that the "case" elements of the block are WORD! values, not DATATYPE! values (because they haven't been evaluated yet). OTOH, we can do this:
>> foreach item reduce selblk [print type? :item]
datatype block datatype block datatype block to get a collection of DATATYPE!/BLOCK! pairs. This means we'd expect to reduce the type/action block to get the desired behavior. For example
>> vi: 12
== 12
>> switch/default type? vi selblk [print "unknown"]
unknown
>> switch/default type? vi reduce selblk [print "unknown"]
int and
>> vs: "Hello, world!"
== "Hello, world!"
>> switch/default type? vs selblk [print "unknown"]
unknown
>> switch/default type? vs reduce selblk [print "unknown"]
str because the datatypes resulting from TYPE? Vx don't match the words in the non-REDUCEd version, but do match the datatypes in the REDUCEd version. Unfortunately, there's still a gotcha!
>> vb: [1 2 3]
== [1 2 3]
>> switch/default type? vb selblk [print "unknown"]
== string!
>> switch/default type? vb reduce selblk [print "unknown"]
== string! Which looks totally mysterious, until we take into account that SELECT apparently has a different behavior if the target is a datatype: it matches the first value of that datatype, rather than matching the datatype value itself!
>> foo: [1 "HI" #"X" 1.2 http://www.rebol.com [x--y--com] "EEK"]
== [1 "HI" #"X" 1.2 http://www.rebol.com [x--y--com] "EEK"]
>> select foo integer!
== "HI"
>> select foo decimal!
== http://www.rebol.com
>> select foo url!
== [x--y--com] (And, remember, SWITCH is built on top of SELECT, as you can see by entering SOURCE SWITCH in the console.) This means that TYPE? VB evaluates to BLOCK! which matches the first "action block" in the target/action pairs (item 2) which returns the next element (item 3) as the result to be DOne by the SWITCH. You can use a couple of alternative work-arounds to this very non-intuitive (and undocumented?) state of affairs: 1) make the selection target a string, as you mentioned (it would be nice if TO-WORD could take a datatype as an argument which would then match in the non-REDUCEd block, instead of blowing up in one's face!) 2) create your own SWITCH variation that avoids the problem by forcing target/action parity:
>> case: func [[throw] val cases [block!] /default def] [
[ either val: select/skip cases val 2 [do first val] [ [ either default [do def] [none]] [ ]
>> case/default type? vi reduce selblk [print "unknown"]
int
>> case/default type? vs reduce selblk [print "unknown"]
str
>> case/default type? vb reduce selblk [print "unknown"]
blk HTH! -jn- -- This sentence contradicts itself -- no actually it doesn't. -- Doug Hofstadter joel<dot>neely<at>fedex<dot>com