[REBOL] Re: More dialects than you think, validating function input.
Tiny correction to my code so as not to confuse. It does not change the result or conclusion. set value any! to end should read set value any-type! to end Brett. -- To unsubscribe from this list, please send an email to [EMAIL PROTECTED] with unsubscribe in the subject, without the quotes.
[REBOL] Re: More dialects than you think, validating function input.
Hi Brett, I don't know, why you didn't write it as follows: f3: func [ [catch] block [block!] ] [ if not parse block [any [number!] end] [ throw make error! F3 can only process numbers. ] ] The parse rule contains END only for compatibility with my proposed PARSE behaviour, otherwise it isn't necessary. Cheers -L - Original Message - From: Brett Handley [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Thursday, September 12, 2002 2:05 PM Subject: [REBOL] More dialects than you think, validating function input. I have a function that takes a block! as an argument. This block! should contain only numbers. The question is how do I check for valid input and throw an error on encountering a problem in an efficient manner? My first thought was something like this: f1: function [ [catch] block [block!] ] [kount] [ kount: 0 repeat value block [ if not number? value [ throw make error! F1 can only process numbers. ] kount: kount + 1 ] ] After reflecting on this, I thought about how a block! passed to a function is one sense is being interpreted by the function according to an implied grammar. That is my requirement in the above function for only numbers, in a sense, implies that my function is processing a fairly simple REBOL based grammar (ie dialect). I don't think it is too outlandish to say every function that processes a block! is implementing grammar processing even if trivial. Hence, the subject title of this message. As a side note, I reckon every offline script can be considered as an out of memory block! ready for loading. Anyway, this thought leads me to PARSE, REBOL's grammar validator. So I recoded my function to look something like this: f2: function [ [catch] block [block!] ] [kount value] [ kount: 0 if not parse block [ any [set value number! (kount: kount + 1)] | set value any! to end ] [throw make error! F2 can only process numbers.] ] Then I did some quick and dirty testing to see which was faster. On my machine, F2 takes half the time that F1 does. Just thought I'd share my little ramble. Test code below. Cheers, Brett. REBOL [] data: copy [] repeat i 2000 [insert tail data i] f1: function [ [catch] block [block!] ] [kount] [ kount: 0 repeat value block [ if not number? value [ throw make error! F1 can only process numbers. ] kount: kount + 1 ] ] f2: function [ [catch] block [block!] ] [kount value] [ kount: 0 if not parse block [ any [set value number! (kount: kount + 1)] | set value any! to end ] [throw make error! F2 can only process numbers.] ] timeit: func [f] [ t1: now/precise repeat i 300 [error? try [f data]] t2: now/precise t2/time - t1/time ] print [f1 timeit :f1] print [f2 timeit :f2] insert at data 1001 'a-word print [f1 - error half way timeit :f1] print [f2 - error half way timeit :f2] --- Website: http://www.codeconscious.com Rebsite: http://www.codeconscious.com/index.r -- To unsubscribe from this list, please send an email to [EMAIL PROTECTED] with unsubscribe in the subject, without the quotes. -- To unsubscribe from this list, please send an email to [EMAIL PROTECTED] with unsubscribe in the subject, without the quotes.
[REBOL] Re: More dialects than you think, validating function input.
Hi Ladislav, I was less than clear. The kount stuff was to simulate other processing. The value needs to be set for processing and to report the type in the error message. My mistake for over simplifying the examples, and for stuffing them up. Here is the actual function I was working on: bayes: function [ {Calculate combined probability.} [catch] probabilities [any-block!] ] [p0 p1 d] [ p0: p1: 1.0 if not parse probabilities [ any [ set value number! (p0: value * p0 p1: 1 - value * p1) | set value any-type! to end skip ] ] [throw make error! reduce ['script 'cannot-use 'bayes mold type? get/any 'value]] if zero? d: add p0 p1 [throw make error! The probabilities cannot be combined.] divide p0 d ] Sorry for the confusion. Brett. Hi Brett, I don't know, why you didn't write it as follows: f3: func [ [catch] block [block!] ] [ if not parse block [any [number!] end] [ throw make error! F3 can only process numbers. ] ] The parse rule contains END only for compatibility with my proposed PARSE behaviour, otherwise it isn't necessary. Cheers -L -- To unsubscribe from this list, please send an email to [EMAIL PROTECTED] with unsubscribe in the subject, without the quotes.
[REBOL] Re: More dialects than you think, validating function input.
Hi Brett, On Thursday, September 12, 2002, 2:05:39 PM, you wrote: BH if not parse block [ BH any [set value number! (kount: kount + 1)] | BH set value any! to end BH ] [throw make error! F2 can only process numbers.] The second part of the rule will never be reached. ANY does not fail if it matches 0 elements. In your trivial example, your code could look like: if not parse block [any number!] [ ... provided you are accepting empty blocks as input too. Of course, I imagine your example was actually cut down form something bigger, that needed the SET VALUE ... and the count (which you could maybe do faster by just using LENGTH?...). Regards, Gabriele. -- Gabriele Santilli [EMAIL PROTECTED] -- REBOL Programmer Amigan -- AGI L'Aquila -- REB: http://web.tiscali.it/rebol/index.r -- To unsubscribe from this list, please send an email to [EMAIL PROTECTED] with unsubscribe in the subject, without the quotes.
[REBOL] Re: More dialects than you think, validating function input.
Brett, et al A very good post, and related to the discussion on error handling to boot! :) I can see at least two major ways to apply this approach. 1) Parse drives the processing of the function, automatically validating the correctness of the argument block as it goes. 2) Parse is used only to validate the block at the entry point, like a precondition in a Design by Contract design, and the operation of the function is separate. You could also use parse to validate return values (i.e. as a post-condition processor). In a large system, and as more things are driven by dialects, this could prove very useful indeed. Now, does anyone have a model they use to return helpful context information when a parse operation fails? Programmers are OK with Syntax error: expected integer! but users are probably better served by I understood the first part (sell 400 shares of MSFT at), but then I was expecting to see a monetary value for the sell price (e.g. $50.00), and I didn't, so I couldn't process your request. I'm sorry for any inconvenience this might cause you. Have a nice day. Or maybe just No sell price was specified in your request. or even a prompt for the missing info. In any case, I agree that this is a good tool to keep in mind. --Gregg -- To unsubscribe from this list, please send an email to [EMAIL PROTECTED] with unsubscribe in the subject, without the quotes.
[REBOL] Re: More dialects than you think, validating function input.
Thanks. -L - Original Message - From: Brett Handley ... Here is the actual function I was working on: bayes: function [ {Calculate combined probability.} [catch] probabilities [any-block!] ] [p0 p1 d] [ p0: p1: 1.0 if not parse probabilities [ any [ set value number! (p0: value * p0 p1: 1 - value * p1) | set value any-type! to end skip ] ] [throw make error! reduce ['script 'cannot-use 'bayes mold type? get/any 'value]] if zero? d: add p0 p1 [throw make error! The probabilities cannot be combined.] divide p0 d ] Sorry for the confusion. Brett. -- To unsubscribe from this list, please send an email to [EMAIL PROTECTED] with unsubscribe in the subject, without the quotes.