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

The all function.

 [1/18] from: louisaturk:eudoramail at: 12-Apr-2002 14:43


Rebol friends, I have the following line of code to check to make sure that a record does not already exist, but it always returns none: rec: all [find database code find database chknum]
>> find database code
== make hash! ["boo" make object! [ code: "boo" chknum: "9898" date: 19-Jan-2001 amount: $100....
>> find database 2 chknum
== "9898"
>> rec: all [find database code find database 2 chknum]
== none ; Why is this none???????????????? Futher testing shows where the failure is happening:
>> rec: all [find database code]
== make hash! ["boo" make object! [ code: "boo" chknum: "9898" date: 19-Jan-2001 amount: $100....
>> rec: all [find database 2 chknum]
== none
>> find database 2 chknum
== "9898"
>> all [find database 2 chknum]
== none
>> find database 2 chknum
== "9898"
>>
Why? Louis

 [2/18] from: louisaturk:eudoramail at: 12-Apr-2002 20:56


I found the solution---add the word copy. rec: all [find database code copy (find database chknum)] For some reason I keep having to learn that lesson again and again. :>) Louis At 02:43 PM 4/12/2002 -0500, you wrote:

 [3/18] from: anton:lexicon at: 13-Apr-2002 15:42


No, adding copy didn't fix your code. Removing the 2 did. (Although, I am not really sure it is fixed...) The problem is that find takes two arguments, not three, as you seem to think in this line: find database 2 chknum This just returns the value of chknum. You had obviously set chknum sometime in your testing on the console. I'll put brackets to show how the above line was evaluated: (find database 2) (chknum) The first value returns none, the second value returns 9898 , which must have been what you set it to at some point. In the 'all block, you actually had three values to check, not two, as I am sure you thought you had: rec: all [find database code find database 2 chknum] I will put brackets to show how it was evaluated. rec: all [(find database code) (find database 2) chknum] So 'all would have returned at the second value (none). Perhaps you meant to write: find database/2 chknum That means to look in the second value of the hash! Anton.

 [4/18] from: louisaturk:eudoramail at: 13-Apr-2002 1:54


Anton, Thanks for the help. Further testing proved that you are right about my code being incorrect. However, when I try find database/2 chknum I get the following error message: Code: boo Check#: 9898 ** Script Error: find expected series argument of type: series port bit set ** Where: forever ** Near: rec: all [find database code find database/2 chknum] either rec
>>
Here is the the code from my program: if choice = #"1" [ forever [ print cls print " ADD A RECORD" print " ============^/" code: ask " Code: " chknum: ask " Check#: " if code = "" [break] ;gsj added to avoid empty error rec: all [find database code find database/2 chknum] either rec = none [ date: ask " Date: " amount: ask " Amount: " special: ask " Special Offering: " insert-data code chknum date amount special save-data ][ ask "^/ Record is already in database. Continue? " ] ] ; End forever loop for choice 1 ] ; End if choice 1 Thanks again, Louis At 03:42 PM 4/13/2002 +1000, you wrote:

 [5/18] from: inetw3:mindspring at: 13-Apr-2002 19:18


Hello Dr. Louis, Im still learning how to Rebol my way around, so hopefully someone can correct me if Im wrong but, is code & chknum looking for type? string "9898" "BOO" or type? string and type? number "BOO" 9898 some functions will find string code the first time but afterward you must specify them with {"BOO"} brackets in order not to loose your #" " characters.

 [6/18] from: anton:lexicon at: 14-Apr-2002 14:05


Sorry, my slip up there. You can't use find on an object! You should probably use this: in database/2 'chknum ; to see if there is such a word database/2/chknum ; get the value (not none or false it's ok). so... all [find database code (in database/2 'chknum) database/2/chknum]

 [7/18] from: louisaturk:eudoramail at: 13-Apr-2002 23:45


Hi, At 07:18 PM 4/13/2002 -0500, you wrote:
>Hello Dr. Louis, > >Im still learning how to Rebol my way around, so hopefully someone can >correct me if Im wrong but, > >is code & chknum looking for type? string "9898" "BOO" >or type? string and type? number "BOO" 9898
They are both strings.
>some functions will find string code the first time but afterward >you must specify them with {"BOO"} brackets in order not to >loose your #" " characters.
I don't understand what you mean. Please give an example. Louis

 [8/18] from: louisaturk:eudoramail at: 14-Apr-2002 0:05


Hi Anton, Thanks again. But it is still not working. No matter what record I search for all [find database code (in database/2 'chknum) database/2/chknum] appears to be stopping most of the time at the first record in the database, and returning its chknum. Louis At 02:05 PM 4/14/2002 +1000, you wrote:

 [9/18] from: anton:lexicon at: 14-Apr-2002 17:33


Now I see your intention.. Golly. Of course, database/2 always refers to the second element in your database, which was your first record. Duh. My apologies for misleading you there. Ok, what you need is something simple like this: rec: select database code select finds the code, then returns the next object. Great! Now you can see if rec contains 'chknum and get its value. chknum: all [(in rec 'chknum) rec/chknum] Anton.

 [10/18] from: joel:neely:fedex at: 14-Apr-2002 7:42


Hi, Louis, I've had a hard time understanding the exact setting of the problem... Sorry! Dr. Louis A. Turk wrote:
> all [find database code (in database/2 'chknum) database/2/chknum] > > appears to be stopping most of the time at the first record in the > database, and returning its chknum. >
Let me make a couple of assumptions: 1) DATABASE is a series containing alternating strings (used as keys) and objects (the corresponding values). 2) Each object has a CHKNUM attribute. 3) Given a key (string) you want the corresponding CHKNUM value. I can build a trivial test case for requirements (1) and (2) by database: [] repeat i 10 [ append database join "X" i append database make object! [ chknum: i stuff: random 1000000 ] ] == ["X1" make object! [ chknum: 1 stuff: 170632 ] "X2" make object! [ chknum: 2 stuff... Under those assumptions... rec: all [obref: select database code obref/chknum] will give you back the CHKNUM field of the object associated with CODE, or NONE if there is no such key.
>> rec: all [obref: select database "X7" obref/chknum]
== 7
>> rec: all [obref: select database "XYZ" obref/chknum]
== none
>> rec: all [obref: select database "X3" obref/chknum]
== 3 If the phrase obref: select database code finds the desired key, then OBREF will refer to the corresponding object and obref/chknum will obtain the desired attribute. OTOH, if the key does not exist in the series, then OBREF will be NONE and the ALL will terminate with that value. Hope I haven't missed the point! -jn- -- ; Joel Neely joeldotneelyatfedexdotcom REBOL [] do [ do func [s] [ foreach [a b] s [prin b] ] sort/skip do function [s] [t] [ t: "" foreach [a b] s [repend t [b a]] t ] { | e s m!zauafBpcvekexEohthjJakwLrngohOqrlryRnsctdtiub} 2 ]

 [11/18] from: louisaturk::eudoramail::com at: 14-Apr-2002 21:00


Anton and Joel, How thankful I am for you and the others on this list. You all have saved me so much time. And, frankly, I probably wouldn't be able to get past problems like this without you. From studying what both of you have said, I think that the root problem may be that I have a basic design flaw in my database. This is (I think) what has confused me, and also is perhaps what has made it difficult for you to understand my problem. I think I only have one key but need two keys. (Or maybe I don't need any keys at all! Is only one key per record allowed?) Here are the first few records from the database:
>> probe database
make hash! ["bbi" make object! [ code: "bbi" chknum: "298" date: 26-Jan-2001 amount: $40.00 special: $0.00 ] "bbi" make object! [ code: "bbi" chknum: "315" date: 9-Feb-2001 amount: $40.00 special: $0.00 ] "boo" make object! [ code: "boo" chknum: "9898" date: 19-Jan-2001 amount: $100.00 special: $0.00 ] "boo" make object! [ code: "boo" chknum: "" date: 20-Apr-2001 amount: $100.00 special: $0.00 ] "bho" make object! [ code: "bho" chknum: "5259" date: 27-Jul-2001 amount: $100.00 special: $0.00 What I am wanting to do is to make sure that the record is not already in the database before I insert it. In other words, no duplicate _records_ are allowed. Note, however, that although the records are all unique, the code data is not necessarily unique, nor is the chknum data. There may be many records with the same code, and also many records with the same chknum. Only the code / chknum combination is unique. So, do I perhaps need the records to look like this?: ] "bho" "5259" ; <===<<< TWO KEYS. make object! [ code: "bho" chknum: "5259" date: 27-Jul-2001 amount: $100.00 special: $0.00 Would not this line then return none if the unique record does not exist, and return the chknum otherswise?: all [find database code find database chknum] Am I correct about all this? If so, won't the following functions have to be rewritten?: load-data: has [data] [ if exists? db-file [ data: reduce load/all db-file clear database if data [ foreach item data [ item: make record item repend database [item/code item] ;item/key_field item ] ] database: make hash! database ] ] update-key-data: func [code-old code-new /local record] [ record: find database code-old if none? record [alert reform ["Missing record:" code-old] exit] insert clear first record code-new ] save-data: has [data] [ data: copy [] foreach [key obj] database [ append/only data obj 5 ; number of fields in each record ] save db-file data ] find-data: func [code] [select database code] remove-data: func [code] [remove/part find database code 2] insert-data: func [code' chknum' date' amount' special'] [ repend database [ code' make record [ code: code' chknum: chknum' date: date' amount: amount' special: special' ] ] ] These are the functions that Carl wrote for me several years ago for a database that only had one key. Thanks again Carl! They have served me well in several databases. This is my first need for two keys. Thanks again for your help. Louis

 [12/18] from: anton:lexicon at: 15-Apr-2002 14:53


First of all, I have never bothered to use hash before, so perhaps I will miss some hash specific details. As far as I know, hash!s are very similar to blocks. That means you can put in any number of any datatype. There is, due to the key, duplication of data in the database. The code appears before each object and within each object. I would try to eliminate one of them. I would simplify your hash to a series of objects only (with the keys in the objects.) However, that may well not be very speedy. So you may decide to have two keys then an object, or store all your keys and data in the objects. You will need to modify your functions either way. With your two key example, this line will not work: all [find database code find database chknum] It would find code somewhere, then chknum somewhere else, but who says they are together? Nobody. ;) Use this instead: find/skip database reduce [key1 key2] 3 The skip refinement treats the series as records of fixed number of objects, which is 3 in this case (2 keys and 1 object). Anton.

 [13/18] from: ingo:2b1 at: 15-Apr-2002 10:40


Hi Louis, Dr. Louis A. Turk wrote: <...>
> What I am wanting to do is to make sure that the record is not already > in the database before I insert it. In other words, no duplicate
<<quoted lines omitted: 11>>
> amount: $100.00 > special: $0.00
well, I think this would get you into much trouble, but how about using a single key, that joins the two values?, e.g.
>> key: join join code "-" chknum
== "bho-5259" and then use ] "bho-5259" ; <===<<< ONE KEY, composed of TWO KEYS. make object! [ code: "bho" chknum: "5259" date: 27-Jul-2001 amount: $100.00 special: $0.00 I hope that helps, Ingo

 [14/18] from: louisaturk:eudoramail at: 15-Apr-2002 7:13


Ingo, This was a great idea, and it seems to have solved my problem! I changed the load-data function as follows: load-data: has [data] [ if exists? db-file [ data: reduce load/all db-file clear database if data [ foreach item data [ item: make record item repend database [join item/code item/chknum item] ; <==<<< ONLY THIS LINE CHANGED. ] ] database: make hash! database ] ] Then, search for the unique record as follows: rec: find database join code chknum I tested it on several records, and it seems to work perfectly. Many thanks! Louis At 10:40 AM 4/15/2002 +0200, you wrote:

 [15/18] from: louisaturk:eudoramail at: 15-Apr-2002 7:02


Anton, Thanks. Little by little you are helping me understand how things work. Thanks for your time. Louis At 02:53 PM 4/15/2002 +1000, you wrote:

 [16/18] from: joel:neely:fedex at: 15-Apr-2002 6:50


Hi, Louis, Dr. Louis A. Turk wrote:
> From studying what both of you have said, I think that the root > problem may be that I have a basic design flaw in my database.
<<quoted lines omitted: 3>>
> any keys at all! Is only one key per record > allowed?)
...
> ... Note, however, that although the records are all unique, > the code data is not necessarily unique, nor is the chknum data. > There may be many records with the same code, and also many > records with the same chknum. Only the code / chknum combination > is unique. >
Then my suggestion is to use a combination of those two attributes as the key.
> So, do I perhaps need the records to look like this?: > ] "bho" "5259" ; <===<<< TWO KEYS.
<<quoted lines omitted: 4>>
> amount: $100.00 > special: $0.00
How about ... "bho:5259" ; <===<<< COMBINED key make object! [ code: "bho" chknum: "5259" ... ] ...
> all [find database code find database chknum] >
That wouldn't work (with the "two key" version you conjectured) because it fails (yields NONE) if neither value is present *anywhere* in DATABASE and succeeds (yields a subseries of DATABASE) if both values occur *somewhere* in DATABASE, but the two occurrences could be uncorrelated...
>> database: [
[ "A" "1" #dummy [ "B" "2" #dummy [ "C" "3" #dummy [ ] == [ "A" "1" #dummy "B" "2" #dummy "C" "3" #dummy ]
>> all [find database "A" find database "3"]
== ["3" #dummy ] ...whereas you apparently want to know only if the *combination* of the two values is present. If the two values may occur (with other neighbors) multiple times, then you'd need a more complex expression (i.e. one involving an explicit loop AFAICT) to keep re-trying until all occurrences of one value have been checked to see whether one of them is paired with the other value. This way lies madness. (e.g. what happens when you need to check a combination of 3 key fields...?)
> Am I correct about all this? If so, won't the following functions > have to be rewritten?:
<<quoted lines omitted: 11>>
> ] > ]
Just modify the above to contain the following instead: foreach item data [ item: make record item repend database [ rejoin [item/code ":" item/chknum] item ] ;item/key_field item ] and make the corresponding changes to the other functions. HTH! -jn- -- ; Joel Neely joeldotneelyatfedexdotcom REBOL [] do [ do func [s] [ foreach [a b] s [prin b] ] sort/skip do function [s] [t] [ t: "" foreach [a b] s [repend t [b a]] t ] { | e s m!zauafBpcvekexEohthjJakwLrngohOqrlryRnsctdtiub} 2 ]

 [17/18] from: joel:neely:fedex at: 15-Apr-2002 8:17


Hi, Anton and Louis, Thanks, Anton, for bypassing my goof! Anton wrote:
> Use this instead: > > find/skip database reduce [key1 key2] 3 > > The skip refinement treats the series as records > of fixed number of objects, which is 3 in this case > (2 keys and 1 object). >
Doh! You're right, of course! I spoke too hastily when I said there would be a need for a loop. If I had thought more carefully, I would have realized that my bias toward *ALWAYS* having a unique key was influencing my thinking. After further thought, I'd ask another design question: Are the values of CODE and CHKNUM guaranteed to be immutable over the life of an object? If so, then the "concatenated key" approach has a slight edge in performance, I believe. If not, then the work required to keep the key (or keys, for the FIND/SKIP version) up to date. -jn- -- ; Joel Neely joeldotneelyatfedexdotcom REBOL [] do [ do func [s] [ foreach [a b] s [prin b] ] sort/skip do function [s] [t] [ t: "" foreach [a b] s [repend t [b a]] t ] { | e s m!zauafBpcvekexEohthjJakwLrngohOqrlryRnsctdtiub} 2 ]

 [18/18] from: louisaturk:eudoramail at: 15-Apr-2002 14:21


Joel, It was your first post that made me realize that my problem was that I had misunderstood how the key was used. I had just copied Carl's load-data function without noticing that the key was not part of the object. Everyone that contributed to this thread helped me understand what was happening. Your sharing of expertize is always highly appreciated. Louis At 08:17 AM 4/15/2002 -0500, you wrote:

Notes
  • Quoted lines have been omitted from some messages.
    View the message alone to see the lines that have been omitted