I hate computers!
[1/12] from: edanaii::cox::net at: 4-Jan-2003 9:34
No, really! I do.
Well, OK, when they don't do what I want, I hate 'em. :)
This is driving me nuts. I whipped up a small routine to validate
parameters. It is relatively simple, You pass it the parameter, you pass
it a series full of datatypes, it compares the two and tells you if your
parameter's datatype is valid (IOW, in the series).
But it's actin' strangely.
Here it is:
======================================================================
REBOL []
Valid-Type?: Func [ Parameter [Any-Type!]
DataTypes [Series!]
] [
ForEach DataType DataTypes [
If (Type? Parameter) = DataType [
Return True
]
]
Return False
]
======================================================================
The problem is in the line "If (Type? Parameter) = DataType" it just
doesn't work. When I call the routine, it does this:
>> Valid-Type? "x" [ String! Money! Integer! ]
== false
Which is incorrect. It should be "true" since "x" is clearly a string.
The only way it works, is when I change the line in question to "If
(join (to-string Type? Parameter) "!") = (to-string DataType)", which is
a little counter-intuitive.
So, bug or oversight? And is there, as always, a more elegant way of
doing this?
--
Sincerely, | The problems of two little people don't amount to
Ed Dana | a hill of beans in this crazy mixed-up world! But
Software Developer | this is OUR hill, and these are OUR beans!
1Ghz Athlon Amiga | -- Leslie Neilson, Naked Gun (Casablanca).
[2/12] from: joel:neely:fedex at: 4-Jan-2003 11:20
Hi, Ed,
You're 95% there!!! (see below)
Ed Dana wrote:
> ... I whipped up a small routine to validate parameters. It is
> relatively simple, You pass it the parameter, you pass it a series
> full of datatypes, it compares the two and tells you if your
> parameter's datatype is valid (IOW, in the series).
>
> But it's actin' strangely.
>
It's doing just what you designed it to do. (Maybe you want to
design it to do something different... ;-)
> Here it is:
> ...
<<quoted lines omitted: 3>>
> == false
> Which is incorrect. It should be "true" since "x" is clearly a string.
The problem is that your usage above isn't passing a block of types,
but a block of words! (Others have been bitten by this; wrapping a
collection of words in a block keeps them from being evaluated at
unless you expressly ask for DO or REDUCE at some point.)
>> foo: [string! money! integer!]
== [string! money! integer!]
>> foreach item foo [print type? :item]
word
word
word
>> foo: reduce foo
== [string! money! integer!]
>> foreach item foo [print type? :item]
datatype
datatype
datatype
We can fix this either of two ways:
1) either make sure that the calling expression really passes a
block of data types...
>> valid-type? "x" reduce [string! money! integer!]
== true
2) or rewrite your function to perform the reduction for you (
which is safe because reducing a block of data types gives
back a block of data types)...
======================================================================
valid-type?: func [
parameter [any-type!]
datatypes [series!]
][
foreach datatype reduce datatypes [
if datatype = type? parameter [
return true
]
]
return false
]
======================================================================
And now, if you'll pardon the editorializing, a couple of suggestions:
1) Use the standard REBOL conventions for code layout (including
capitalization) to make your code more readable to the widest
audience on the list.
2) Use the fact that parameters values are local to avoid having
to evaluate TYPE? PARAMETER over and over for all values in the
block of types.
3) Use the fact that the value of a function evaluation is the last
expression evaluated in the function (lose the RETURN in the
last line reading RETURN FALSE).
4) Use the fact that the value of a FOREACH is the last expression
evaluated inside the body. Use the fact that the value of an IF
expression is either the value of the controlled expression if
the guard is true or is NONE if the guard is false (and NONE acts
as false for most purposes).
In other words, of none of the tests succeed (causing the RETURN
TRUE to evaluate) then the last IF evaluates to NONE, and so does
the FOREACH, and therefore so does the entire function!
A version utlizing all of these hints appears as:
======================================================================
valid-type?: func [
parameter [any-type!]
datatypes [series!]
][
parameter: type? parameter
foreach datatype reduce datatypes [
if datatype = parameter [
return true
]
]
]
======================================================================
Hope this helps!
-jn-
[3/12] from: joel:neely:fedex at: 4-Jan-2003 11:32
Hi, again, Ed,
Man, is my face red!!!!!
I was so focused on the incremental transformations that I overlooked
the totally obvious solutions:
valid-type?: func [param [any-type!] types [series!]] [
found? find reduce types type? param
]
Sorry for the wasted bandwidth!!! ;-)
-jn-
[4/12] from: dockimbel:free at: 4-Jan-2003 18:54
Hi Joel,
Here's an alternative approach, if you want to avoid the 'reduce call :
valid-type?: func [param [any-type!] types [series!]][
to logic! find types type?/word param
]
-DocKimbel
En réponse à Joel Neely <[joel--neely--fedex--com]>:
[5/12] from: g:santilli:tiscalinet:it at: 4-Jan-2003 19:58
Hi Joel,
On Saturday, January 4, 2003, 6:20:39 PM, you wrote:
JN> ======================================================================
JN> valid-type?: func [
JN> parameter [any-type!]
JN> datatypes [series!]
JN> ][
JN> parameter: type? parameter
JN> foreach datatype reduce datatypes [
JN> if datatype = parameter [
JN> return true
JN> ]
JN> ]
JN> ]
JN> ======================================================================
And of course, one could also write:
valid-type?: func [
parameter [any-type!]
datatypes [block!] ; are you sure to want series! here?
] [
found? find reduce datatypes type? parameter
]
Anyway, this function has the little problem of not working with
pseudo-types. (Just warning you, maybe you don't need to use
them.)
Regards,
Gabriele.
--
Gabriele Santilli <[g--santilli--tiscalinet--it]> -- REBOL Programmer
Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r
[6/12] from: joel:neely:fedex at: 4-Jan-2003 14:07
Hi, Doc,
Tradeoffs about... ;-)
[dockimbel--free--fr] wrote:
> Here's an alternative approach, if you want to avoid the
> 'reduce call :
>
> valid-type?: func [param [any-type!] types [series!]][
> to logic! find types type?/word param
> ]
>
OTOH, staying with the REDUCE allows one to use VALID-TYPE? with
exemplars as well, since the expressions would evaluate to types
in something like
valid-type? foo [type? something type? somethingelse]
Good thing the cat has nine lives, as he can be skinned so many
different ways!
-jn-
[7/12] from: joel:neely:fedex at: 4-Jan-2003 14:23
Hi, Gabriele,
Gabriele Santilli wrote:
> And of course, one could also write:
> valid-type?: func [
<<quoted lines omitted: 3>>
> found? find reduce datatypes type? parameter
> ]
(see my red face... At least I ended up with the same solution as
yours, which makes me cheerful! ;-)
> Anyway, this function has the little problem of not working with
> pseudo-types. (Just warning you, maybe you don't need to use
> them.)
>
That reminds me of a couple of other interesting question whichs I
never put the thought into solving, but which someone on the list
may have already pondered:
1) Since pseudo-types (e.g., SERIES!) are simply identified by
REBOL as data types (not a distinct "pseudo-type" type), what
is the best way to determine whether a value of type DATATYPE!
is a "physical" type or a "pseudo" type?
2) Given two datatypes, is there a simple way to determine whether
one is a super-type of the other?
super-type? number! integer! ==> true
super-type? series! string! ==> true
super-type? number! logic! ==> false
super-type? any-string! file! ==> true
Any suggestions (other than brute-force enumeration, of course)
would be welcomed!
-jn-
[8/12] from: al:bri:xtra at: 5-Jan-2003 10:20
jn wrote:
> 1) Since pseudo-types (e.g., SERIES!) are simply identified by REBOL as
data types (not a distinct "pseudo-type" type), what is the best way to
determine whether a value of type DATATYPE! is a "physical" type or a
pseudo
type?
>> Physical?: func [Datatype [datatype!]] [
[ attempt [make Datatype 0 true]
[ ]
>> Physical? string!
== true
>> Physical? foo!
** Script Error: foo! has no value
** Near: Physical? foo!
>> Physical? series!
== none
>> Physical? number!
== none
>> Physical? function!
== none
Basically trying to 'make the real value. Unfortunately, it doesn't work for
'function!, which requires two block! values and crashes Rebol when using a
0 value instead.
Andrew Martin
ICQ: 26227169 http://valley.150m.com/
[9/12] from: rotenca:telvia:it at: 5-Jan-2003 2:41
Hi Andrew,
> determine whether a value of type DATATYPE! is a "physical" type or a
> "pseudo" type?
<<quoted lines omitted: 4>>
> 'function!, which requires two block! values and crashes Rebol when using a
> 0 value instead.
It does not work also for action!, datatype!, date!, error!, function!,
get-word!, library!, lit-word!, native!, object!, op!, port!, refinement!,
routine!, set-word!, struct!, symbol!, tuple!, unset!, word!
This function
t-d?: func [x][if error? set/any 'x try [make x] [x: disarm x return x/id <>
'cannot-use] true]
fails on:
action! datatype! native! op! unset!
This is a very empirical example which happens that fails only on unset! (but
is unset! a real datatype?):
t-d?: func [x /local y][
if parse/all second system/words [
to x skip to x y: skip to end
][return x = type? first y]
true
]
I think that we need some natives to works on datatype!, for example:
1) pseudo-datatype?
pseudo-datatype? any-string! ;== true
2) in-datatype?
in-datatype? any-string! string! ;== true
3) parent-datatype?
parent-datatype? string! ;== any-string!
parent-datatype? any-string! ;== series!
---
Ciao
Romano
[10/12] from: edanaii:cox at: 5-Jan-2003 9:26
Joel Neely wrote:
>OTOH, staying with the REDUCE allows one to use VALID-TYPE? with
>exemplars as well, since the expressions would evaluate to types
>in something like
>
> valid-type? foo [type? something type? somethingelse]
>
>Good thing the cat has nine lives, as he can be skinned so many
>different ways!
>
But would you want to do this?
The purpose of the function was to allow the use of multiple datatypes
for a parameter and still keep it optional.
As was pointed out to me earlier, the use of Any-Type! seems to make a
parameter optional. Were I to define a parameter as such: Parameter [
String! Money! ], if I omit the parameter when called, it blows up. But
with any-type!, it doesn't. So this was a means to have multiple
parameters and have it optional. This would allow me to do some
overloading, i.e. fall Foo with a String performs a different action
than Foo with Money or Foo without a parameter.
--
Sincerely, | Don't part with your illusions. When they are gone
Ed Dana | you may still exist, but you have ceased to live.
Software Developer | -- Mark Twain
1Ghz Athlon Amiga |
[11/12] from: lmecir:mbox:vol:cz at: 6-Jan-2003 12:21
Hi Ed,
you wrote:
> As was pointed out to me earlier, the use of Any-Type! seems to make a
> parameter optional. Were I to define a parameter as such: Parameter [
<<quoted lines omitted: 3>>
> overloading, i.e. fall Foo with a String performs a different action
> than Foo with Money or Foo without a parameter.
you can use this:
f: func [parameter [string! money! unset!] [
...
]
to have an optional parameter.
Regards
-L
[12/12] from: edanaii:cox at: 6-Jan-2003 8:00
Ladislav Mecir wrote:
>Hi Ed,
>you wrote:
<<quoted lines omitted: 12>>
> ]
>to have an optional parameter.
Ah hah! That's another thing I didn't know I could do.
Never thought of Unset as a datatype.
At this rate, I should get this language figured out in about 50 years. :)
--
Sincerely, | Control is an illusion, you infantile egomaniac!
Ed Dana | Nobody knows what's gonna happen next: not on a
Software Developer | freeway, not in an airplane, not inside our own
1Ghz Athlon Amiga | bodies and certainly not on a racetrack with 40
| other infantile egomaniacs!
| -- Nicole Kidman, Days of Thunder
Notes
- Quoted lines have been omitted from some messages.
View the message alone to see the lines that have been omitted