COBOL - Understanding SET MYSELF - cobol

In my COBOL program I have the following statement:
SET MYSELF (STATUS) TO -1.
What this statement does? I don't understand the MYSELF and STATUS words. It seems that the it gives the status parameter the value -1, am I right? What MYSELF means?

MYSELF is a reserved word that enables a compiler-supplied task item to refer to the attributes of its own process. So you are setting STATUS in your own process to -1.
COBOL ANSI-74 Programming Reference Manual (PDF Link)
The reserved word MYSELF is a compiler-supplied task item that
enables a program to access its own task attributes. Thus, any
attribute of a given task can be referenced within that task as
ATTRIBUTE attribute-name OF MYSELF.
For example, CHANGE ATTRIBUTE DECLAREDPRIORITY OF MYSELF TO 90.
CHANGE ATTRIBUTE DECLAREDPRIORITY OF ATTRIBUTE PARTNER OF MYSELF TO 65.
The second example illustrates another task running with a task that you are running.
The PARTNER attribute refers to the other task and the example changes the
DECLAREDPRIORITY of the other task.

In a "plain" COBOL program this statement would not be valid. MYSELF would be an entry below an OCCURS (a "table cell") and STATUS would be the index to use (= a numeric variable).
But as the SET statement can only ("standard COBOL") adjust variables of type POINTER or INDEX and both cannot be set to be negative this statement would normally be invalid.
There are some implementations where you can use SET to adjust any numeric variable (where the -1 would be valid if the target is a signed variable), but as #JerryTheGreek pointed out it looks to be NO COBOL but the "Task-Attribute Identifiers (Extension to ANSI X3.23-1974 COBOL)".

Related

DLV Rule is not safe

I am starting to work with DLV (Disjunctive Datalog) and I have a rule that is reporting a "Rule is not safe" error, when running the code. The rule is the following:
foo(R, 1) :- not foo(R, _)
I have read the manual and seen that "cyclic dependencies are disallowed". I guess this is why I am being reported the error, but I am not sure how this statement is so problematic to DLV. The final goal is to have some kind of initialization in case that the predicate has not been defined.
More precisely, if there is no occurrence of 'foo' with the parameter R (and anything else), then define it with parameters R and 1. Once it is defined, the rule shouldn't be triggered again. So, this is not a real recursion in my opinion.
Any comments on how to solve this issue are welcomed!
I have realised that I probably need another predicate to match the parameter R in the body of the rule. Something like this:
foo(R, 1) :- not foo(R, _), bar(R)
Since, otherwise there would be no way to know whether there are no occurrences of foo(R, _). I don't know whether I made myself clear.
Anyway, this doesn't work either :(
To the particular "Rule is not safe" error: First of all this has nothing to do with cyclic or acyclic dependencies. The same error message shows up for the non-cyclic program:
foo2(R, 1) :- not foo(R,_), bar(R).
The problem is that the program is actually not safe (http://www.dlvsystem.com/html/DLV_User_Manual.html#SAFETY). As mentioned in the section on negative rules (anchor #AEN375, I am only allowed to use 2 links in my answer):
Variables, which occur in a negated literal, must also occur in a
positive literal in the body.
Observe that the _ is an anonymous variable. I.e., the program
foo(R,1) :- not foo(R,_), bar(R).
can be equivalently written as (and is equivalent to)
foo(R,1) :- not foo(R,X), bar(R).
Anonymous variables (DLV manual, anchor #AEN264 - at the end of the section) just allow us to avoid inventing names for variables that will only occur once within the rule (i.e. for variables that only express "there is some value, I absolutely do not care about it), but they are variables nevertheless. And since negation with not is "negation" and not "true negation" (or "strong negation" as it is also often called), none of the three safety conditions is satisfied by the rule.
A very rough and high-level intuition for safety is that it guarantees that every variable in the program can be assigned to some finite domain - as it is now the case with R by adding bar(R). However, the same also must be the case for the anonymous variable _ .
To the actual problem of defining default values:
As pointed out by lambda.xy.x, the problem here is the Answer Set (or stable model) semantics of DLV: Trying to do it in one rule does not give any solution:
In order to get a safe program, we could replace the above problems e.g. by
foo(1,2). bar(1). bar(2).
tmp(R) :- foo(R,_).
foo(R,1) :- not tmp(R), bar(R).
This has no stable model:
Assume the answer is, as intended,
{foo(1,2), bar(1), bar(2), foo(2,1)}
However, this is not a valid model, since tmp(R) :- foo(R,_) would require it to contain tmp(2). But then, "not tmp(2)" is no longer true, and therefore having foo(2,1) in the model violates the required minimality of the model. (This is not exactly what is going on, more a rough intuition. More technical details could be found in any article on answer set programming, a quick Google search gave me this paper as one of the first results: http://www.kr.tuwien.ac.at/staff/tkren/pub/2009/rw2009-asp.pdf)
In order to solve the problem, it is therefore somehow necessary to "break the cycle". One possibility would be:
foo(1,2). bar(1). bar(2). bar(3).
tmp(R) :- foo(R,X), X!=1.
foo(R,1) :- bar(R), not tmp(R).
I.e., by explicitly stating that we want to add R into the intermediate atom only if the value is different from 1, having foo(2,1) in the model does not contradict tmp(2) not being part of the model as well. Of course, this no longer allows to distinguish whether foo(R,1) is there as default value or by input, but if this is not required ...
Another possibility would be to not use foo for the computation, but some foo1 instead. I.e. having
foo1(R,X) :- foo(R,X).
tmp(R) :- foo(R,_).
foo1(R,1) :- bar(R), not tmp(R).
and then just use foo1 instead of foo.

What is the difference between BY CONTENT and BY VALUE in a CALL statement?

What is the difference between BY CONTENT and BY VALUE in a CALL statement in COBOL?
BY CONTENT on a CALL will copy the content of the identifier to a compiler-managed area of storage, which will then be passed to the CALLed program "by reference" implicitly.
This means the CALLed program can change the data, but no change made in the CALLed program will affect the original data in the CALLing program.
Any identifier, of any size valid for the compiler, can be used BY CONTENT (subject to any limits, if existing, which are documented for the specific compiler - you never know).
Although you can change the value in a CALLed program, it would seem a bit obscure to do so, at best.
BY VALUE is an entirely different beast. It is very limited, in that the value "passed" can be either an "integer" or a one-byte alphanumeric value. It can also be a literal.
The PROCEDURE DIVISION USING ... has to know, in the case of BY VALUE, that is is so, by specifying it in an equivalent manner to the CALL. BY REFERENCE and BY CONTENT on the CALL are both BY REFERENCE on the PROCEDURE DIVISION USING.
How this is implemented is down to the specific compiler. IBM Enterprise COBOL puts the value itself in the "parameter list".
Passing parameters by content is the same as passing by reference, except that the data is not copied back into the COBOL memory when the call has completed. Meaning that the original variable cannot be edited by the Called unit.
So the difference between BY CONTENT and BY VALUE is that in the case of BY VALUEonly the value gets passed and therefor not all kind of variables can be passed this way while BY CONTENT the pointer of a copied variable gets passed and in this way every type of variable can be passed.
See: http://documentation.microfocus.com/help/index.jsp?topic=%2Fcom.microfocus.eclipse.infocenter.visualcobol.eclipseux%2FGUID-EB09203C-3873-4DBE-9298-0C353BC0701A.html
By Reference:
When a parameter is passed by reference, a copy of the item in the JVM
COBOL is passed to the native code. When the call to the native has
finished, any changes to the information made in the native code are
copied back to the JVM COBOL. However, this does mean that memory is
shared between the JVM and native environments. In fact, what is
actually passed to the native code is a pointer to the copied data.
This is useful if you are calling non-COBOL programs. The implications
of this are very important, particularly in multi-threaded
environments. Any changes to reference parameters are not visible to
the JVM COBOL calling program until the call has completed.
Arbitrarily complex group items (within the memory limitations) can be
passed by reference. The group definition must be identical in the
native and JVM COBOL source code and it must not contain USAGE POINTER
items. Strings (java.lang.Strings) and tables (java.lang.byte arrays)
can be passed by reference. All other objects (types that inherit from
java.lang.Object, including valuetypes) cannot be passed by reference
(or by value - see below).
By Content
Passing parameters by content is the same as passing by reference,
except that the data is not copied back into the JVM COBOL memory when
the call has completed. Any item that can be passed by reference can
be passed by content.
By Value
In JVM COBOL, the only items that can be passed by value are as
follows: binary-long - the recommended type for passing by value pic
x(4) comp-x pic (9)9 comp pic s(9)9 comp pic (9)9 comp-5 pic s(9)9
comp-5

When do FORTRAN subprograms save data, and when not?

Have a pretty simple function for taking the name of a month, "Jan", "Feb", etc. and converting to the number of the month:
function month_num(month_str)
character*(*) :: month_str
character*3 :: month_names(12)
integer :: ipos(1),location(12)
data month_names/'Jan','Feb','Mar','Apr','May','Jun','Jul','Aug', &
'Sep','Oct','Nov','Dec'/
where (month_names==month_str) location=1
ipos = maxloc(location)
month_num = ipos(1)
end function
And OK, yes, I know it's dangerous to not define "location" before using it.
Problem: During execution of the function, if input is OK, some value of "location" will be set to 1. And, to my surprise, when the function is called again, that value will still be equal to 1. And this, of course, really messes things up. So I figured I would fix it with a new line
data location/12*0/
And I got the same problem.
Finally, I put in
location = 0
just before the "where" statement, and that fixed everything.
So, I thought FORTRAN subprograms would not save data unless the variables were declared with the "SAVE" attribute. Also, with many compilers, you can invoke some sort of "static" option that will keep everything saved. I did neither of these here, but the "location" array was saved just the same. Can someone enlighten me on the rules of when FORTRAN saves data and when not? Thanks.
The value of a variable local to a procedure is preserved across (ie it is SAVEd) in one of two ways:
The programmer specifies the SAVE attribute when declaring the variable, for example:
REAL, SAVE :: var1
The programmer initialises the variable upon declaration, for example
REAL :: var1 = 3.1415
This second, implicit, behaviour is one features of Fortran which seem designed to catch out the programmer, and not just beginners. Note that the value the variable has upon re-invocation is not, in the 2nd example 3.1415, but whatever value it had when the last invocation exited.
It is common for compilers to behave as if a variable is SAVEd when the programmer has not exercised either of these options, perhaps the memory locations used by one invocation of a procedure are not overwritten before the next invocation. But this behaviour is not to be relied on.
The situation is slightly different for variables declared in modules. Again any variable with the SAVE attribute is saved but any other variable only retains its value while the module is use-associated with a program unit which has started executing but not finished. Again some compilers, and some executions of some programs, may behave as if the value of a module variable is preserved despite the module going out of scope but this is non-standard behaviour and not to be relied on.
This behaviour is scheduled to change in Fortran 2008 when variables defined in modules will acquire the SAVE attribute implicitly.
Personally I like to explicitly SAVE variables even when I am sure that they would get the attribute implicitly, it makes the code just a bit easier to understand next time round.

initialize an index variable in cobol

We have a COBOL program in which we populate values into a COBOL internal table and then search this table to find out a certain value. Prior to this search, we initialize tables index variable.
SET PAF-IDX TO 1.
Could anyone clarify, if it is allowed in COBOL to initialize an index variable loke this.
INITIALIZE PAF-IDX.
No. And why would you want to "INITIALIZE" it?
This is from the IBM Enterprise Cobol manual:
identifier-1
Receiving areas.
identifier-1 must reference one of the following:
v An alphanumeric group item
v A national group item
v An elementary data item of one of the following categories:
Alphabetic
Alphanumeric
Alphanumeric-edited
DBCS
External floating-point
Internal floating-point
National
National-edited
Numeric
Numeric-edited
v A special register that is valid as a receiving operand in a MOVE
statement with identifer-2 or literal-1 as the sending operand.
When identifier-1 re
EDIT:
The OpenCobol Programmer's Guide documents it specifically:
The list of data items eligible to be set to new values by this statement is:
Every elementary item specified as identifier-1 ..., PLUS...
Every elementary item defined subordinate to every group item specified as dentifier-1
..., with the following exceptions:
USAGE INDEX items are excluded.
Items with a REDEFINES as part of their definition are excluded; this means that
tems subordinate to them are excluded as well.
The Draft Cobol Standard is less explicit, but these items when used in INITIALIZE are processed by generating a SET rather than a MOVE: DATA-POINTER, FUNCTION-POINTER, OBJECT-REFERENCE, or PROGRAM-POINTER.
EDIT:
Seeing that the OpenCobol reference is not as "specific" as I thought: In IBM Cobol, currently, nothing which cannot be manipulated by being the target of a MOVE can be INITIALIZEd. This is the same for the current OpenCobol. The Draft Cobol has some exceptions, listed, but including neither INDEXED BY (which are not part of the table itself, but separate items for which the compiler itself defines storage) nor USAGE INDEX.

Duh? help with f# option types

I am having a brain freeze on f#'s option types. I have 3 books and read all I can but I am not getting them.
Does someone have a clear and concise explanation and maybe a real world example?
TIA
Gary
Brian's answer has been rated as the best explanation of option types, so you should probably read it :-). I'll try to write a more concise explanation using a simple F# example...
Let's say you have a database of products and you want a function that searches the database and returns product with a specified name. What should the function do when there is no such product? When using null, the code could look like this:
Product p = GetProduct(name);
if (p != null)
Console.WriteLine(p.Description);
A problem with this approach is that you are not forced to perform the check, so you can easily write code that will throw an unexpected exception when product is not found:
Product p = GetProduct(name);
Console.WriteLine(p.Description);
When using option type, you're making the possibility of missing value explicit. Types defined in F# cannot have a null value and when you want to write a function that may or may not return value, you cannot return Product - instead you need to return option<Product>, so the above code would look like this (I added type annotations, so that you can see types):
let (p:option<Product>) = GetProduct(name)
match p with
| Some prod -> Console.WriteLine(prod.Description)
| None -> () // No product found
You cannot directly access the Description property, because the reuslt of the search is not Product. To get the actual Product value, you need to use pattern matching, which forces you to handle the case when a value is missing.
Summary. To summarize, the purpose of option type is to make the aspect of "missing value" explicit in the type and to force you to check whether a value is available each time you work with values that may possibly be missing.
See,
http://msdn.microsoft.com/en-us/library/dd233245.aspx
The intuition behind the option type is that it "implements" a null-value. But in contrast to null, you have to explicitly require that a value can be null, whereas in most other languages, references can be null by default. There is a similarity to SQLs NULL/NOT NULL if you are familiar with those.
Why is this clever? It is clever because the language can assume that no output of any expression can ever be null. Hence, it can eliminate all null-pointer checks from the code, yielding a lot of extra speed. Furthermore, it unties the programmer from having to check for the null-case all the same, should he or she want to produce safe code.
For the few cases where a program does require a null value, the option type exist. As an example, consider a function which asks for a key inside an .ini file. The key returned is an integer, but the .ini file might not contain the key. In this case, it does make sense to return 'null' if the key is not to be found. None of the integer values are useful - the user might have entered exactly this integer value in the file. Hence, we need to 'lift' the domain of integers and give it a new value representing "no information", i.e., the null. So we wrap the 'int' to an 'int option'. Now, if there is no integer value we will get 'None' and if there is an integer value, we will get 'Some(N)' where N is the integer value in question.
There are two beautiful consequences of the choice. One, we can use the general pattern match features of F# to discriminate the values in e.g., a case expression. Two, the framework of algebraic datatypes used to define the option type is exposed to the programmer. That is, if there were no option type in F# we could have created it ourselves!

Resources