Page 1 of 2

Definition of variables

PostPosted: May 28th, 2015, 1:49 pm
by Ajay Askoolum
All workspace variables have a definition, created by one or more statements. For example:

Code: Select all
      a←3 4⍴12?100
      a[1;2]←¯1
      a
 87 ¯1 54 46
 75 91 31 30
  7 57 44 16

I would like to be able to elicit the following:
Code: Select all
      a←3 4⍴87 ¯1 54 46 75 91 31 30 7 57 44 16

I can contrive the expression sought when the all the values are integer; however, there is a loss of precision when one or more values are floating point.

Re: Definition of variables

PostPosted: May 28th, 2015, 2:13 pm
by Davin Church
User command ]WMAKE contains a subroutine named Wfmt that should do what you want. I use it for several purposes myself.

Re: Definition of variables

PostPosted: May 28th, 2015, 2:17 pm
by Davin Church
Oh, and for more data precision, set ⎕pp←16 (or 17) during your run.

Re: Definition of variables

PostPosted: May 28th, 2015, 5:39 pm
by brent hildebrand
Rex Swain has a function FFATC, Format For Assignment using TC characters which may be what you are looking for.

a
87 ¯1 54 46
75 91 31 30
7 57 44 16

FFATC a
3 4⍴87 ¯1 54 46 75 91 31 30 7 57 44 16

His function has some interesting features:
a
1 2 3 4 5 6 7 8
FFATC a
⍳8

I have a modification of his function which I think is also his work called FFATCx
a
1 2 3 4 5 6 7 8
FFATCx a
1+(-⎕io)+⍳8

The latter function has another interesting feature:
a
hijklmnopqrstuv
FFATCx a
⎕av[104+⍳15]

It handles nested arrange.
a←'Ajay' 'Askoolum' 'APL' (1 2 3 4 5 6) (2 5 3 4 1) 'abcdefghijklm'
a
Ajay Askoolum APL 1 2 3 4 5 6 2 5 3 4 1 abcdefghijklm
FFATC a
'Ajay' 'Askoolum' 'APL' (⍳6) (2 5 3 4 1) 'abcdefghijklm'
FFATCx a
'Ajay' 'Askoolum' 'APL' (1+(-⎕io)+⍳6) (2 5 3 4 1) (⎕av[97+⍳13])

Re: Definition of variables

PostPosted: May 29th, 2015, 12:40 am
by Ajay Askoolum
Thanks Brent. As I mentioned, it is relatively easy to construct the APL expression that defines a variable; however, the approach fails when floating point numbers are involved. Here's an example:
Code: Select all
      a←0.01×4 2⍴8?2000
      a[1;1]←10÷3
      FFATC a
4 2⍴3.333333333 4.89 10.82 9.34 15.59 19.02 6.41 6.4
      a≡⍎FFATC a
0
      a≡⍎FFATCx a
0
The reason is
Code: Select all
      a=⍎FFATC a
 0 1
 1 1
 1 1
 1 1
      a=⍎FFATCx a
 0 1
 1 1
 1 1
 1 1

The interpreter can reference the variable with integrity, thus:
Code: Select all
      a≡a
1
Would it be able to return the definition?

Re: Definition of variables

PostPosted: May 29th, 2015, 12:49 am
by brent hildebrand
Note - the result of FFATC/FFATCx is a character string, so it will never match. You need to execute the extression using ⍎.

Also setting ⎕pp←17 will increase the possibility of a match, though with floating point numbers, you may still have an error, you might try manipulating ⎕ct.

Using your last example:

a←0.01×4 2⍴8?2000
a≡⍎FFATCx a
1
a≡⍎FFATC a
1
FFATC a
4 2⍴17.37 4.89 10.82 9.34 15.59 19.02 6.41 6.4
a[1;1]←10÷3
a≡⍎FFATCx a
0
a≡⍎FFATC a
0
⎕pp
10
⎕pp←17
a≡⍎FFATCx a
1
a≡⍎FFATC a
1

Re: Definition of variables

PostPosted: May 29th, 2015, 1:02 am
by Ajay Askoolum
Very interesting.
Why don't these functions localise Print Precision and set it to 17 internally?

Re: Definition of variables

PostPosted: May 29th, 2015, 1:10 am
by brent hildebrand
Depends I suppose on your goal for using these functions. But the neat thing is, YOU can add []PP and []CT to fit your needs! :thumbsup:

Re: Definition of variables

PostPosted: May 29th, 2015, 1:27 am
by Davin Church
Be careful about using []PP = 17 indiscriminately. It gives you the value out as far as the internal storage representation allows. But APL doesn't always use that full value. Usually, APL rounds numbers off slightly when it's processing them because the internal binary representation can't always match the decimal representation. Consequently, some numbers that you think are nicely rounded off are actually stored internally plus or minus 1E¯17 (adjusting for leading digits). You wouldn't want 1 to come back as showing 1.0000000000000001 or .99999999999999999, would you? Worse, if you re-execute that text value it may round for storage in the wrong direction, and you end up two "ticks" off the true value, which may no longer even display correctly.

It's an annoying business when you're dealing with stuff so close to the internals of the system. I typically set my []PP to just 16, which tends to avoid the weird end-precision rounding at the expense of intentionally losing that one final (erratic) digit.

Re: Definition of variables

PostPosted: May 29th, 2015, 1:30 am
by Davin Church
Oh, by the way... Do you need the result to be in readable text format? If not, there's a way of storing the true internal representation of your data so that it can be reconstructed exactly later. Check out 'wrapl' []DR x.

Re: Definition of variables

PostPosted: May 29th, 2015, 2:22 am
by Ajay Askoolum
Background:

1. I am investigating the option for writing functions and variables (and files) from the workspace to database tables as BLOB or CLOB objects. Files & Functions are straightforward. With variables, the best I have is to use 'wrap': this works except that the result of 'wrap' differs without the underlying variable changing. Another APL I am familiar with does have a quad function that returns variables as definitions - works quite well.

2. Primary reason for writing to database tables are a. I can associate names with every row written b. I can hold several versions of any given APL object in the same table etc.

Years ago, I remember reading that a variable that holds a Windows form should not be modified manually; I suppose that also means that it (the variable that holds the definition of the form) should not be created programmatically - for related reasons.

'wrap' appears to work reliably. How does the APL+Win component file system write variables to component files (that too works reliably) ? Does it use 'wrap'?

Re: Definition of variables

PostPosted: May 29th, 2015, 11:32 am
by Davin Church
I use 'wrapl' myself often enough. It works perfectly fine and you can store/retrieve the data in databases or any other kind of file. I'm pretty sure the APL file system uses the same process internally for its components.

The reason that the contents vary is because the 'wrapl' form contains internal workspace pointers, so that if the same variable comes from different places in the workspace the pointers will be different. But that doesn't affect their value - internal pointers are reconstructed upon 'unwrapl' so they're correct for where they end up in the workspace. In addition, variables whose data is not a multiple of 4 bytes may have a little garbage at the end which is unneeded, unpredictable, and inconsequential. This, too, can cause equivalent data to not match exactly when 'wrapl'ed. Both of these effects also take place elsewhere within the variable when it is nested, so the changes may occur in many places throughout the 'wrapl' string. Despite all that, when 'unwrapl'ed the data comes back exactly as it went in, so you may use it however you wish.

APL GUI objects are also structured much like internal storage, probably assembled from multiple pieces of Windows memory, but I don't know the exact process. They're stored as nested heterogenous (mixed) arrays in the workspace. I think they may have special relative-pointers too, so they can't readily be constructed or modified directly. However, two 'def' variables with identical contents WILL come out to be identical, except for subscripts [3] and [4] which are a timestamp. I do a lot of direct comparisons of those in my work. These also should be able to be 'wrapl'ed and 'unwrapl'ed without any problems.

Re: Definition of variables

PostPosted: May 29th, 2015, 11:34 am
by Davin Church
I'm curious about why you're storing multiple versions of variables in your database table. It's not for code versioning purposes, is it?

Re: Definition of variables

PostPosted: May 29th, 2015, 1:18 pm
by Ajay Askoolum
I too like 'wrap' and find it reliable; it provides me with an ideal string to write to or read from databases and still be able to reconstruct the original object.
Why do variables have versions? At any given point of reference, there is only one version (that is, value) of any variable. However, there are many points of reference in real life. Some examples:
1. an individual may have only one surname at a time but over time may have several (surnames may change upon being married, divorced, remarried etc. etc.)
2. a variable holding, say, tax rate will have only one value at a time but over time, it will have had several values.
3. seemingly unchangeable data may also have several versions; for example, if a date of birth was entered incorrectly and then corrected, you may want to know the duration or time span during which the incorrect date of birth was used.

For practical purposes, there may be several values for , say, discount rate: it may vary by (size of) client, age of client i.e. there may be introductory rates for a period and then a 'normal' rate. In a database table:

Client Discount
ABC 1.05
DEF 1.09
...
XYZ 1.03

The application will have a variable Discount, given a Client: the computation remains the same:

Code: Select all
      Discount ← get from database according to client & other criteria
AmtDue←Cost ÷ 1 + 0.01 × Discount


This simplifies coding: the alternative is:

Code: Select all
    ∇ Z←Client GetAmtDue Cost
[1]   :select Client
[2]       :case 'ABC'
[3]           Z←Cost ÷ 1+ 0.01 * 1.05
[4]       :case 'DEF'
[5]           Z←Cost ÷ 1+ 0.01 * 1.09
[6]       :case 'XYZ'
[7]           Z←Cost ÷ 1+ 0.01 * 1.03
[8]   :endselect
    ∇
This has the additional overhead that if the rates change, the code needs to change as well.
Besides, you mentioned version control - isn't that a recognition that objects (data or code) changes?

Re: Definition of variables

PostPosted: May 29th, 2015, 2:56 pm
by Davin Church
Certainly I see what you mean there, I just didn't know what you were meaning by "versions" in your note. It could have meant many things.

Many of the cases you describe I might also consider just keeping a list, and using whichever one is on the bottom (or top, if inverted). But keeping alternative data in the DB as you describe certainly works great.

Version control systems, or source code control systems, or library systems, or any number of other terminologies for that sort of thing is what I was asking about. This is not really the same as "previous user data", but might be thought of similarly from a programmer's point of view I suppose. I certainly wasn't trying to deny the existence of changing data. I was just wondering what kind of versions you were needing. Personally, I've written my own source code version control system in APL for APL and use it extensively. I was just wondering if you were trying to build something like that yourself. I can see now that you're not, but that was the reason for my question.