UV function that returns variable type

511 views
Skip to first unread message

Chuck Stevenson

unread,
Aug 17, 2016, 12:10:04 PM8/17/16
to Pick and MultiValue Databases
I don't know if the word 'type' is the right word in this loosely typed language, but I'd swear there is now a Universe function that will return what kind of thing a variable currently contains.  E.g., string, filevar, listvar, dimensioned, unassigned.   

But now I can't find it or any reference to it, or a UNIVERSE.INCLUDE file that defines the return values.  Maybe I'm getting 2 programming languages mixed up, but I'm pretty sure I've used it in UV.   It may have been a rel10 or 11 enhancement.

Anyone???   
TIA,
cds

P.S.  I'm going to cross-post this because it is unclear to me where the best place to ask these kinds of questions is.  

Peter McMurray

unread,
Aug 17, 2016, 5:35:13 PM8/17/16
to Pick and MultiValue Databases

Hi
I reckon you are thinking of the NUM() function that returns a 1 for anything numeric. However some caution is required as period, plus, minus and the combination of period with plus or minus also return a 1. 
I haven't used Universe for quite a few years now but D3 and U2 do not vary too much with original functions.
It does raise the question of what would be the situation for European users where the comma is used for the decimal point and also what would happen if one was looking at a US style number with comma thousand delimiters. D3 will return 1,123.45 as non numeric in US style.

Glen Batchelor

unread,
Aug 17, 2016, 5:38:45 PM8/17/16
to mvd...@googlegroups.com
  There is no concept of variable data typing in MV languages unless someone snuck something by me in the past 3 years. What is the root problem?

--
You received this message because you are subscribed to
the "Pick and MultiValue Databases" group.
To post, email to: mvd...@googlegroups.com
To unsubscribe, email to: mvdbms+unsubscribe@googlegroups.com
For more options, visit http://groups.google.com/group/mvdbms

Wols Lists

unread,
Aug 17, 2016, 6:29:46 PM8/17/16
to mvd...@googlegroups.com
On 17/08/16 22:38, Glen Batchelor wrote:
> There is no concept of variable data typing in MV languages unless
> someone snuck something by me in the past 3 years. What is the root problem?

That doing certain operations on certain variable types will crash your
program?

IF FILEVAR EQ "" will crash a UV-Basic program (unless they've fixed
it). This caused us loads of grief in our port from PI because to me the
obvious value of that statement is "false", not "crash", and our
programs had a habit of relying on it.

There is some SYSTEM function that will tell you whether a variable is a
filevar, or unassigned, or whatever, but I can't tell you what it is...

Cheers,
Wol
> <mailto:mvd...@googlegroups.com>
> To unsubscribe, email to: mvdbms+un...@googlegroups.com
> <mailto:mvdbms%2Bunsu...@googlegroups.com>
> For more options, visit http://groups.google.com/group/mvdbms
> <http://groups.google.com/group/mvdbms>
>
>
> --
> You received this message because you are subscribed to
> the "Pick and MultiValue Databases" group.
> To post, email to: mvd...@googlegroups.com
> To unsubscribe, email to: mvdbms+un...@googlegroups.com

Chuck Stevenson

unread,
Aug 17, 2016, 7:29:02 PM8/17/16
to Pick and MultiValue Databases
Glen, 
Wol nailed why I want it:  Avoiding runtime errors, sometimes fatal.  
Troubleshooting & trying to be robust in a low level subroutine where I can't control what is being passed to me.

There is ASSIGNED(X), UNASSIGNED(X), FILEINFO( X, FINFO$IS.FILVAR ),
Those each do part of the trick, but not the whole thing.

Wol, 
I don't think SYSTEM  will do it.  It has one argument & you feed it a code, a number & it returns a value.  It would not know what variable you are asking about.  Unless there is a form that takes 2 arguments.  I looked.  I don't see it.

Peter,  
NUM(), LEN() all assume the variable is a string (strings can be numbers, per Glen's no such thing as type comment.)   If you put a file variable in it or a list variable, it would error out. 


Here is an attempt.  But it doesn't see the difference between a list-variable & a string:

CDS.BP X

0001       CRT 'unassigned'
0002       GOSUB WHAT.IS.X
0003
0004       CRT 'list var'
0005       EXECUTE 'SELECT VOC SAMPLE' RTNLIST X CAPTURING DUMMY
0006       GOSUB WHAT.IS.X
0007
0008       CRT 'file var'
0009       OPEN 'VOC' TO X ELSE STOP
0010       GOSUB WHAT.IS.X
0011
0012       CRT 'String'
0013       X = '123456':@VM:'ABC'
0014       GOSUB WHAT.IS.X
0015       STOP
0016 WHAT.IS.X:
0017       CRT '       NUM( X ): ':DQUOTE( NUM( X ))
0018       CRT '    ISNULL( X ): ':DQUOTE( ISNULL( X ))
0019       CRT '  ASSIGNED( X ): ':DQUOTE( ASSIGNED( X ))
0020       CRT 'UNASSIGNED( X ): ':DQUOTE( UNASSIGNED( X ))
0021       CRT 'FILEINFO( X,0 ): ':DQUOTE( FILEINFO( X, 0 ))
0022       RETURN
0023    END
>RUN CDS.BP X
unassigned
       NUM( X ): "0"
    ISNULL( X ): "0"
  ASSIGNED( X ): "0"
UNASSIGNED( X ): "1"
FILEINFO( X,0 ): "0"
list var
       NUM( X ): "0"
    ISNULL( X ): "0"
  ASSIGNED( X ): "1"
UNASSIGNED( X ): "0"
FILEINFO( X,0 ): "0"
file var
       NUM( X ): "0"
    ISNULL( X ): "0"
  ASSIGNED( X ): "1"
UNASSIGNED( X ): "0"
FILEINFO( X,0 ): "1"
String
       NUM( X ): "0"
    ISNULL( X ): "0"
  ASSIGNED( X ): "1"
UNASSIGNED( X ): "0"
FILEINFO( X,0 ): "0"
>


For you primates, a list-variable is for PICK flavour concept. See $OPTIONS VAR.SELECT.
For you newbies, I wasn't being rude.  There are people & systems that come from Pick & Prime heritages.  We affectionately refer to each other as Pickies & Primates, respectively.

Kevin Powick

unread,
Aug 17, 2016, 9:37:44 PM8/17/16
to Pick and MultiValue Databases
Although there is no difference between a string and a list-variable returned from "Execute", which is just an attribute-delimited string of item ids, the question in terms of error checking is, "Does it really matter?"

If you're really paranoid, one thing you might do for a list-variable check is ensure that all values in the string (id = listvar<n>) do not exceed the max item id length for your system, and that all values conform to your company standards for item ids.  i.e. Only 0-9, a-z, -, etc.

Having said that, there is indeed a difference, on D3 anyway, for what is returned into a list-variable via a Basic SELECT statement done against a file variable. e.g. SELECT MY.FILE.VAR TO MY.SELECT.LIST

I don't know if you have to think about that one on UV.

--
Kevin Powick

Chuck Stevenson

unread,
Aug 18, 2016, 7:29:05 AM8/18/16
to Pick and MultiValue Databases
Kevin,
What you say about list variables & dynamic arrays is true for some flavours but not others.
I'm working in "PICK Flavour", & a list variable cannot be treated like a dynamic array.

     RELLEVEL
001 X
002 11.1.15
003 PICK
004 PICK.FORMAT
005 11.1.15

My question was motivated by some troubleshooting,  but wondering about a complete answer is also academic.

I still think there is a uniVerse-supplied function that gives the answer.

Chuck Stevenson

unread,
Aug 18, 2016, 8:13:23 AM8/18/16
to Pick and MultiValue Databases
Found it!  DESCRINFO( )

UV11 Basic Cmd Ref, pg 1-239

DESCRINFO function

Syntax

DESCRINFO(key, variable)

Description

The DESCRINFO function returns requested information (key) about a variable.

Set the key value to 1 to obtain information about the type of variable. Set the key value to 2 to obtain the reuse flag of the variable. Any other value is invalid, and will result in the program exiting.

If the key value is 1, the return type indicates the following type of variable:

_________________________
Return
Value Type               
  0   unassigned variable
  1   integer
  2   numeric
  3   string
  4   file
  5   array
  6   subroutine
  7   sequential file
  8   GCI descriptor
9 NULL value
10 ODBC descriptor   
DESCRINFO Return Values


Example:
Inserted into my sample program from yesterday.

CDS.BP X
0001       CRT 'unassigned'
0002       GOSUB WHAT.IS.X
0003
0004       CRT 'list var'
0005       EXECUTE 'SELECT VOC SAMPLE' RTNLIST X CAPTURING DUMMY
0006       GOSUB WHAT.IS.X
0007
0008       CRT 'file var'
0009       OPEN 'VOC' TO X ELSE STOP
0010       GOSUB WHAT.IS.X
0011
0012       CRT 'String'
0013       X = '123456':@VM:'ABC'
0014       GOSUB WHAT.IS.X
0015       STOP
0016 WHAT.IS.X:
0017       CRT 'DESCRINFO( 1, X ): ':DQUOTE(DESCRINFO( 1, X ))
0018       CRT '         NUM( X ): ':DQUOTE( NUM( X ))
0019       CRT '      ISNULL( X ): ':DQUOTE( ISNULL( X ))
0020       CRT '    ASSIGNED( X ): ':DQUOTE( ASSIGNED( X ))
0021       CRT '  UNASSIGNED( X ): ':DQUOTE( UNASSIGNED( X ))
0022       CRT '  FILEINFO( X,0 ): ':DQUOTE( FILEINFO( X, 0 ))
0023       RETURN
0024    END
>RUN CDS.BP X
unassigned
DESCRINFO( 1, X ): "0"
         NUM( X ): "0"
      ISNULL( X ): "0"
    ASSIGNED( X ): "0"
  UNASSIGNED( X ): "1"
  FILEINFO( X,0 ): "0"
list var
DESCRINFO( 1, X ): "-1"  <-- undocumented.
         NUM( X ): "0"
      ISNULL( X ): "0"
    ASSIGNED( X ): "1"
  UNASSIGNED( X ): "0"
  FILEINFO( X,0 ): "0"
file var
DESCRINFO( 1, X ): "4"
         NUM( X ): "0"
      ISNULL( X ): "0"
    ASSIGNED( X ): "1"
  UNASSIGNED( X ): "0"
  FILEINFO( X,0 ): "1"
String
DESCRINFO( 1, X ): "3"
         NUM( X ): "0"
      ISNULL( X ): "0"
    ASSIGNED( X ): "1"
  UNASSIGNED( X ): "0"
  FILEINFO( X,0 ): "0"
>

As usual, the Pick-related features are not as well-developed or documented as those with Prime-heritage.






Will Johnson

unread,
Aug 18, 2016, 2:53:02 PM8/18/16
to Pick and MultiValue Databases

Although it's true that you do not *define* variable types in Pick BASIC, it's also true that the run time engine has always had variable types.  So as the variable is being stored and shuffled around amonst buffers, it's also assigned a "type" like numeric, string, file pointer, etc.

The run time engine does "on the fly" conversion in *some* instances if you try to do string work on a numeric, or vice versa, which is why you don't have to predefine those types.
 

Will Johnson

unread,
Aug 18, 2016, 2:54:23 PM8/18/16
to Pick and MultiValue Databases
I said "buffer" I meant "register"

geneb

unread,
Aug 18, 2016, 6:34:18 PM8/18/16
to Pick and MultiValue Databases
On Wed, 17 Aug 2016, Chuck Stevenson wrote:

> For you newbies, I wasn't being rude. There are people & systems that come
> from Pick & Prime heritages. We affectionately refer to each other as
> Pickies & Primates, respectively.
>
And SQL users are known as "those poor unfortunates". :)

g.

--
Proud owner of F-15C 80-0007
http://www.f15sim.com - The only one of its kind.
http://www.diy-cockpits.org/coll - Go Collimated or Go Home.
Some people collect things for a hobby. Geeks collect hobbies.

ScarletDME - The red hot Data Management Environment
A Multi-Value database for the masses, not the classes.
http://scarlet.deltasoft.com - Get it _today_!

Peter McMurray

unread,
Aug 18, 2016, 7:05:13 PM8/18/16
to Pick and MultiValue Databases


HI
I am afraid that those who say that everything is a string are wrong as it depends on the circumstances. Storage in a true pick item is a string but Pick can also store binary items and UTF8 as strings of characters. 
I cannot for the life of me imagine why anyone would try and operate on a file variable as anything other than assigned or unassigned 
However for normal variables it will cause issues if they are used in operations that require a specific type of data in particular Numeric. Unfortunately some people are silly enough to store numbers in external format which can cause much confusion. I well remember a thread many moons ago where it became apparent that some did not understand the difference between adding integers and full floating point numbers'
As I pointed out proper data vetting is essential. I have seen lazy programmers use something like IF NUM(VAR) then accept it and a month later the month end procedures crash.
Personally I examine every character entered for its type and the total variable for its length. It is as important to exclude control characters as it is to get the numbers right. 
Yes I do cater for UTF8 which unfortunately the Pick LIST and SORT verbs do not despite the fact that standard Pick storage is 100% compatible.
It appears from the responses that U2 has addressed the issue of type whether it has addressed the UTF8 issue I do not know. Certainly it was promised for D3 in the latest version but failed to make it. QM went off on a tangent with a half solution - what is this obsession with 16 bit Pick is 8 bit UTF8 is 8 bit the two are instantly identifiable and compatible.
.  

Wols Lists

unread,
Aug 19, 2016, 7:23:36 AM8/19/16
to mvd...@googlegroups.com
On 19/08/16 00:05, Peter McMurray wrote:
> I cannot for the life of me imagine why anyone would try and operate on
> a file variable as anything other than assigned or unassigned

Because, for us Pr1mates, named common was ALWAYS initialised? Put a
variable in named common, and it could NEVER be unassigned?

So at the start of my code, I had an include block that said

IF FILEVAR EQ "" THEN OPEN FILE, ...

Which was great until we ported it to UV and pretty much EVERY program
would crash ...

Cheers,
Wol

Chuck Stevenson

unread,
Aug 19, 2016, 7:42:50 AM8/19/16
to Pick and MultiValue Databases

Because, for us Pr1mates, named common was ALWAYS initialised? Put a 
variable in named common, and it could NEVER be unassigned? 

So at the start of my code, I had an include block that said 

IF FILEVAR EQ "" THEN OPEN FILE, ... 

Which was great until we ported it to UV and pretty much EVERY program 
would crash ... 

Yeah common, named or nameless is a bit peculiar in UV.

BEFORE you explicitly assign something to a common variable, it seems to have been initialized to 0, yet ASSIGNED() returns false, UNASSIGNED()  true.
(IIRC, for a long time both functions came back true.  Or was it both false?)


DESCRINFO() returns code "1", meaning "integer'.
& if you reference the variable, you don't get the "unassigned variable" runtime error.

frosty

unread,
Aug 19, 2016, 12:04:27 PM8/19/16
to Pick and MultiValue Databases
On Thursday, August 18, 2016 at 12:54:23 PM UTC-6, Will Johnson wrote:
I said "buffer" I meant "register"

Back in early Pick days this was called a "descriptor" -- quite different from a register.

-- 
frosty

Will Johnson

unread,
Aug 22, 2016, 11:31:10 AM8/22/16
to Pick and MultiValue Databases
Not sure what you mean.
Are you referring to the Run Time Engine names?
And are you referring to the first byte of the register or the entire register?

Charlie Noah

unread,
Aug 22, 2016, 5:39:36 PM8/22/16
to mvd...@googlegroups.com
DESCRINFO doesn't seem to exist in Jbase, at least the version I'm using (3.4). Is there an alternative?

Thanks,
Charlie Noah

stope19

unread,
Aug 22, 2016, 10:39:40 PM8/22/16
to Pick and MultiValue Databases
Maybe just naming confusion. I think what frosty is saying (and I’m sure he will correct me) is that in the early Pick systems (eg: R83) the Basic runtime stored variables in ‘descriptors’, which IIRC where 10 bytes long. This allowed for small strings (max 9 chars, inc the SM) to be stored ‘in-place’ within the descriptor itself. For longer strings the descriptor contained a ‘pointer’ to out-of-descriptor-space storage to the actual string location. I think numbers would also be stored within the descriptor buffer. So, a Basic runtime ‘descriptor’ would consist of a ‘type’ value then either a short string, a pointer to a longer string, a number or a file variable (file variable would be base/module/sep of file). Of course, for non-R83 systems this would almost certainly be very different. I may be way out here - as have not looked at any of this for many years. :)

frosty

unread,
Aug 26, 2016, 3:04:41 PM8/26/16
to Pick and MultiValue Databases
On Monday, August 22, 2016 at 9:31:10 AM UTC-6, Will Johnson wrote:
Not sure what you mean.
Are you referring to the Run Time Engine names?
And are you referring to the first byte of the register or the entire register?

Pick BASIC run-time had a construct called a descriptor. it was ten bytes long.
The first byte determined the type of the variable contained in that descriptor,
e.g. integer, short string, long string, file variable, select variable. This sounds
like what you were calling a "register". Pick Virtual Machines had a construct
called a register -- it was quite different than the descriptor.

-- 
frosty 

CWNoah

unread,
Aug 31, 2016, 10:05:40 AM8/31/16
to Pick and MultiValue Databases
Anybody?


|| DESCRINFO doesn't seem to exist in Jbase, at least the version I'm using (3.4). Is there an alternative?
|
|Thanks,
|Charlie Noah

Chuck Stevenson

unread,
Aug 31, 2016, 5:03:56 PM8/31/16
to Pick and MultiValue Databases
Sorry, Charlie.
I'm going to guess UV is unique on this point.  But silence is not proof it doesn't exist (same as for the sasquatch).
No one answered my original question about UV either, at least not before I rediscovered it myself.

Ed Clark

unread,
Aug 31, 2016, 9:28:29 PM8/31/16
to mvd...@googlegroups.com
I asked on the jbase google group. Jim Idle responded that a well written program would never need anything like that. Take the conversation there if you’re interested :)

Brian Speirs

unread,
Aug 31, 2016, 10:34:08 PM8/31/16
to Pick and MultiValue Databases
No - it isn't unique to UV. OpenQM has the VARTYPE function. The documentation says this:

QM stores data internally in a type variant manner. The actual data type associated with a variable may change as new data is stored. The VARTYPE() function allows a program to determine the internal data type being used. It returns one of the following values. The symbolic names shown are defined in the SYSCOM KEYS.H include record.


And then follows the list of return codes...

Cheers,

Brian

Ross Ferris

unread,
Sep 1, 2016, 4:24:56 AM9/1/16
to Pick and MultiValue Databases
I tend to agree with Jim ... your program should be in total control ... if you have to check to see if a variable has been assigned, or is of the right "type", fix the problem in the program tather than the symptom in the runtime.

Chuck Stevenson

unread,
Sep 1, 2016, 5:42:16 AM9/1/16
to Pick and MultiValue Databases
But sometimes one's program interfaces with other programs over which one has ittle or no control.  Or future programs that haven't been conceived of, let alone well-written.

In those cases sometimes it is nicer to anticipate & avoid an error, & report it so it can get fixed, rather than ploughing ahear & crashing.

Chuck Stevenson

unread,
Sep 1, 2016, 5:51:08 AM9/1/16
to Pick and MultiValue Databases
QM, nice.
QM has also already implemented something somewhat related that I suggested to Rocket as an enhancement:  Error handling for CALL statement for when a subroutine doesn't exist, or there is an argument mismatch, or some (trickier) system error when executing.
Something along the lines of    CALL subName( arg1, . . . ) ON ERROR . . .

I talked to Rocket about a year ago & they seemed interested, but I don'tr know the disposition of the request.
There are some good workarounds already.  For example change the call to execute & examine @system.return.code afterward.

Kevin King

unread,
Sep 1, 2016, 8:56:18 AM9/1/16
to mvd...@googlegroups.com

Ross, let's say we have a subroutine that accepts a file name as a formal argument. Years pass and some new person passes a file pointer instead.  If the subroutine could check the variable type it could accept either and behave properly instead of blowing up. By your definition this would signify a problem with the subroutine that it is being used improperly. I disagree. Without this ability to check the variable type, the subroutine writer doesn't have a fighting chance to protect against fringe misuse.


On Sep 1, 2016 2:24 AM, "Ross Ferris" <ross....@hotmail.com> wrote:
I tend to agree with Jim ... your program should be in total control ... if you have to check to see if a variable has been assigned, or is of the right "type", fix the problem in the program tather than the symptom in the runtime.

--
You received this message because you are subscribed to
the "Pick and MultiValue Databases" group.
To post, email to: mvd...@googlegroups.com
To unsubscribe, email to: mvdbms+unsubscribe@googlegroups.com

Wols Lists

unread,
Sep 1, 2016, 8:59:26 AM9/1/16
to mvd...@googlegroups.com
On 01/09/16 10:42, Chuck Stevenson wrote:
> But sometimes one's program interfaces with other programs over which
> one has ittle or no control. Or future programs that haven't been
> conceived of, let alone well-written.

Or the runtime's behaviour is just, well, nonsensical.

Consider the following Info-basic code, of the sort put into hundreds of
include files as a matter of GOOD PROGRAMMING PRACTICE.

COMMON /MYFILE/ MYFILE.DATA, MYFILE.DICT
IF MYFILE.DATA EQ "" THEN OPEN "MYFILE" TO MYFILE.DATA
IF MYFILE.DICT EQ "" THEN OPEN "DICT" "MYFILE" TO MYFILE.DICT

Excuse the poor syntax, I'm rusty at actually programming. But that code
should NOT - REPEAT SHOULD NOT - cause the program to crash.

It'll take out UV Basic EVERY SINGLE TIME.
>
> In those cases sometimes it is nicer to anticipate & avoid an error, &
> report it so it can get fixed, rather than ploughing ahear & crashing.
>
Yes. And in this case, I'd argue that the fault is in the Basic
implementation, not my program! I shouldn't have to indulge in expensive
rewrites of lots of programs to get round a problem with the Basic
runtime. It's bad enough having to modify the include file and
re-compile every single program ...
>
> On Thursday, September 1, 2016 at 2:24:56 AM UTC-6, Ross Ferris wrote:
>
> I tend to agree with Jim ... your program should be in total control
> ... if you have to check to see if a variable has been assigned, or
> is of the right "type", fix the problem in the program tather than
> the symptom in the runtime.
>
Cheers,
Wol

Will Johnson

unread,
Sep 1, 2016, 2:46:49 PM9/1/16
to Pick and MultiValue Databases
I just ran your code and it doesn't do anything exciting.
Is it supposed to abort or something?  Because it doesn't

Universe 11 in Information mode on Windows 7

Wols Lists

unread,
Sep 1, 2016, 7:50:31 PM9/1/16
to mvd...@googlegroups.com
On 01/09/16 19:46, 'Will Johnson' via Pick and MultiValue Databases wrote:
> I just ran your code and it doesn't do anything exciting.
> Is it supposed to abort or something? Because it doesn't
>
> Universe 11 in Information mode on Windows 7
>
Did you get it to run twice?

The first time, it runs fine, because " IF FILEVAR EQ "" " returns true.
But, in typical PI fashion, it got called repeatedly ... and if FILEVAR
actually was an open file, it crashed. That was definitely the case in
9.6, and I believe it was still true in 10.

I don't think I've used 11, certainly I haven't tried running that sort
of code on it. As I said :-) "unless they've fixed it". Maybe I
shouldn't have said "every single time" :-) but my personal - quite
likely out-of-date - experience is exactly that.

Cheers,
Wol
>
> On Thursday, September 1, 2016 at 5:59:26 AM UTC-7, Wol wrote:
>
>
> Or the runtime's behaviour is just, well, nonsensical.
>
> Consider the following Info-basic code, of the sort put into
> hundreds of
> include files as a matter of GOOD PROGRAMMING PRACTICE.
>
> COMMON /MYFILE/ MYFILE.DATA, MYFILE.DICT
> IF MYFILE.DATA EQ "" THEN OPEN "MYFILE" TO MYFILE.DATA
> IF MYFILE.DICT EQ "" THEN OPEN "DICT" "MYFILE" TO MYFILE.DICT
>
> Excuse the poor syntax, I'm rusty at actually programming. But that
> code
> should NOT - REPEAT SHOULD NOT - cause the program to crash.
>
> It'll take out UV Basic EVERY SINGLE TIME.
> >
>

Peter McMurray

unread,
Sep 2, 2016, 7:57:45 PM9/2/16
to Pick and MultiValue Databases

'
Hi
What a weird subject.
If in doubt about a thing being open in old code just open the blessed thing again. 
Better still dump the junk and write it properly.
I have always passed file variables in Common because in the beginning file opens were very time consuming.
However just for fun I thought I would give it a burn in D3

    try
001 open '','test'to tesf else crt "boom no test";stop
002 if assigned(tesf) then
003 crt "open"
004 end else
005 crt "not open"
006 end
007 if test  ne "" then
008 crt "open"
009 end else
010 crt "not open"
011 end
012 tesf = "Joe"
013 if assigned(tesf) then
014 crt "open"
015 end else
016 crt "not open"
017 end

:run mmbp try
open
[B10] in program "try", Line 7:
      Variable has not been assigned a value; zero used.
open
open
:

Whilst D3 would not fall over I very much doubt that the null variable test would have ever worked properly on anything because VAR = "FRED" would produce the same result until you tried to read or write.

The current D3 manual describes it well:
"Unlike numeric and string variables, a file variable cannot be output with a print or crt statement, used in a string or arithmetic expression, or displayed in the FlashBASIC or BASIC debugger. A file variable can be assigned to other variables in a standard assignment statement or copied to other variables, in the form."

"Rocket advises programmers to not rely on the assigned() function to return a specific nonzero value. Its exact value is undefined and can vary between implementations"

MarioB

unread,
Sep 4, 2016, 10:07:32 PM9/4/16
to Pick and MultiValue Databases
Line 7 should be:  if tesf  ne "" then

Peter McMurray

unread,
Sep 5, 2016, 5:39:53 PM9/5/16
to Pick and MultiValue Databases

OOPS! Quite right Mario.
In which case the compiler would bring up 
  File variable used where string expression expected.
and fail compile.
Take out that line and the null test would still be useless later on as the re-assignment to FRED is a valid action.
If the null test was used in a called subroutine then 
:run mmbp try
[B34] in program "try1", Line 2:  File variable used where string expression exp
ected.
there would be a fatal run time error.
In other words don't do it.
Message has been deleted

Ross Ferris

unread,
Sep 6, 2016, 12:58:31 AM9/6/16
to Pick and MultiValue Databases
'd suggest runtime rather than compiler ... and your open failure could try creating & re-opening file. "Easier" to do all sorts of weird & wonderful things with a common routine to open a file, like checking MD if create failed to see if there was already a verb entry there, OR if a super-Q pointer on D3, execute a :start-network & then retry open etc etc 

Wols Lists

unread,
Sep 6, 2016, 10:49:12 AM9/6/16
to mvd...@googlegroups.com
But this is exactly the point !!! Why is the IF expression in line 2
expecting a string expression ??? There is absolutely NO justifiable
reason for enforcing that restriction!

This is Chuck's original point. He is being passed this stuff by a
subroutine to which he has no source. So your admonition "don't do it"
is impractical. He doesn't know what he's got so he can't not do it.

It always amazes me how so many people are happy to put up with hacky
workarounds and stupid restrictions, just to work around someone else's
stupid decisions.

At the end of the day, if you are working with two-value logic, the
statement "IF A EQ B" must ALWAYS evaluate to either TRUE or FALSE. So
who was the idiot who decided that evaluating to "crash" was a perfectly
sensible result?

(Okay, I appreciate sometimes there are deeper constraints which make
life difficult. But if that's the case, why did INFORMATION get it
right, and why do all these other implementations (which are supposed to
be PI-compatible) get it wrong?)

Cheers,
Wol

Peter McMurray

unread,
Sep 6, 2016, 5:26:02 PM9/6/16
to Pick and MultiValue Databases


Hi Wol
You seem to have missed the point altogether.
Information got it wrong not everyone else.
If there is any doubt about the file variable that is passed OPEN it again as the ONLY way that you know whether it is right or wrong is to read it and crash hopefully with an error routine. Remember write did not have an error routine and I have seen code with ERROR NULL or similar.
As I pointed out in line 12 some clown could have changed the file variable to FRED and it would still pass the assigned or true test.
In my opinion the sensible way is to have a file control in a separate routine as Ross suggested.
From day one some 40 years ago I have always written file opens in a special routine and passed them in COMMON at the very beginning of the application so the problem never arose.  

Ross Ferris

unread,
Sep 6, 2016, 8:02:19 PM9/6/16
to Pick and MultiValue Databases
WOL,

<SNIP>


This is Chuck's original point. He is being passed this stuff by a
subroutine to which he has no source. So your admonition "don't do it"
is impractical. He doesn't know what he's got so he can't not do it.

Quite a feat, writing a subroutine that is being called from a "black box" , without even knowing how many parameters are being passed, let alone what is supposed to be in each!

For well written closed system I'd like to think that such sanity checking wasn't necessary - and if things fail FIX THEM or get them fixed properly, which is my takeaway from this statement

It always amazes me how so many people are happy to put up with hacky
workarounds and stupid restrictions, just to work around someone else's
stupid decisions.


The only time I would see this level of sanity checking being required is for a routine that IS being accessed from outside of the application ecosystem, like a web service - and if the core logic could be called from the outside world OR from an "internal" routine within UV, D3 or whatever then I'd suggest it could even be worthwhile having a stub routine for the external world interface that does the necessary sanity checking, which then CALLs the routine with known good data, so that the internal routines don't have the (albiet minimal) overhead of unnecessary checks when used "properly" from within the core application.

I'm amazed by the number of people who never check their errors, runtime-errors or whatever file on development systems, and worse still for deployed applications, to identify these sorts of problems & correct the offending code ASAP to avoid repeat performances

  

Ross Ferris

Stamina Software

Visage > Better by Design!

Chuck Stevenson

unread,
Sep 6, 2016, 9:23:32 PM9/6/16
to Pick and MultiValue Databases
Let me restate the original motivation.
It's for troubleshooting where errors are happening and I'm trying to find the source.
Yes, it would be nice to just never have buggy code.  Even if I were so clever, myself, there are other mere mortals who don't turn out perfect code every time.  I suspect I'm tracking down a latent bug that has lain dormant for, lo, these many years, but now, due to some new business need (dang users!) sometimes gets triggered.

There are variables that are usually of one 'type' or another but sometimes not.   Don't tell me, "Don't do that."  1st, I haven't, but, 2nd, someone has. 3rd, the enterprise relies on it.

My new temporary debugging code that logs what I want needs to be robust enough to roll with the punches.  At the point where I detect a problem, I am logging the return stack (per system(9001)), and values of several variables, many of which are in common.  I don't want to assume the variable "type", even though I'm 99.999% sure of it because I'm chasing a 0.001% bug.

Frankly, FILEINFO(), ASSIGNED(), UNASSIGNED() are probably good enough for what I need.  It was just that when I was writing it I couldn't remember DESCRINFO() & it bothered me.  I knew it was out there.  I thought a quick ping to this group would yield a quick pong back with the answer.

I like DESCRINFO().  I used it one time before & it allowed compact coding for checking of input parameters in the interest of robustness.


Brian Speirs

unread,
Sep 6, 2016, 10:20:42 PM9/6/16
to Pick and MultiValue Databases
It seems as if most of the drama here is over whether something is a file variable or something else. FWIW, I sometimes write code where a variable passed to a subroutine may be either a file variable or a file name. I then use FILEINFO to determine which I've got. Here is an extract from a subroutine that writes to a log file, and is passed "something" in the 'logfile' variable:

err = @FALSE
IF FILEINFO(logfile, FL$OPEN) THEN
  logfp = logfile
END ELSE
  CALL Q.OPEN(logfile, logfp, 2, err)
  IF (err) THEN RETURN
END
vocname = FILEINFO(logfp, FL$VOCNAME)

This just adds a bit of flexibility to my code library.

Cheers,

Brian

Wols Lists

unread,
Sep 7, 2016, 12:46:09 PM9/7/16
to mvd...@googlegroups.com
On 06/09/16 22:26, Peter McMurray wrote:
>
> Hi Wol
>
> You seem to have missed the point altogether.
> Information got it wrong not everyone else.

How is it wrong to correctly return the correct value in the case of a
logical comparison?

Oh - and as for re-opening the file every time, how is it correct to
slow the program speed down by half? This technique was standard
practice on Pr1me because opening files was slow.

But I repeat my main point - why is it wrong to return the correct answer?

Cheers,
Wol

Peter McMurray

unread,
Sep 7, 2016, 5:22:18 PM9/7/16
to Pick and MultiValue Databases


Hi Wol
It is not the correct answer. 
The If statement does not tell you whether it is a file variable or an ordinary variable. Perhaps there should be a command that tells you that but there wasn't in Information or Pick.
Relying on it was foolish as it would still crash if as I said some twerp wrote FILEVAR = "FRED"  and the IF statement had "saved time".
It appears that there is one in U2 and since U2 and D3 are being amalgamated at the operating system level by Rocket the problem will be solved.
It was not standard practice on Prime for me or my partner Stuart Evans we ensured that the File Common area was used for exactly that at the start of any application.
As for sometimes passing a file variable and sometimes ANOther in the same variable I am glad that I never had to work on stuff that bad.
Ross has it right.
Regarding fixing current code. First of all since FSI was introduced to D3 the speed problem of Open has been dramatically reduced from the Pick days. Secondly whilst it may be very satisfying to trace the wonky call is it worth the cost of chasing something so rare when the junk should be gradually replaced.

Wols Lists

unread,
Sep 7, 2016, 6:22:01 PM9/7/16
to mvd...@googlegroups.com
On 07/09/16 22:22, Peter McMurray wrote:
>
> Hi Wol
> It is not the correct answer.
> The If statement does not tell you whether it is a file variable or an
> ordinary variable.

Who cares if it's a file variable or not? That is NOT the question the
IF statement is asking.

The IF statement is asking "is this variable NULL, or not?". And I do
NOT consider a runtime crash to be an acceptable answer! Either the
variable is null, and the statement returns true, or it is not (whether
it is a file variable or not is completely irrelevant) and it returns false.

At the end of the day, as I said before, if you are using two-value
logic then an IF statement has only two valid values, true or false. It
should not return a third value, namely "crash". Taking your logic to
the extreme, it seems you would not consider it an error if adding 1+1
returned 3 - oh - and an ex-boss of mine found a FORTRAN compiler once
that did exactly that :-) Would you argue that it's the user's program
that is at fault when fed through that compiler?

(As I used it, it was a named common variable, therefore it was not
allowed to be unassigned, and was initialised to null as per the
compiler specification. All I wanted to know was whether the variable
had been altered from its pristine state.)

Cheers,
Wol

Peter McMurray

unread,
Sep 8, 2016, 5:38:19 PM9/8/16
to Pick and MultiValue Databases

Who Cares what it is?
The person trying to read from it. Far better to crash it at compile on the main or at least at the first use in a called routine than plough on.

! + ! = 3
Sounds like someone who did not understand the difference between a base 2 and a base 10 integer variable to me. In this circle that has cropped up with people confusing floating point and integer arithmetic.

Have a Good Day

Wols Lists

unread,
Sep 9, 2016, 5:39:24 AM9/9/16
to mvd...@googlegroups.com
???

INT X, Y
X = 3
Y = X + 1
PRINT Y

That is, approximately, the program my boss sent to the computer
manufacturer people. Oh - and when they ran it the reaction was "Oh,
holy shit!" because the answer was NOT 4. (This is FORTRAN remember, any
decent programmer explicitly typed his variables.)

> Have a Good Day
>
Remind me never to go near a program you've QA'd, if you think ignoring
the laws of mathematics is acceptable behaviour in a compiler ...

I'm sorry, but all I want is for my program to output *mathematically*
*correct* results.

Cheers,
Wol

Peter McMurray

unread,
Sep 9, 2016, 10:24:15 PM9/9/16
to Pick and MultiValue Databases


Hi Wol
In Order for a program to output mathematically correct answers the programmer has to first understand maths.
The fact that there is no equivalent to a tenth in binary which is the basis of floating point arithmetic leads to many a mess.
Python has 53 digit precision and a separate function to bring the results back to decimal.
In Javascript the recommendation from masters in the field when dealing with currency is just multiply by 100 and do integer arithmetic.
As for the Fortran example you gave my first Fortran lecturer back in 1969 would have failed him. 
Rule 1 is Initialise all Variables as you don't know what is left in registers.
In Pick use internal format for storage, don't store in external format then set floating point and race through adding up lots of decimal fractions you will not get the correct answer.

Personally I recommend Tom Lehrer's 1965 record "That Was The Year That Was" and the song New Math.

Oh in conclusion how did I discover the other issue of significant digits that affect results in Pick.I wrote the Rental system for the company responsible for the most expensive shopping precinct in Melbourne at the time. Being used to the accuracy of my Hewlett Packard calculator I only rounded results at the end. OOPS! the prime location was a Fur Shop. All went well in Summer but suddenly in Winter their rent which was based on a minimum figure or a %age of turnover went negative. Mink coats are expensive.
Now I have been congratulated by the ACCC as one of the few people that get GST calculations correct. The Tax office decided that GST must be calculated on the price to six decimal places times the quantity. Unfortunately lawyers drew up the legislation and failed to define the difference between price and value. The result is that many packages calculate 30,000 litres of  Diesel at $1.456 as ((30,000 * 1.456) *1.1) instead of ((1.456/10) + 1.456) *30,000. In desperation the tax office accept both.
.  

Will Johnson

unread,
Sep 14, 2016, 2:47:07 PM9/14/16
to Pick and MultiValue Databases
Yes it's true that we don't *all* have the fortune of being able to look inside code that we are required to call.

It's called *job* security through obsfucation.... or something.

*Some* people (not naming names) write all their own code and have never encountered documentation which just tells you how many arguments, what types they are supposed to be, and what the output should look like, and maybe if you're lucky what kinds of errors you might encounter.  But I certainly have.  It seems to be very popular with certain software vendors to give you documentation like this, and then when it breaks spend your money to figure out how you had to wrong to being with.

And of course the problem becomes worse for independent contractors called in to *fix* something that the vendor left broke, and being hobbled by trying to work around the break.

That's the world in which we live.

geneb

unread,
Sep 15, 2016, 2:58:43 AM9/15/16
to 'Will Johnson' via Pick and MultiValue Databases
On Wed, 14 Sep 2016, 'Will Johnson' via Pick and MultiValue Databases wrote:

>
> And of course the problem becomes worse for independent contractors called
> in to *fix* something that the vendor left broke, and being hobbled by
> trying to work around the break.
>
Decompilers help. :)

g.

--
Proud owner of F-15C 80-0007
http://www.f15sim.com - The only one of its kind.
http://www.diy-cockpits.org/coll - Go Collimated or Go Home.
Some people collect things for a hobby. Geeks collect hobbies.

ScarletDME - The red hot Data Management Environment
A Multi-Value database for the masses, not the classes.
http://scarlet.deltasoft.com - Get it _today_!

Tony Gravagno

unread,
Sep 15, 2016, 3:27:53 AM9/15/16
to mvd...@googlegroups.com
On my phone and not sure where else to put this, sorry if misplaced.

I use this pattern extensively in D3:

COMMON /BLAH/ INITIALIZED, FV

IF NOT(ASSIGNED(INITIALIZED)) THEN
  GOSUB DO.INIT
  INITIALIZED = 1
END ...

For files it's similar:

IF NOT(ASSIGNED(FV)) THEN
  OPEN "FOO" TO FV ELSE ..
END

Actually I structure named common and file variables so the above is a dirt-simple example, not production code.

The next time the program is executed the variables will have been assigned, so continue without refreshing.

Do not compare a variable to empty string if it hasn't been assigned! Recall the error "Unassigned variable, zero used". You're comparing zero to empty string, they will never be equal. And another error results from comparing a file descriptor to a literal, so FV="" is invalid as well.

All other platforms seem to work the same (been a long time, correct if required) except Unidata which uses IF UNASSIGNED(...). If you want to use platform-specific tools, go for it, just don't be surprised when you need to recode to run elsewhere - and yeah, it happens a lot. In that case I use Kevin King's XBASIC. See FOSS4MV for the code.

Please, no arguments that this doesn't work. I've been using this pattern everywhere for many years. If you don't think it works then you aren't using the tools correctly.

Chuck, if you want to know if Rocket still has your suggestion, ask. Always get an ID for your exchanges. You don't need to remember/log them, just make sure they (your vendor) has it so they can look it up later.

Enough outta me.
T

Tony Gravagno

unread,
Sep 15, 2016, 3:40:57 AM9/15/16
to mvd...@googlegroups.com
Ross, you won't get much argument about runtime-errors because most people simply don't know about it, which explains why they don't check it. That includes high priced support companies and "value-add" resellers.

My user macro on D3 client systems first lists runtime errors and then lists system errors, before even prompting for an account. With that info as soon as I login, I know where my priorities are. And I rely on those reports for all debugging and system maintenance efforts.

Agreed that this applies to all platforms.

T

Wols Lists

unread,
Sep 15, 2016, 2:28:35 PM9/15/16
to mvd...@googlegroups.com
On 15/09/16 08:27, Tony Gravagno wrote:
> Do not compare a variable to empty string if it hasn't been assigned!
> Recall the error "Unassigned variable, zero used". You're comparing zero
> to empty string, they will never be equal. And another error results
> from comparing a file descriptor to a literal, so FV="" is invalid as well.

Okay, Pr1me went bust what, 25 years ago? But did you ever run that code
on INFORMATION?

If I Recall Correctly, the Pr1me documentation on named common
explicitly said all common variables are initialised to null, so your
"IF NOT(ASSIGNED())" would *never* return true. I don't think that was
true of unnamed common.

And, my biggest moan, what on earth is wrong comparing a file descriptor
to a literal? The correct answer is "no, they are not equal, so return
false". Not "that is illegal, crash". And Pr1me got it right.

Cheers,
Wol

Will Johnson

unread,
Sep 15, 2016, 3:39:28 PM9/15/16
to Pick and MultiValue Databases
I wrote my own decompiler for the R83 p-code and it worked for Ultimate and Adds implementations
But I'm not aware of any decompiler for the Universe code

Chuck Stevenson

unread,
Sep 15, 2016, 5:25:11 PM9/15/16
to Pick and MultiValue Databases
On Thursday, September 15, 2016 at 12:58:43 AM UTC-6, geneb wrote:

Decompilers help. :)

UniVerse has "VLIST"  which decompiles basic code into a pseudo-assembler readout.
I recommend that everyone read through a program or 2 & see what happens with typical basic constructs.
You might change a few habits.

Similarly DLIST does much the same for I-descriptors.

Chuck Stevenson

unread,
Sep 15, 2016, 6:07:40 PM9/15/16
to Pick and MultiValue Databases
UV has both ASSIGNED() & UNASSIGNED().

But how they behave with named common variables depends on the flavour of the account they are  RUN in.  Note that this is Independent of compiler directive $OPTIONS or flavour of the account it was compiled in.   The same compiled code will run differently in PIck vs Ideal accounts.  I haven't checked all the flavours.

(In an earlier release, iirc, there was an inconsistency with common variables.  Before a var was explicitly assigned they both came up TRUE.  (Or was it both false?)  That may have been a Pick-flavour problem only.)

In either, flavour, before explicitly assigned you can use a common variable and it will contain a "0" after the common is declared & before any explicit 

Bob Dubery

unread,
Oct 28, 2016, 4:26:04 PM10/28/16
to Pick and MultiValue Databases


On Thursday, 1 September 2016 10:24:56 UTC+2, Ross Ferris wrote:
I tend to agree with Jim ... your program should be in total control ... if you have to check to see if a variable has been assigned, or is of the right "type", fix the problem in the program tather than the symptom in the runtime.

I am coming late to this thread.

I've certainly had the need to use ASSIGNED when doing bug fixes. I curse each time I do, but I can see how it happens. Long program. Some variable not initialised in every branch of some complex nested CASE or IF .structure, and tested further down the code. Sure, I would try to not write code like that, but it's out there. Factor in the poor programmer being under pressure to do a quick and dirty at an hour past home time...

I didn't know about the function eventually described., bur I am not surprised that it exists. Within the Universe debugger you can examine a variable and be told if it's a file handle, a string, a matrix, label etc. Clearly at some level Universe has to be able to differentiate. it cannot always tell, and often doesn't need to know, the difference between a number and a string, but that doesn't mean that all variables are stored identically internally. i would be that a similar level of differentiation exists in all languages regarded as having weak typing. They all have typing, really. 

This has been an interesting discussion. Thank you all :-)
Reply all
Reply to author
Forward
0 new messages