[noob questions] Arrays..

Aaaaaaaaaaaaaaaarrrrgggghhhhhgadsfhasdjhf

1. Is foxpro incapable of returning an array from a function by using the return statement 
Tongue Tied
2. Does foxpro have a function that merges 2 arrays
3. How do you pass an array as an argument to a function in a class when the array is a class variable

For example:
define class test as Custom
    dimension Arr(1)   

    procedure asdf(tmpArray, tmpString)
       * do stuff
    endproc

    .. etc etc


How do I call the procedure asdf (from some other procedure in this class) using Arr as an argument


oh, and I almost forgot ->  I'm using foxpro 9



Answer this question

[noob questions] Arrays..

  • Tom Le-Rademacher

    Thanks for the code samples! I do appreciate the time and effort you guys took to answer me!

    But I still don't understand :)


    3) Indirectly. First you need to acopy() it to an array and pass that by reference


    So you mean that it really is impossible to do a call by reference with an array that has the prefix "THIS."

    Hmm, I just read something about macro substitution and I think that it might help me.

    (btw, thanks to you guys I now have more than enough insight and ex
    amples on how to make an alternative solution to my problem )

  • NormanHH

     AndyKr wrote:
    >> But I still don't understand :)

    What don't you understand You cannot do things in VFP as if it were VB - it isn't!

    If you would tell us what you want to do, and why, maybe we can help but without some idea of what you want it is hard to guess the answer.

    >> So you mean that it really is impossible to do a call by reference with an array that has the prefix "THIS."

    Yes. An array with the the prefix "THIS." is a property and you cannot pass a PROPERTY by reference (this has nothing to do with arrays - it applies to ANY property).

    By definition a property belongs to the object that defines it. All you can ever do is pass the propety's values or copy the values to something that is NOT bound to the object (i.e. a copy!).

    The reason is obvious. If you could pass a property by reference you could not release the original object as long as the reference existed - this would be extremely difficult to manage, and impossible to debug.
     


    Well, you answered what I didn't understand Smile It is impossible to pass a property by reference. But it is not very obvious to me, since I'm new to foxpro and in some other programming languages it is possible to pass a property by reference.

    I don't have any experience with VB, but in C++ I  do it like this:
    class cTest
    {
      private:
        int var1;
      public:
        cTest(){
          this->var1 = 12345;
          this->display(&this->var1);
        }
        void display(int *pInt) {
          cout<<*pInt<<endl;
        }
    };

    And in PHP it is almost similar:
    class cTest
    {
        protected $var1;
        function cTest() {
            $this->var1 = 12345;
            $this->display(&$this->var1);
        }
        function display($var) {
            echo $var;
        }
    }
    In the function display I can change the content of the class property var1.

    So I assumed that this would also be possible in foxpro with an array but I was wrong Sad

  • LANDDIS

    > It is impossible to pass a property by reference. But it is not very obvious to me

    If you are interested in the "why" (at least as far as someone without access to the VFP sources can say), you might want to check out my article "How FoxPro works internally" on http://www.foxpert.com/docs/howfoxproworks.en.htm.


  • pablex

    One thing I forgot to mention is that arrays are not used as much in VFP (as opposed to, say VB6). In VFP arrays have a use, and there are many array manipulation functions, but it is so much easier and so much more powerful to use cursors (in-memory tables) instead of arrays that most people use these instead.

    It depends on your needs.

  • Kennibal

     ggvw wrote:
    Aaaaaaaaaaaaaaaarrrrgggghhhhhgadsfhasdjhf

    1. Is foxpro incapable of returning an array from a function by using the return statement 
    Tongue Tied
    2. Does foxpro have a function that merges 2 arrays
    3. How do you pass an array as an argument to a function in a class when the array is a class variable

    For example:
    define class test as Custom
        dimension Arr(1)   

        procedure asdf(tmpArray, tmpString)
           * do stuff
        endproc

        .. etc etc


    How do I call the procedure asdf (from some other procedure in this class) using Arr as an argument


    oh, and I almost forgot ->  I'm using foxpro 9



    Alex has already answered you specifically, but if you tell us what you are trying to do, maybe there is an easier (VFP-specific) way (as Alex said, VFP is a database and has integrated data handling capabilities that make passing arrays around redundant)


  • peter_heard01

     AndyKr wrote:

    Alex has already answered you specifically, but if you tell us what you are trying to do, maybe there is an easier (VFP-specific) way (as Alex said, VFP is a database and has integrated data handling capabilities that make passing arrays around redundant)

    You are right, I saw that it is even possible to use sql statements on cursors!
    But now I use an external MySql database from which I retrieve data and send it to an array. My code now looks something like this:

    reslt = SQLEXEC(this.gnConnHandle, sqlQuery, "tmpc")
    select * from tmpc INTO ARRAY tmpArr

    The compiler complains when I want to merge the content of tmpArr to a global class variable called arr:
    this.ArrayMerge(@this.Arr, @tmpArr)

    But I see now that it is perhaps much easier to merge cursors instead of arrays. (But I'm still curious about how to pass the array as an argument :) )


  • asdsasdd

     ggvw wrote:

    The compiler complains when I want to merge the content of tmpArr to a global class variable called arr:
    this.ArrayMerge(@this.Arr, @tmpArr)
    But I see now that it is perhaps much easier to merge cursors instead of arrays. (But I'm still curious about how to pass the array as an argument :) )


    Since you insist, here is how you do it it:

    ******** BEGIN CODE *********
    *** Create the source array from a query
    SELECT * FROM account WHERE cacref = 'B' INTO ARRAY laSce

    *** Create the destination array from a query
    SELECT * FROM account WHERE cacref = 'A' INTO ARRAY laDest

    "Before Merge"
    "Source:", ALEN( laSce, 1 ),  ALEN( laSce, 2 )
    "Target:", ALEN( laDest, 1 ),  ALEN( laDest, 2 )

    *** Call the function
    ArrayMerge( @laSce, @laDest )

    "After Merge"
    "Source:", ALEN( laSce, 1 ),  ALEN( laSce, 2 )
    "Target:", ALEN( laDest, 1 ),  ALEN( laDest, 2 )


    FUNCTION ArrayMerge( taSource, taDest )
    LOCAL lnSRows, lnSCols, lnTRows, lnStart, lnToAdd, lnRow, lnCol
    *** How many rows/cols in Source
    lnSRows = ALEN( taSource, 1 )
    lnSCols = ALEN( taSource, 2 )
    *** How Many Rows in Destination
    lnTRows = ALEN( taDest, 1 )
    *** How many rows to be added
    IF lnTRows = 1 AND EMPTY( taDest[1,1] )
      *** This is an empty array
      lnStart = 0
    ELSE
      *** We have something already
      lnStart = lnTRows
    ENDIF

    *** Arrays in VFP are 1-based NOT 0 based!!!!
    FOR lnCnt = 1 TO lnSRows
      *** Add the row
      lnRow = lnStart + lnCnt
      DIMENSION taDest[ lnRow, lnSCols ]
      *** Now populate the columns 
      FOR lnCol = 1 TO lnSCols
        taDest[ lnRow, lnCol] = taSource[ lnCnt, lnCol]
      NEXT
    NEXT

    RETURN



  • james_h

    >> But I still don't understand :)

    What don't you understand You cannot do things in VFP as if it were VB - it isn't!

    If you would tell us what you want to do, and why, maybe we can help but without some idea of what you want it is hard to guess the answer.

    >> So you mean that it really is impossible to do a call by reference with an array that has the prefix "THIS."

    Yes. An array with the the prefix "THIS." is a property and you cannot pass a PROPERTY by reference (this has nothing to do with arrays - it applies to ANY property).

    By definition a property belongs to the object that defines it. All you can ever do is pass the propety's values or copy the values to something that is NOT bound to the object (i.e. a copy!).

    The reason is obvious. If you could pass a property by reference you could not release the original object as long as the reference existed - this would be extremely difficult to manage, and impossible to debug.
     

  • RHocking

    Thank you both for your answers!

    I spent a lot of time in other programming languages where I used to solve almost all problems using arrays. After the comment from Alex I looked into the cursors... and I found that they are indeed a very powerful alternative to arrays, so perhaps I'll just use cursors instead. One question remains for me however: you say they are in-memory like tables, but is using them not much slower then using arrays

    But I still can't figure out how to call the procedure asdf using the class variable Arr. I did know I had to use a call by reference but the problem was that I can't put an @ in front of 'this.Arr' because the compiler will complain.
    Like this:
       asdf(@this.Arr, "blah blah")

    I have a function in my class that merges two multidimensional arrays and i just can't find a way to pass the array as an argument. There must be a way :)

  • digitallyskilled01

    Yes it's impossible to do a call by reference that has the prefix "this.".

    acopy(this.aArray, laSomeArray)

    and pass laSomeArray by reference. You might also handle it in your code and if a parameter is not passed use this.aRecs instead. 

    Don't get into macro substitution much. It's something abused frequently.

  • kareddy

    1) You must pass arrays by Reference not by Value. You do this by prepending a "@" to the array name. ( MyFunction(@MyArray) )

    See: http://fox.wikis.com/wc.dll Wiki~PassingArrays

    2) Not directly. You and copy arrays ( with ACOPY() ) or insert array elements ( with AINS() ).

    See:
    http://msdn.microsoft.com/library/default.asp url=/library/en-us/dv_foxhelp9/html/4cfd7044-d4e6-46ee-a6f0-98b5c8d8ffca.asp frame=true

    You could make it easier by converting the array to a cursor (or table) and then joining both arrays in the table, then copying to an array.

    Check the help for:
    APPEND FROM ARRAY
    http://msdn.microsoft.com/library/default.asp url=/library/en-us/dv_foxhelp9/html/5b11bd53-12f9-4727-9ae3-f5a7d3d21274.asp frame=true

    COPY TO ARRAY
    http://msdn.microsoft.com/library/default.asp url=/library/en-us/dv_foxhelp9/html/977adad9-d33e-4f01-8f63-244fd066d832.asp frame=true

    and SELECT (SQL) command that can also copy to arrays.

    3) By Reference

    HTH


  • Paszt

    1) It's capable of doing so for class member arrays. See RETURN in help.
    2) Indirectly with Acopy(),Ains()..
    3) Indirectly. First you need to acopy() it to an array and pass that by reference

    ie:

    [code]

    o = CREATEOBJECT('myClass')

    LOCAL laRecs1[1], laRecs2[1]

    SELECT * FROM customer WHERE .f. INTO CURSOR crsShow readwrite

    USE IN 'customer'

    laRecs1 = o.GetRecsIntoArray("customer","cust_id between 'B' and 'C'")

    APPEND FROM ARRAY laRecs1

    BROWSE TITLE "laRecs1 content"

    zap

    laRecs2 = o.GetRecsIntoArray("customer","cust_id between 'F' and 'G'")

    APPEND FROM ARRAY laRecs2

    BROWSE TITLE "laRecs2 content"

    zap

    o.MergeArray(@laRecs1,@laRecs2)

    APPEND FROM ARRAY laRecs1

    BROWSE TITLE "Merged content"

    ZAP

    APPEND FROM ARRAY o.aRecs

    BROWSE TITLE "Class aRecs content"

    USE

    Define Class myClass As Session

    DataSession = 2

    Dimension aRecs[1]

    Procedure GetRecsIntoArray(tcFrom,tcFilter)

    If Empty(m.tcFilter)

    Select * From (m.tcFrom) Into Array This.aRecs

    Else

    Select * From (m.tcFrom) Where &tcFilter Into Array This.aRecs

    Endif

    Return @This.aRecs

    Endproc

    Procedure MergeArray(taRecords1, taRecords2)

    Local lnPosToStartCopy

    lnPosToStartCopy = Alen(taRecords1)+1

    Dimension taRecords1[ALEN(taRecords1,1)+ALEN(taRecords2,1),ALEN(taRecords1,2)]

    Acopy(taRecords2,taRecords1,1,-1,m.lnPosToStartCopy)

    ENDPROC

    Enddefine

    [/code]


     


  • Paras Dhawan

    >>It is impossible to pass a property by reference. But it is not very obvious to me, since I'm new to foxpro and in some other programming languages it is possible to pass a property by reference.

    Ah, but that is because the other languages you refer to do not implement a strong containership model. VFP does.

    But in the examples you show, the function is part of the same class anyway. In that case you do not NEED to pass anything. All properties defined in a strong containership environment are automatically visible to all member methods. So you can do this:

    DEFINE CLASS cTest AS session
      var1 = 0

    FUNCTION ctest()
      This.Var1 = 12345
      This.DisplayVar()
      This.Var1 && 7890
    ENDFUNC

    FUNCTION displayvar()
      This.Var1  && 12345
      This.Var1 = 7890
      RETURN
    ENDFUNC

    ENDDEFINE

    Array Properties can be handled directly as well - providing that they are members of the class, or of a parent class (no multiple inheritance in VFP!).  For details see "Protecting and Hiding Class Members" in the VFP Help file.


  • [noob questions] Arrays..