Welcome To The Home Of The Visual FoxPro Experts  
home. signup. forum. archives. search. google. articles. downloads. faq. members. weblogs. file info. rss.
 From: Tony Vignone
  Where is Tony Vignone?
 St Augustine
 Florida - United States
 Tony Vignone
 To: Tony Vignone
  Where is Tony Vignone?
 St Augustine
 Florida - United States
 Tony Vignone
 Tags
Subject: RE: Passing arrays to procedures
Thread ID: 268401 Message ID: 268850 # Views: 29 # Ratings: 0
Version: Visual FoxPro 9 Category: General VFP Topics
Date: Thursday, July 15, 2010 3:06:02 AM         
   


> Is there any way to pass a form array to a form procedure by reference?
> I have several arrays in the form and a one common procedure.
>
> Passing Thisform.myArray by value passes only the first element of the array
> Passing @Thisform.myArray by reference is illegal. (VFP may be great for database but is a poor programming language.)
>
> I know I can place the called procedure in a program and use a DO WITH Thisform.myArray
> but I would like the procedure to be in the form.
>
> And yes, I can also write a procedure for each array (Yuk.)
>
> Tony

I am responding to myself after reading many responses.

I realize that most of you did not appreciate my assessment of VFP. I'm an old timer who has coded in many high and low level languages since the 1960's. In my opinion, a good language is one that handles both arrays and relational databases equally well, and of course an Object Oriented Language. VFP handles relations database the best I have seen so far and it is why I use it. But some solutions require arrays such as for proven published algorithms written with arrays (vectors and matrices). You lose the proof if you rewrite them with cursors. I also have a library of math functions using vectors and matrices, real and complex numbers. To simulate the math used in Quantum Mechanics, say, using the Hermitian operator on a vector, needs arrays. Ok, I could use a different language for this, but I prefer to stick with one. So my goal is to extend the language to arrays.

To correct this deficiency in arrays, I have a written over the past 10 years a library of array functions some of which mimic relation databases. This is because algorithms using relational tables can also be proved correct with mathematical set theory (tables are sets that are combined with union, intersection, etc). Here is an example of combining a group of matrices and vectors (1 and 2 dimen arrays) in a similar way as combining a group of relational tables. You will notice that I simply load the matrices into cursors and do an SQL-Select and return the resulting cursor as an array. Now a good language would have provided a built-in function. This function is a new one that I have added to my array library and may need some more debugging and more error checking. Please, no comment to my coding of variables - we have had a long discussion on this topic before. Anyway it doesn't matter since this code is in a DLL. This is the test code. The real code references internal procedures with This.proc; example, This.cpos(clause," )",p).


PROCEDURE aSelect(cSelectClause,lKeepCursorOpen)


* USAGE: aSelect( cClause [,lKeepOpen] )

* cSelectClause is the same as the VFP SQL Select:

* SELECT Select_List
* FROM Table_List
* [WITH (BUFFERING = lExpr)]
* [WHERE Conditions]
* [GROUP BY Column_List]
* [UNION Clause]
* [HAVING Conditions]
* [ORDER BY Column_List]
* [INTO Clause | TO Clause ]
* [Additional_Display_Options]

* with the following differences:
* 1. Private (or public) array names instead of table names.
* 2. Column numbers instead of field names.
* 3. INTO ARRAY clause is required.
* 4. TO clause is not allowed.
* 5. No display options
* 6. No BUFFERING clause

* SELECT Select_ColumnNumber_List
* FROM Array_List
* INTO ARRAY Clause
* [WHERE Conditions]
* [GROUP BY ColumnNumber_List]
* [UNION Clause]
* [HAVING Conditions]
* [ORDER BY ColumnNumber_List]

* keepCursorOpen: Make True if INTO cursor is to remain open
* The cursor fields are memos with the contents of each array element.
* Each element value is preceded by its type followed by the
* character value of the element. These are the only types allowed so far.
* Examples: C abc, N 123.45, D 05/06/2010, L FALSE

	if pcount() = 1 then
		lKeepCursorOpen = .F.
	endif	

	local i,j,k,p,q,r,clause,arrlist,intoArr,cCol
	local array arrname(1)
*		subscripts i,j,k
*		pointer into string p,q,r
*		cursors created are array names
*		cursor fields are M1_, M2_,...,Mn_
	clause = lower(cSelectClause)
	
	p = at("from",clause)+5			&& find 'from' array names
	q = cpos(clause," )",p)
	arrlist = substr(clause,p,q-p)
	for i=1 to getwordcount(arrlist,", )")
		dimen arrname(i)
		arrname(i) = getwordnum(arrlist,i,", )")
		MakeCursor(@&arrname(i),arrname(i))
	next	
	
	p = at("into array",clause)+11	&& find into array name
	intoArr = getwordnum(substr(clause,p),1," )")
	MakeCursor(@&intoArr,intoArr)
	i = 1
	
	p = at(".",clause,i)			&& change col numbers to field names
	do while p > 0
		q = cpos(clause," ,)",p)
		cCol = substr(clause,p+1,q-p-1)
		clause = stuff(clause,p+1,q-p-1,"M"+cCol+"_")
		i = i+1
		p = at(".",clause,i)
	enddo
	
	clause = strtran(clause,"array","cursor")
	&clause
	MakeArray(intoArr,@&intoArr)	&& create 'into' array	

	for i=1 to alen(arrname)			&& close 'from' cursors
		use in select(arrname(i))
	next	
	if not lKeepCursorOpen then
		use in select(intoArr)			&& close 'into' cursors
	endif	
		
ENDPROC

*	Supporting Subroutines 

	procedure MakeCursor(parr,pcursor)		&& Make cursor from array
		EXTERNAL array parr
		
		local cCommand
		local array arr(1,1)
		DIMEN arr(alen(parr,1),max(1,alen(parr,2)))
		acopy(parr,arr)
		cCommand = "Create cursor "+pcursor+" (m1_ M"
		for j=2 to alen(arr,2)
			cCommand = cCommand+",m"+trans(j)+"_ M"
		next
		cCommand = cCommand+")"
		&cCommand
		local mName,typ
		for i=1 to alen(arr,1)
			append blank
			for j=1 to alen(arr,2)
				mName = "m.m"+trans(j)+"_"
				typ = vartype(arr(i,j))
				&mName = typ+" "+tvstr(arr(i,j))
			next
			gather memvar memo
		next	
	endproc

	procedure MakeArray(pcursor,parr)		&& Make array from cursor
		EXTERNAL array parr
		
		local i,j,cmemo
		local array arr(1,1)
		DIMEN arr(alen(parr,1),max(1,alen(parr,2)))
		go top
		i = 0
		do while not eof()
			i = i+1
			dimen arr(i,fcount())
			for j=1 to fcount()
				cmemo = eval(field(j))
				do case
				case left(cmemo,1) = "N"
					arr(i,j) = val(trim(substr(cmemo,3)))
				case left(cmemo,1) = "D"
					arr(i,j) = ctod(trim(substr(cmemo,3)))
				case left(cmemo,1) = "L"
					arr(i,j) = iif(trim(substr(cmemo,3))="TRUE",.T.,.F.)
				otherwise		  && "C"
					arr(i,j) = trim(substr(cmemo,3))
				endcase	
			next	   
			skip
		enddo
		if alen(parr,2) = 0 then		&& one dimensional array
			dimen parr(alen(arr))
			acopy(arr,parr)	
		else	
			dimen parr(alen(arr,1),alen(arr,2))
			acopy(arr,parr)	
		endif 
	endproc

	function cpos           && 1st occurance from dels at or after p
	   lparameter ph,dels,p
	   local i
	   if pcount() = 2 then
	      p = 1
	   endif   
	   if p <= 0 then
	      p = 1
	   endif   
	   for i = p to len(ph)
	      if at(substr(ph,i,1),dels,1) > 0 then
	         return i
	      endif   
	   next
	return 0



EXAMPLE:
Note that matread loads the values into the array (This function is not provided here - you will have to use your own code.

private arr1,arr2,arr3
dimen arr1(1),arr2(1,5),arr3(1,3)

matread(@arr1,"aa,bb,cc")
matread(@arr2,"aa,2,3,4,5, aa,22,33,44,55, bb,222,333,444,555")

*arr1 will be  (a one dimensional array is a viewed as a vector (vertical 3 rows, 1 column)"
*   aa
*   bb
*   cc
*arr2 will be
*   aa 2   3   4   5
*   aa 22  33  44  55
*   bb 222 333 444 555

*After the Select, arr3 wil be: 
*   aa 3   4
*   aa 33  44
*   bb 333 444

local SQLSelect
SQLSelect = [;
	SELECT arr1.1,arr2.3,arr2.4 ;
	FROM arr1,arr2 ;
	WHERE arr1.1 = arr2.1 ;
	INTO ARRAY arr3 ;
	]


ENTIRE THREAD

Passing arrays to procedures Posted by Tony Vignone @ 7/11/2010 6:46:56 PM
RE: Passing arrays to procedures Posted by Samir H. @ 7/11/2010 7:15:34 PM
RE: Passing arrays to procedures Posted by Tony Vignone @ 7/12/2010 6:52:53 PM
RE: Passing arrays to procedures Posted by Borislav Borissov @ 7/11/2010 7:19:17 PM
RE: Passing arrays to procedures Posted by Tony Vignone @ 7/12/2010 6:51:23 PM
RE: Passing arrays to procedures Posted by Mike Yearwood @ 7/13/2010 3:38:03 PM
RE: Passing arrays to procedures Posted by Tony Vignone @ 7/14/2010 6:39:43 PM
RE: Passing arrays to procedures Posted by Anil Sharma @ 7/11/2010 7:31:36 PM
RE: Passing arrays to procedures Posted by Tony Vignone @ 7/12/2010 6:55:23 PM
RE: Passing arrays to procedures Posted by Eduard @ 7/11/2010 10:34:31 PM
RE: Passing arrays to procedures Posted by Tony Vignone @ 7/12/2010 7:02:24 PM
RE: Passing arrays to procedures Posted by Samir H. @ 7/12/2010 7:28:19 PM
RE: Passing arrays to procedures Posted by Tony Vignone @ 7/13/2010 3:08:33 AM
RE: Passing arrays to procedures Posted by Samir H. @ 7/13/2010 3:48:58 AM
RE: Passing arrays to procedures Posted by Tony Vignone @ 7/13/2010 4:33:38 AM
RE: Passing arrays to procedures Posted by Tamar Granor @ 7/12/2010 10:48:02 PM
RE: Passing arrays to procedures Posted by Tony Vignone @ 7/13/2010 3:07:39 AM
RE: Passing arrays to procedures Posted by Koen Piller @ 7/12/2010 11:37:18 PM
RE: Passing arrays to procedures Posted by Tony Vignone @ 7/13/2010 3:02:01 AM
RE: Passing arrays to procedures Posted by Koen Piller @ 7/13/2010 4:07:34 PM
RE: Passing arrays to procedures Posted by Samir H. @ 7/13/2010 5:56:25 PM
RE: Passing arrays to procedures Posted by Koen Piller @ 7/13/2010 8:43:23 PM
RE: Passing arrays to procedures Posted by Mike Yearwood @ 7/13/2010 10:36:16 PM
RE: Passing arrays to procedures Posted by Samir H. @ 7/14/2010 4:42:58 AM
RE: Passing arrays to procedures Posted by Mike Yearwood @ 7/14/2010 5:57:12 AM
RE: Passing arrays to procedures Posted by Samir H. @ 7/14/2010 7:22:33 AM
RE: Passing arrays to procedures Posted by Mike Yearwood @ 7/14/2010 7:13:43 PM
RE: Passing arrays to procedures Posted by Koen Piller @ 7/14/2010 10:21:59 AM
RE: Passing arrays to procedures Posted by Tony Vignone @ 7/14/2010 6:59:18 PM
RE: Passing arrays to procedures Posted by tushar @ 7/13/2010 6:02:24 AM
RE: Passing arrays to procedures Posted by Tony Vignone @ 7/14/2010 7:00:41 PM
RE: Passing arrays to procedures Posted by Mike Yearwood @ 7/13/2010 3:39:32 PM
RE: Passing arrays to procedures Posted by Christian Tabligan @ 7/14/2010 4:46:09 AM
RE: Passing arrays to procedures Posted by Samir H. @ 7/14/2010 4:54:22 AM
RE: Passing arrays to procedures Posted by Christian Tabligan @ 7/14/2010 5:48:51 AM
RE: Passing arrays to procedures Posted by Tony Vignone @ 7/15/2010 3:06:02 AM