1. will map:put() never fail?
- Posted by euphoric (admin) Sep 09, 2011
- 1116 views
Shouldn't map:put() be a function in case it needs to report an error? I don't see anything like "map:get_error()" either...
Or maybe map:put() will never fail?
2. Re: will map:put() never fail?
- Posted by mattlewis (admin) Sep 09, 2011
- 1089 views
Shouldn't map:put() be a function in case it needs to report an error? I don't see anything like "map:get_error()" either...
Or maybe map:put() will never fail?
The only failure mode I could think of would be if you passed an invalid map, which would result in a crash. What sort of error are you expecting?
Matt
3. Re: will map:put() never fail?
- Posted by euphoric (admin) Sep 09, 2011
- 1093 views
Shouldn't map:put() be a function in case it needs to report an error? I don't see anything like "map:get_error()" either...
Or maybe map:put() will never fail?
The only failure mode I could think of would be if you passed an invalid map, which would result in a crash. What sort of error are you expecting?
No expectations, just ignorance. If, for some reason, map:put() cannot complete the put(), I would like to know about it. But, if map:put() will never fail, then no biggie.
A SUCCESS or FAIL result would be enough (for now).
4. Re: will map:put() never fail?
- Posted by DerekParnell (admin) Sep 09, 2011
- 1027 views
Shouldn't map:put() be a function in case it needs to report an error? I don't see anything like "map:get_error()" either...
Or maybe map:put() will never fail?
It can fail, but if it does it causes a program fail too. It can fail for these reasons ...
- The MAP ID is wrong. Either an invalid value or it refers to an object which isn't a map.
- The OPERATION argument is not a valid value.
- The OPERATION argument is invalid for the case when the KEY does not exist in the map.
- The computer's RAM has been exhausted.
I think that the idea was that if one of these situations arose, then the application is already compromised and cannot continue anyhow.
5. Re: will map:put() never fail?
- Posted by euphoric (admin) Sep 09, 2011
- 1062 views
Shouldn't map:put() be a function in case it needs to report an error? I don't see anything like "map:get_error()" either...
Or maybe map:put() will never fail?
It can fail, but if it does it causes a program fail too. It can fail for these reasons ...
- The MAP ID is wrong. Either an invalid value or it refers to an object which isn't a map.
- The OPERATION argument is not a valid value.
- The OPERATION argument is invalid for the case when the KEY does not exist in the map.
- The computer's RAM has been exhausted.
I think that the idea was that if one of these situations arose, then the application is already compromised and cannot continue anyhow.
- We should return BAD_MAP_ID (-1)
- We should return BAD_OPERATION_VALUE (-2)
- We should return KEY_DOES_NOT_EXIST (-3)
- We should return OUT_OF_MEMORY (-4), if possible
Otherwise, we return 1 (SUCCESS!).
It could STILL be used as a procedure, because 4.x does not require you to use the return value. So it won't break code if we turn this into a function.
OR, we could put it on the user to test for all those things first, which is not very nice. :)
6. Re: will map:put() never fail?
- Posted by jeremy (admin) Sep 10, 2011
- 1098 views
I prefer the method it currently uses. For example:
map m = map:new() sequence name = "John" map:put(name, "age", 22)
is an exceptional problem. It is a programming error and one cannot recover from it by checking the return result. The proper thing to do is an application crash. If it fails because of memory, your app is going to fail regardless. If it fails because you pass a bad operation:
map:put(name, "age", 22, 192839283)
then it's a programming error and it cannot be recovered from by checking an error return value. It's better to fail early than late. Failing late only obscures the real problem. It's also better to check ALL function returns. By turning an exceptional error into a passable situation, you introduce errors into everyones code. If the routine is going to pass 99.9% of the time, who is going to check the return result with every call to that routine? No one. That would lead to horrid code as well:
if map:put(name, "age", 22) != map:SUCCESS then error() end if if map:put(name, "city", "Smalltown") != map:SUCCESS then error() end if if map:put(...) then .... end if
Now, number 3 in Dereks list is pretty debatable.
3. The OPERATION argument is invalid for the case when the KEY does not exist in the map.
For that, an error code result actually makes sense, but one can handle this a bit differently and save the terrible coding techique given above. They can do it by:
if not map:has(my_map, "name") then map:put(my_map, "age", 100) else map:put(my_map, "age", 4, map:DIVIDE) end if
Thus, you have provided a solution for the potential failure of map:put() w/o having to fall back on checking the errror result. Now, the code may be slightly better if map:put returned an error code in this condition, ONLY IF the majority of the iterations you are doing a divide operation:
if map:put(my_map, "age", 4, map:DIVIDE) != map:SUCCESS then map:put(my_map, "age", 100) end if
but that is only a good case if you know the majority of the time age already exists. Not sure that warrants an error return value when a valid method exists for avoiding it.
Jeremy
7. Re: will map:put() never fail?
- Posted by DerekParnell (admin) Sep 10, 2011
- 1080 views
OR, we could put it on the user to test for all those things first, which is not very nice. :)
This is a question that has been argued and discussed since the dawn of programming. It boils down to where do we want to make the trade-off point. The trade-off is between application reliability and application performance. The more that low-level routines examine input arguments for validity the slower an application runs.
Another consideration is that the fact that a routine returns a success/failure code does not necessarily increase application reliability, unless the application chooses to test the routine's result. So it is quite possible to have a routine expend time testing argument correctness only to have the calling process either not test the result or get that testing wrong anyhow.
In this case, nearly all calls to the put() routine will be passed correct arguments and thus having the routine itself examine them for correctness is mostly going to be a waste of time. If your application requires greater reliability than this assumption, then maybe your application should take on the responsibility of argument validation.
A further complication in this particular case is that the some of the current error conditions are tested for free. The testing for a bad OPERATION argument adds no real performance hit, and and out-of-RAM error will crash your application even if put() explicitly tested for that anyway. The only one that could add some performance penalty is having put() test for a valid MAP ID, but you can simply test for this before invoking significant put() calls ...
if map(someid) then put(someid, ... ) end if
8. Re: will map:put() never fail?
- Posted by DerekParnell (admin) Sep 10, 2011
- 1100 views
Shouldn't map:put() be a function in case it needs to report an error?
I just had another thought ... very soon I expect that we will add exceptions to Euphoria and that means then that applications can trap certain or all exceptions and handle them in specific ways.
9. Re: will map:put() never fail?
- Posted by bill Sep 10, 2011
- 1063 views
Some doubts about map.e
This is from load_map in in std:map.e, lines 1531-1670. This code is intended to load key, value pairs from a text file into a hash-map.
The structure of a key value pair is:
key = value <nl>
Line continuation characters are `,`, `$` and `{`. `",$\n"` concatenates strings, `,$` joins lines removing the `,$` Comments are allowed anywhere.
1 while sequence(logical_line) with entry do 2 delim_pos = find('=', logical_line) 3 if delim_pos > 0 then 4 data_key = text:trim(logical_line[1..delim_pos-1]) 5 if length(data_key) > 0 then = 6 data_key = search:match_replace("\\-", data_key, "-") 7 if not t_alpha(data_key[1]) then 8 conv_res = stdget:value(data_key,,stdget:GET_LONG_ANSWER) 9 if conv_res[1] = stdget:GET_SUCCESS then 10 if conv_res[3] = length(data_key) then 11 data_key = conv_res[2] 12 end if 13 end if 14 end if 15 data_value = text:trim(logical_line[delim_pos+1..$]) 16 data_value = search:match_replace("\\-", data_value, "-") 17 conv_res = stdget:value(data_value,,stdget:GET_LONG_ANSWER) 18 if conv_res[1] = stdget:GET_SUCCESS then 19 if conv_res[3] = length(data_value) then 20 data_value = conv_res[2] 21 end if 22 end if 23 put(new_map, data_key, data_value) 24 end if 25 end if 26 entry 27 logical_line = -1 28 while sequence(line_in) with entry do 29 if atom(logical_line) then 30 logical_line = "" 31 end if 32 has_comment = search:rmatch("--", line_in) 33 if has_comment != 0 then 34 line_in = text:trim(line_in[1..has_comment-1]) 35 else 36 line_in = text:trim(line_in) 37 end if 38 logical_line &= line_in 39 if length(line_in) then 40 if not find(line_in[$], line_conts) then 41 logical_line = search:match_replace(`",$"`, logical_line, "") 42 logical_line = search:match_replace(`,$`, logical_line, "") 43 exit 44 end if 45 end if 46 entry 47 line_in = gets(file_handle) 48 end while 49 end while
Take the section from line 26 to the end.
What is intended is *something like:
---------------------------- read a line in remove comments and trim redo if the line is blank while the line has a continuation read a line in remove comments and trim append end while remove characters as needed return to the main loop
Errors:
1 Line 32 assumes -- cannot appear in a comment, or a quoted string
2 Line 2 assumes = will not appear in a quoted string
3 Lines 41,42 remove ",$" ,$ globally in the line
4 Blank lines are completely ignored - so blank lines after a continuation will be ignored and the next non-blank line appended.
5 The inner loop is not entered at end of file. If a line was incomplete at EOF then it would not be properly processed.
6 Lines 3 and 5 ignore lines without a key.
7 Sequence constructors are allowed in the line but no attempt is made to check their validity.
8 All lines are valid as they are read in as text.
10. Re: will map:put() never fail?
- Posted by DerekParnell (admin) Sep 10, 2011
- 1063 views
Some doubts about map.e
Good call. I'll repair these (and others) and introduce much more vigorous unit tests.