Singular Manual: countedref

| ## 4.28 reference and shared (experimental) The black box data types `reference` and `shared` in SINGULAR allow for concurrently accessing SINGULAR object data. Copying such object will only add an additional handle which allows you to define multiple identifers for the same object instance. Both experimental features are hidden by default, please activate them by typing `system("reference");` or `system("shared");`, respectively, at the SINGULAR prompt. You must initialize a `reference` using a named identifier or a subexpression of the latter. The resulting object can be stored to gain read and write access from sophisticated data structures.
    system("reference"); system("shared");
    int i = 17;
    reference ref = i;

    ref;
    ==> 17
    ==>
    ref = 19;
    ref;
    ==> 19
    ==>
    i;             // original handle changed!
    ==> 19

    kill ref;
    i;             // 'i' stays alive
    ==> 19

    reference uninitialized;
    uninitialized;   // not initialized
    ==> <unassigned reference or shared memory>
    // error: not a named identifier:
    uninitialized = 17;
    ==>    ? Can only take reference from identifier
    ==>    ? error occurred in or before ./examples/reference_and_shared__experim\
       ental_.sing line 16: `uninitialized = 17;`

    // but subexpressions of named identifiers will do
    list ll = list(3,4,5);
    reference ref = ll[2];
    ref;
    ==> 4
    ==>
    ref = 12;
    ref;
    ==> 12
    ==>
    ll;
    ==> [1]:
    ==>    3
    ==> [2]:
    ==>    12
    ==> [3]:
    ==>    5
In contrast, the type `shared` can be used to avoid the initial identifier definition. Each copy has equal rights for manipulating the data.
    system("reference"); system("shared");
    shared ll= list(2,3);

    ll[1];
    ==> 2
    ==>
    ll[1]= 17;
    ll;
    ==> [1]:
    ==>    17
    ==> [2]:
    ==>    3
    ==>
In most cases the value look-up is done automatically, but sometimes you have to disambiguate the input.
    system("reference"); system("shared");
    int i = 0;
    reference ref = i;
    shared sh = 12;

    ref + sh;    // automated 'dereferencing'
    ==> 12
    ref + 4;
    ==> 4
    4 + sh;
    ==> 16

    list ll = list(ref, ref, ref, ref, ref, ref, ref);
    string(ll);
    ==> 0,0,0,0,0,0,0
    ref = 1;
    string(ll);   // all one now
    ==> 1,1,1,1,1,1,1

    ll[3] = 0;
    string(ll);   // only third element changed
    ==> 1,1,0,1,1,1,1

    reference(ll[1]) = 9;
    string(ll);   // all others changed
    ==> 9,9,0,9,9,9,9

    def(ll[1]) = 11;  // alternative (generic) syntax
    string(ll);
    ==> 11,11,0,11,11,11,11
The previous example had shown that `reference` and `shared` objects can store highly structured without duplicating data all over again. As an additional feature, you can use `reference` objects for implementing procedures having side-effects.
    system("reference"); system("shared");
    list changeme;
    changeme;
    ==> empty list

    proc setfirst(reference ll, def arg) {  ll[1] = arg; }

    setfirst(changeme, 17);
    changeme;
    ==> [1]:
    ==>    17
> If you do not need write-access to `proc` parameters, your code will usually perform better using the `alias` statement in the parameter list, see proc.
> 4.28.1 reference declarations |  |
> 4.28.2 reference expressions |  |
> 4.28.3 shared declarations |  |
> 4.28.4 shared expressions |  |
> 4.28.5 reference and shared operations |  |
> 4.28.6 reference and shared related functions |  |

User manual for Singular version 4-1-3, 2020, generated by texi2html.