have a look at this code snippet
METHOD PUBLIC CHAR EXTENT GetInboundFiles():
DEF VAR lv_Files AS CHAR EXTENT NO-UNDO.
IF EXTENT(lv_files) EQ ? THEN RETURN ERROR "No files found".
RETURN lv_Files.
END METHOD.
Why won't this compile ? Is it a bug in the ABL ? How can I return an error if I have a indeterminate array as the return value ? This is the error message:
RETURN statement expression must have the same extent as method or function return definition unless one of them is indeterminate. (14913)
It is better to have an array as an output parameter than a return value. But if it is necessary to have it as a return value, then either it has to be indeterminate or match the extent in the method or function definition, unless that is indeterminate.
1) Why is it "better" to have an array as an output parameter ?
2) I am not returning the array, I'm returing an ERROR
Try
UNDO, THROW NEW Progress.Lang.AppError ("File not found") .
Should have the same effect. RETURN ERROR is very retro
I agree its confusing and could be considered a bug but not anything that could be changed at this point in the life of ABL RETURN ERROR. As Mike said this is something we fixed with structured error handling and it is best to use that. since there is full mapping between classic and structured error handling Mike's suggestion is the best way to go.
-Shelley.
* jmls dons his 70's shades ...
The irony of this was that I am in the middle of implementing structured error handling . lol.
Thanks Mike
You must be doing a lot of interesting work lately, Julian, since you seem to keep coming up with interesting questions.
Shelley, is the issue here the fact that the return value of the method has been defined as an indeterminate extent, but the extent is never determined? Would this work if the extent of the return value were determined?
I think Mike is right, that the structured error handling is to be preferred regardless and it may get away from this issue as well, but I'm wondering if it is that combination which is the issue.
There is a part of me which would rather return an object with an indefinite number of contents instead of an indeterminate extent.
Thanks Shelly,
Will be doing that.
"interesting" is a word that could be used. There are a lot of other, more anglo-saxon terms I am using at the moment
The irony of this was that I am in the middle of implementing structured error handling . lol.
Don't forget to add ON ERROR UNDO, THROW to all FOR and REPEAT LOOPs
I've met a number of developers, that were thinking that ROUTINE-LEVEL ON ERROR, UNDO THROW is enough (including me when I started using structured EH)
In answer to your question, even if the array is determined ( extent(foo) = 10 ) then you still can't RETURN ERROR.
however, RETURN ERROR is so retro these days ...
got bit in the ass by that on Friday. The realisation of this made a
whole load of things suddenly make sense !
We need a
LOOP-LEVEL ON ERROR, UNDO THROW
or a startup option to implement this. Really am not looking forward
going through all the code to add this in
Julian
On 13 February 2011 20:34, Mike Fechner
however, RETURN ERROR is so retro these days ...
Like
LOOP-LEVEL ON ERROR, UNDO THROW
Something like that also came into my mind. Where's the ERS, when you need one?
Tedious, perhaps ... another argument in favor of code generation!
But, I wonder if it wouldn't be a bit dangerous to make it sweeping without considering case by case. ROUTINE-LEVEL I can see since one of the first things one ought to do in implementing SEH is to put in a top level handler for everything that doesn't get handled below. LOOP-LEVEL I'm not so sure about.
But, whatever, I'm not sure that the difference between an available ERS and a not available ERS will be noticeable in terms of what gets in the product (who me, cynical?)
No - it has to do that RETURN ERROR only works with a string but when it is used in a function with a return type that is not CHAR then you can't RETURN ERROR string anymore - the compiler complains. So RETURN ERROR cannot return a CHAR EXTENT but you also can't return a CHAR now, you can only do RETURN ERROR with nothing after it. Seemed like a bug to me and we tried "fixing"it when we released SEH but the change in behavior broke some customer applications so we backed it out.
-Shelley
"Hursh" is a Saxon word ...
mikefe schrieb:
The irony of this was that I am in the middle of implementing structured error handling . lol.
Don't forget to add ON ERROR UNDO, THROW to all FOR and REPEAT LOOPs
I've met a number of developers, that were thinking that ROUTINE-LEVEL ON ERROR, UNDO THROW is enough (including me when I started using structured EH)
Mike,
so many programmers couldn't be wrong
Still searching for a ABL debugger that stops at every(!) error at once ....
Stefan
>> I've met a number of developers, that were thinking that ROUTINE-LEVEL ON ERROR, UNDO THROW is enough (including me when I started using structured EH)
Mike,
so many programmers couldn't be wrong
Herr Marquard, I'm pretty sure, that Shelley understood Julians and my point that this leads to a lot of misunderstandings in a critical area of every application.
But for the time being (10.2B03) that's the status quo. And so every ABL developer missing the proper ON ERROR phrase on a loop is making improper use of structured error handling - and I would call that in most cases a bug in the ABL developers code.
I'm not saying that I'm glad about this.
It's a bit like the fact that NO-UNDO cannot be set as the default for variable declarations. You gotta get used to it - and continue requesting a change in the language.
There have been discussions within Development concerning the need for a block level error construct in addition to ROUTINE-LEVEL. We have discussed the following proposal - this is NOT slated to be in version 11.0.
Would this address your concerns?
Hi Evan,
thanks for taking that into consideration - even when it's not (yet) commited for 11.0 :-)
I'm pretty sure that that would be a great enhancement! I would have called the statement BLOCK-LEVEL or something like that. Sounds more in sync with the ROUTINE-LEVEL; but that's just the name.
However I would add big, big warning signs to use -undothrow when compiling legacy code.
In this context, we recently reworked our code/xref parser for documentation and QA purposes. The only way to detect currently the presence of the ROUTINE-LEVEL statement seems to be to parse source code. An XREF entry would be nice. Especially when this now could be influenced by a compile time startup parameter as well.
What does it take to increase priority of this enhancement?
Mike
What does it take to increase priority of this enhancement?
Use the ERS?
(or is that not even close to being funny?)
-- peter
(or is that not even close to being funny?)
Not if the "One Progress" is meant to speak with "One Voice" then it's also "your" issue.
I can hear the sounds of 100,000 developers gnashing their teeth right now ...;)
in a word, yes !
Sounds very good. However, I would also call it BLOCK-LEVEL to match
ROUTINE-LEVEL
The startup parameter sounds like a really good idea as well.
Thanks!
On 14 February 2011 14:04, Evan Bleicher
100,000 developers
A dream come true?
Hi Mike:
Thanks for the comments. I will add them to our discussion on this potential feature.
As to how to escalate the priority of the request, speak with your Account Manager and through them, Product Management.
bleicher schrieb:
As to how to escalate the priority of the request, speak with your Account Manager and through them, Product Management.
Evan, do you have any reference number, a bug number, enhancement request number etc. that I could use to simplify the disucssion?
I'd also spread this among my customers as well.
I understand why you went for ALL-BLOCKS instead of BLOCK-LEVEL, since ALL-BLOCKS includes ROUTINE-LEVEL, but I wonder if this is really going to convey routine as block to the average programmer. Possibly ALL-LEVEL? Or does that suggest something that is not included?
If the parameter is compile-time only, wouldn't it be sensible to make it an OEA switch. Under the covers, perhaps this adds the parameter since I suppose one still wants the parameter for compile on the fly, but it seems more direct.
In 25 years, I can think of only one limited example in which telling my Account Manager something like this resulted in any feedback whatsoever. Maybe he passed it on; maybe he didn't, but there was no way I could ever tell.
If the parameter is compile-time only, wouldn't it be sensible to make it an
OEA switch. Under the covers, perhaps this adds the parameter since I
suppose one still wants the parameter for compile on the fly, but it seems
more direct.
Does anyone see a need for being able to toggle this behavior at runtime (ie operates on r-code)?
Also, how would do you want to deal with applications that are sourced from various vendors, with differing error handling schemes and implementations? (so vendor A's code uses RETURN ERROR and vendor B's uses 'the old ABL default behaviour' and yours uses SEH, and you only have control over 1 set of source code).
-- peter
I understand why you went for ALL-BLOCKS instead of BLOCK-LEVEL, since ALL-BLOCKS includes ROUTINE-LEVEL, but I wonder if this is really going to convey routine as block to the average programmer. Possibly ALL-LEVEL? Or does that suggest something that is not included?
I'm sure the avarage programmer didn't refer to .p files, internal procedures, functions, methods, propers seters, getters etc. as routine-level blocks before reading the docs on the structured error handling.
But since it's documented as routine-level blocks, BLOCK-LEVEL includes routine blocks, DO blocks and loops of every kind.
I guess I wasn't clear. I think a lot of programmers are a bit fuzzy on blocks. There are some blocks they are probably well aware of, like REPEAT, but they are often fuzzy about the differences for DO and very fuzzy about some of the others you mention. In particular, I think that a large number are fuzzy about thinking about the whole .p as a block. So, ROUTINE-LEVEL is pretty intuitive since it talks about the routine, not blocks at all. ALL-BLOCKs should be clear, but the fuzziness of seeing the .p as a block might get in the way of it being intuitive. I also think that it won't be entirely intuitive for some of the internal blocks, exactly because of the fuzziness they have about blocks. Thus, I am thinking one wants something that more clearly conveys EVERYWHERE-IT-IS-POSSIBLE. To be sure, there is still going to be confusion from people wondering about behavior because they aren't thinking about something being a block, but I would guess that was generally benign since that also means they won't be using any SEH statements in those places.
There are always programmers that care and those that don't care. The one thing they have in common is a daily fight with remembering too many (new) keywords - and startup parameters.
In the end we're just looking for a name for a potentially another new keyword. But it should at least be easy to remember.
I logged an internal enhancement request to track this discussion - CR OE00204761.
- Evan
straying a little off-topic , but can anyone explain why it is
ERROR-STATUS:RETURN-VALUE and ERROR-STATUS:GET-MESSAGE(1)
but
Progress.Lang.AppError:ReturnValue and Progress.Lang.AppError:GetMessage(1)
?
Curious minds want to know. Can't count the number of times I've added the "-" when using AppError.
Oh, and why can't Progress.Lang.AppError:ReturnValue return Progress.Lang.AppError:GetMessage(1) if Progress.Lang.AppError:Return-value (See! I did it again! grr) is not set ?
Now, if only we could vote for it on the ERS!
Progress.Lang.AppError:ReturnValue and Progress.Lang.AppError:GetMessage(1)
Probably because someone with an OO background from a language that bans dashes in keyword has written the spec?
Or dashes in keywords or so retro... uups.
Curious minds want to know. Can't count the number of times I've added the "-" when using AppError.
Do you prefer the dashed approach? Do you use it yourself in your naming conventions? Do you think it more readable?
Just quite curious,
-- peter
Next, you will be wanting to move away from upper case keywords ...
No, thank you from moving away from dashes. If anything, I would make the dashes optional in historical keywords.
Do you prefer the dashed approach? Do you use it yourself in your naming conventions? Do you think it more readable?
No. No. No.
Next, you will be wanting to move away from upper case keywords ...
You know Peter... Let's hope he won't find a manager that agree's to have the docs rewritten.
No, thank you from moving away from dashes. If anything, I would make the dashes optional in historical keywords.
I wouldn't say PSC is moving away from dashes. It's just the methods of the built in objects methods.
Think of Evans suggestion for the
ALL-BLOCKS ON ERROR, UNDO THROW.
That would be a new keyword using dashes.
But, the language has gotten very complex over the last three decades. Better to keep the dashes (also on new keywords) until we get better syntax completion in OEA, so that the tool does almost all coding for you.
I logged an internal enhancement request to track this discussion - CR OE00204761.
Thanks!
Myself, I outgrew COBOL in the early 70s ...
yeah, baby ..
Heh, I was a FORTRAN man myself
Next you will be disagreeing with whitespace ...
So, one doesn't win every time ... but one can hope that by the time they actually implement the feature, they come up with a better word and skip the dashes.
I don't see any reason to propagate the errors of the past any more than one has to in order to provide upward compatability. Certainly, using dashes in field and table names is a major headache for SQL access and it seems to me that the main reason it is used is because of all caps keywords.
I did a little FORTRAN for my sins, but I think the last of that was in the early 70s too. It was probably FORTRAN in which I wrote my matrix transposition and eigenvector extraction routines for my dissertation (matrix too big to fit in memory of the Univac 1110 ... probably could do it in a cell phone now). But, I did several hundred thousand lines of COBOL, most notably for the core processing of an on-line database system.
As an undergrad ... at a time when there were very few courses for CS for undergrads, then engineers all took courses in which 95% of the course was FORTRAN and 5% assembler, just to give them a taste. But, the course I took, given by an anthropologist who had moved over from physics, was 95% assembler and 5% FORTRAN because he wanted us to understand how the computer actually worked.
On the contrary, I have been a long believer in whitespace for contributing to readability ... I am always interested in readability, which is one of the reasons I dislike SHOUTING keywords, not only does it draw the eye away from the variable or field names but uppercase is just harder to read.
Does anyone see a need for being able to toggle this behavior at runtime (ie operates on r-code)?
No. I don't see any use for the startup parameter anyway.
But please give us ALL-BLOCKS ON ERROR UNDO, THROW asap!
-peter
The one possible reason for a startup parameter would be compile on the fly ... but then one could simply make sure that any compile on the fly code had the desired error handling in it explicitly. Eliminating the startup parameter and providing a toggle in OEA would be fine with me.
The one possible reason for a startup parameter would be compile on the fly ... but then one could simply make sure that any compile on the fly code had the desired error handling in it explicitly. Eliminating the startup parameter and providing a toggle in OEA would be fine with me.
The toggle in OEA would just be a it of UI to toggle a setting.
A startup parameter would be required to tell the AVM about it. Also typically build tools (ANT, Hudson, sorry Jenkins) don't use OEA, they use then prowin32.exe or _progres directly and that would require a startup parameter as well.
Agreed.
That would be great, yes. At last an answer to my questions in 2008 http://communities.progress.com/pcom/message/11449#11449 (when there was no reaction at all, grrr!).
--
Kind regards,
Stefan Houtzager
Houtzager ICT consultancy & development
lol. Maybe no-one used it then, and therefore had nothing to say
On 18 February 2011 11:01, Stefan Houtzager
I think it is because all those famous people (grrr!!!) are discussing it now. And I'm almost sure that I heard rumours voting against at that time.
Grrrrz, Stefan.
That would be great, yes. At last an answer to my questions in 2008 http://communities.progress.com/pcom/message/11449#11449 (when there was no reaction at all, grrr!).
Looks like we all got bitten by that at some time...
Would be interesting to find one who didn't fell into this.
Keep discussing this issue with your account managers....
That would be great, yes. At last an answer to my questions in 2008 http://communities.progress.com/pcom/message/11449#11449 (when there was no reaction at all, grrr!).
Hi Stefan, just read your post from July 2008. I guess in the 10.2A beta forum that would have had more success. I guess that at that time (when the useless 10.1C just got released) most eyes were already starring at 10.2A.
A bit more attention on 10.1C and structured error handling in the beta might have also prevented the dangerous constructors on the AppError class:
UNDO, THROW NEW AppError ("MyMessage here") .
and
UNDO, THROW NEW AppError ("MyMessage here", 0) .
do two completely different things. Changing the meaning of the first parameter to a method/constructor (but leaving it the same CHARACTER data type) based on the presence of a second optional parameter seems like a bad idea. But I guess it's way too late to get that fixed now.
How about creating this class
USING Progress.Lang.*.
CLASS AppError INHERITS Progress.Lang.AppError:
CONSTRUCTOR PUBLIC AppError ( ):
SUPER ().
END CONSTRUCTOR.
CONSTRUCTOR PUBLIC AppError ( INPUT p0 AS CHARACTER, INPUT p1 AS INTEGER ):
SUPER (INPUT p0, INPUT p1).
END CONSTRUCTOR.
CONSTRUCTOR PUBLIC AppError ( INPUT p0 AS CHARACTER ):
SUPER (INPUT p0,0).
END CONSTRUCTOR.
END CLASS.
This would automatically convert all AppError("foo") to AppError("foo",0)
On 18 February 2011 12:22, Mike Fechner
How about creating this class
Autsch! I try to avoid ambiguous class names as much as I can...
Ha! I agree - but this way may be the lesser of two evils. You could
put some code into the ("message") constructor to create a log record
of the stack and find where the offensive line of code is.
Or, of course, you could fire up search and replace with it's regex
expressions to replace all single-parameter occurrences with a ",0) at
the end
On 18 February 2011 12:47, Mike Fechner
bleicher schrieb:
I logged an internal enhancement request to track this discussion - CR OE00204761.
- Evan
Evan, can you already provide some information if that's actually going to make it into any future release?
Hi Mike:
I cannot provide any input concerning the next release (11.1) at this time. The task of reviewing the open enhancements and determining which will be included in the next release has not begun yet. This issue will be part of that discussion and it does have a very active community following. The Enhancement Request contains a link to this community forum so that the user communities comments can be easily seen during the review process.
At this time, it would be premature to state what will be included in a future release.
Sorry, I cannot be more definitive.
Evan
Sorry, I cannot be more definitive.
No problem! But it sounds there is some hope ...
One can always hope .... but it helps to have a lot of patience. How many years have I been asking for multi-threading and *finally* at PCA we heard that it was at least under consideration! Maybe by 12.x!
One can always hope .... but it helps to have a lot of patience. How many years have I been asking for multi-threading and finally at PCA we heard that it was at least under consideration! Maybe by 12.x!
Many people have use cases for multi-threading. But I guess it's clear that this are two enhancements of totally different scope...
Yes, but being of smaller scope doesn't seem to necessarily mean that it is more likely to get implemented. Something big gets allocated resources when it becomes apparent that it is important, which is sometimes easier to do exactly because the impact is more apparent. Something small often has trouble sneaking in because all the resources have been allocated to things which are seen as more obviously important. Personally, I'd like to allocate a certain small percentage of resources to a small group ... even maybe just a single developer ... who would nibble away at a list of very small projects separate from the prioritized work. Obviously, we aren't going to get multi-threading that way, but I'll bet there we could come up with a list for each release that would bring out cheers from the Info Exchange audiences.