Hi Greg --

Sorry for the delayed response.  We had some network reconfigurations 
going on Friday which made it a good day to avoid email and get some other 
work done.

> 1. What does the declaration of an array as a return type look like?
>    'proc p() : [] int { }' doesn't seem to work, but you can leave
>    off the type in the declaration and do 'return arrayvar;' and
>    that gets figured out.

At present, I believe that the only two forms are a fully-specified array 
type, e.g.:

        proc p(): [D] int { ... }

or a fully inferred one:

        proc p() { ... }

Ultimately, I think we'd like to support more inferred forms as well, such 
as the form you show or:

        proc p(): [D] { ... }  // infer array's element type, not domain
        proc p(): []  { ... }  // infer both domain and elt type


> 2. Is this a wise thing to do?  Can you return an array that's been
>    created in a sub-routine?
>    We had thought about doing was get a list of results from one
>    sub-routine, where the number wasn't known in advance, for
>    processing by another.  The code might look like
>       var matches : [] 2*(2*int);
>       matches = find_matching_points(pts1, pts2);
>    where find_matching_points counts the number of matches, creates
>    an array to hold them, and then copies the matches into the result
>    before returning it.  We weren't sure if this would work, though,
>    and took another approach.

Yes, you can return an array that's been created in a subroutine, and I 
think this is something we're going to want/need to continue to support. 
One motivating example, similar to yours, is a helper routine that reads 
an array in from a file without knowing how large that array is going to 
be.

As you may have seen in other threads, we're currently revamping the way 
our automated-memory management is being implemented, and as part of that, 
we're reconsidering how this case is implemented today (and how it should 
be in the future), but I don't anticipate the feature going away.

Here's a toy sample program that demonstrates creating and returning an 
array in a helper routine:

---

proc createarray(n) {
   var D = {1..n, 1..n};
   var A: [D] real;
   forall (i,j) in D do A[i,j] = i: real + j / 10.0;
   return A;
}

var B = createarray(3);
writeln(B);
writeln(B.domain);
writeln(typeToString(B.eltType));

var C = createarray(5);
writeln(C);
writeln(C.domain);
writeln(typeToString(C.eltType));

---


> 3. It seems to be a bad idea to put arrays inside records that are
>    passed as arguments, because of the pass-by-value behavior.  Is
>    this a fair statement, or should it be safe?

Barring any bugs, records should be passed by 'const ref' by default, so 
should not be copied when being passed around, nor should any array fields 
within them.  I wouldn't shy away from putting array fields in records for 
this reason.

>    One sub-routine used an inout intent on a record with arrays that
>    it populated.

Note that 'inout' means "copy the record in; copy the record out", as 
compared to (say), 'ref' or 'const ref' which says to pass a reference to 
the record in/out.  (So passing records by 'inout' would result in copies 
of their fields).

>    It would cause the program to segfault or die with
>    a nil dereference about half the time.

I'm not sure what would be causing this, and would be interested in 
getting a copy of such a test to look into it further.


>    Changing the argument to
>    an array of records, and also passing an index into the array,
>    was stable (because the array is passed by reference, so it gives
>    you access to the arrays inside the record without copying them?).

Huh... Doesn't seem like this should be strictly necessary...


> 4. The spec says that reference assignment for records is under
>    discussion (p. 135).  Does this also apply to a ref intent for a
>    record argument?

No, 'ref' (and 'const ref') intents for record arguments are supported and 
should work (AFAIK).


> 5. The spec (p. 170) says that domain.exterior(), interior(), and
>    translate() can take a single integer argument, but this causes
>    a compilation error.
>       const dom : domain(rank=2) = { 1..10, 1..10 };
>       writeln("exterior(2,2) ", dom.exterior(2,2));
>       writeln("exterior(2) ", dom.exterior(2));
>    The first call is accepted, the second produces
      [errors]

Huh, you're right...  I could've sworn we used to support the 
single-integer form of these, so either my memory is off or else someone 
retired them without updating the spec.  I assume you'd find the 
single-argument form a nice convenience?  If so, I can dig deeper and see 
if they were removed (and if so, why) or if I'm misremembering.


> 6. Many of the internal and standard modules use the low and high
>    members of ranges.  It seems that first and last would be safer
>    if the step size or alignment caused them not to hit low/high
>    exactly.  Would it be a best practice to use first/last, or is
>    the worry unfounded?

It really depends on the use case.  For example, the exterior/interior 
routines are designed to be in terms of a range's low/high values, even if 
those values are not described by the alignment; but when iterating over a 
range's value, using low/high can cause problems (and we've recently 
found/fixed bugs related to this).  The alignment capability of a range is 
(relatively) new compared to a lot of the range code, so much of what's 
there at present predates it (and other bugs may be lurking as a result -- 
it seems that the alignment capability has not been used much in 
practice).  Note that first/last will also take the sign of the stride 
into account (e.g., first may be greater than last), so may not always be 
what you want -- in such cases, alignedLow/alignedHigh may be the desired 
values.

-Brad


------------------------------------------------------------------------------
_______________________________________________
Chapel-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/chapel-users

Reply via email to