Using a process and functions
Using a process and functions
Currently we are using functions as a means of inserting data into a list in the function to reference that data from other reusable parts and forms. Just want clarity if this process is good practice or not.
-
René Houba
- Posts: 220
- Joined: Thu Nov 26, 2015 7:03 am
Re: Using a process and functions
Hi Jarred,
I don't understand what you mean with that.
Can you explain more in detail what you are doing and try to do?
Kind regards,
René
I don't understand what you mean with that.
Can you explain more in detail what you are doing and try to do?
Kind regards,
René
Re: Using a process and functions
Hi Rene
Basically I am storing information into a local list, then I am passing that list to a list in a function, which we then call that function to read the information on another reusable part or form.
This code might help:
So this code assigns values into a list, then we send that data over to a function that also has the same list name:
Mthroutine Name(SKUTRANSACT) Access(*PUBLIC)
Clr_List Named(#List_SKUInfo)
Change Field(#List_SKUInfo) To(*NULL)
#CDX := #VAR_SKU.Value
#CDXQUANTI := #VAR_QTY.Value
#CARDEXDIS := #VAR_DISC.Value
#VAR_LNUM := #gdSKU.Entries + 1
Add_Entry To_List(#List_SKUInfo)
#STD_CODEL := "WRITE"
Exchange Fields(#STD_CODEL #List_SKUInfo)
Call Process(*DIRECT) Function(FUN_GRD) Pass_Lst(#List_SKUInfo)
Signal Event(SETTRANSACT)
Endroutine
Our function code:
Function Options(*DIRECT *HEAVYUSAGE) Rcv_List(#List_SKUInfo)
Def_List Name(#List_SKUInfo) Fields(#SALETYPE #CDX #CXLBSE #CDXQUANTI #CXVP #CardexDiscount #AccountList #TURNOVERL #VAT_SKU #VAR_LNUM) Type(*WORKING)
Case (#STD_CODEL)
When ('= CLEAR')
Clr_List Named(#List_SKUInfo)
Change Field(#List_SKUInfo) To(*NULL)
When ('= WRITE')
Add_Entry To_List(#List_SKUInfo)
Endcase
Return
This code then reads that function list, adds it to its own local list where we then browse through the information and use it:
Evtroutine Handling(#POS_MAIN.SETTRANSACT)
Clr_List Named(#List_SKUInfo)
Change Field(#List_SKUInfo) To(*NULL)
Call Process(*DIRECT) Function(FUN_GRD) Pass_Lst(#List_SKUInfo)
Selectlist Named(#List_SKUInfo)
Endselect
#POSCONN.getvalue From("WSLYN") value(#STD_INT) Index(#VAR_LNUM)
#POSCONN.getvalue From("WSBESKR") value(#CXLBSE) Index(#VAR_LNUM)
If Cond((#STD_INT = 0) *Or (#CXLBSE = ''))
#POSCONN.setvalue InField('WSVELD') Value(#CDX) Index(#VAR_LNUM)
#POSCONN.setvalue InField('WSHOEV') Value(#CDXQUANTI) Index(#VAR_LNUM)
#POSCONN.setvalue InField('WSKORTP') Value(#CARDEXDIS) Index(#VAR_LNUM)
#POSCONN.sendkey Key(#POSCONN.KeyEnter)
Endif
Endroutine
Basically I am storing information into a local list, then I am passing that list to a list in a function, which we then call that function to read the information on another reusable part or form.
This code might help:
So this code assigns values into a list, then we send that data over to a function that also has the same list name:
Mthroutine Name(SKUTRANSACT) Access(*PUBLIC)
Clr_List Named(#List_SKUInfo)
Change Field(#List_SKUInfo) To(*NULL)
#CDX := #VAR_SKU.Value
#CDXQUANTI := #VAR_QTY.Value
#CARDEXDIS := #VAR_DISC.Value
#VAR_LNUM := #gdSKU.Entries + 1
Add_Entry To_List(#List_SKUInfo)
#STD_CODEL := "WRITE"
Exchange Fields(#STD_CODEL #List_SKUInfo)
Call Process(*DIRECT) Function(FUN_GRD) Pass_Lst(#List_SKUInfo)
Signal Event(SETTRANSACT)
Endroutine
Our function code:
Function Options(*DIRECT *HEAVYUSAGE) Rcv_List(#List_SKUInfo)
Def_List Name(#List_SKUInfo) Fields(#SALETYPE #CDX #CXLBSE #CDXQUANTI #CXVP #CardexDiscount #AccountList #TURNOVERL #VAT_SKU #VAR_LNUM) Type(*WORKING)
Case (#STD_CODEL)
When ('= CLEAR')
Clr_List Named(#List_SKUInfo)
Change Field(#List_SKUInfo) To(*NULL)
When ('= WRITE')
Add_Entry To_List(#List_SKUInfo)
Endcase
Return
This code then reads that function list, adds it to its own local list where we then browse through the information and use it:
Evtroutine Handling(#POS_MAIN.SETTRANSACT)
Clr_List Named(#List_SKUInfo)
Change Field(#List_SKUInfo) To(*NULL)
Call Process(*DIRECT) Function(FUN_GRD) Pass_Lst(#List_SKUInfo)
Selectlist Named(#List_SKUInfo)
Endselect
#POSCONN.getvalue From("WSLYN") value(#STD_INT) Index(#VAR_LNUM)
#POSCONN.getvalue From("WSBESKR") value(#CXLBSE) Index(#VAR_LNUM)
If Cond((#STD_INT = 0) *Or (#CXLBSE = ''))
#POSCONN.setvalue InField('WSVELD') Value(#CDX) Index(#VAR_LNUM)
#POSCONN.setvalue InField('WSHOEV') Value(#CDXQUANTI) Index(#VAR_LNUM)
#POSCONN.setvalue InField('WSKORTP') Value(#CARDEXDIS) Index(#VAR_LNUM)
#POSCONN.sendkey Key(#POSCONN.KeyEnter)
Endif
Endroutine
Re: Using a process and functions
I think passing a list is the fastest way to do it. But if you want to stay in all RP's you can pass collections instead.
Art
Art
Art Tostaine
-
Tim McEntee
- Posts: 57
- Joined: Thu May 26, 2016 8:46 am
Re: Using a process and functions
Speed.
Using collections to manipulate sets of data is slow in C++. ie VL. (On the browser using js in VL/Web it is fast.)
So if your list of data is small you could use either. With larger data sets you would use a list.
You would use a collection if you are passing the data between RPs. The method parameter pass by reference.
You can manipulate lists within a RP. I would separate the list into a function if I am calling the code from more than one place.
You can't use a function to pass a list from one one RP to another.
Using collections to manipulate sets of data is slow in C++. ie VL. (On the browser using js in VL/Web it is fast.)
So if your list of data is small you could use either. With larger data sets you would use a list.
You would use a collection if you are passing the data between RPs. The method parameter pass by reference.
You can manipulate lists within a RP. I would separate the list into a function if I am calling the code from more than one place.
You can't use a function to pass a list from one one RP to another.
Re: Using a process and functions
So currently we are using functions with lists to pass data from one reusable part to another (that being said we are passing from a reusable part to our Screen wrapper reusable part) which currently works in design, when you say "You can't use a function to pass a list from one RP to another.", could you please clarify what you mean by that, just want to make sure that it works when we deploy it?
-
Tim McEntee
- Posts: 57
- Joined: Thu May 26, 2016 8:46 am
Re: Using a process and functions
A reusable part calls a function, passing a list into the function. The function does some work, then ends and returns to the Reusable part. That instance of the function dies and so does the list inside the function. The list returned to the reusable part remains.
If you call the function again from the same reusable or another reusable a new instance of the function is created. The list will be set because you are passing it on the pass_list parameter of the call from the calling reusable part.
Reusable part A calls function C passing a list - builds data - returns 5 entries. Function C dies.
Reuasable Part A calls Reusable part B without passing the list, the list in RP B is empty and then it calls Function C - the list is empty on the call and Function C acts on the empty list.
If you call a reusable part from another reusable part (or from a function) you cannot directly pass a list to the called reusable part.
You can use the BIF save_list and restore_saved_list - which is a technique used for submitting batch jobs.
You can copy the list to a collection and pass the collection into the reusable part on the method parameter pass by reference.
Or are you using *heavyusage on the function to set the function into remembering the variables.
If you call the function again from the same reusable or another reusable a new instance of the function is created. The list will be set because you are passing it on the pass_list parameter of the call from the calling reusable part.
Reusable part A calls function C passing a list - builds data - returns 5 entries. Function C dies.
Reuasable Part A calls Reusable part B without passing the list, the list in RP B is empty and then it calls Function C - the list is empty on the call and Function C acts on the empty list.
If you call a reusable part from another reusable part (or from a function) you cannot directly pass a list to the called reusable part.
You can use the BIF save_list and restore_saved_list - which is a technique used for submitting batch jobs.
You can copy the list to a collection and pass the collection into the reusable part on the method parameter pass by reference.
Or are you using *heavyusage on the function to set the function into remembering the variables.
Re: Using a process and functions
We are using *heavyusage on our function. Not sure what drawback that might have? We aren't sending huge amounts of data and at certain points we are clearing the list within the function.
Is this best practice? Sorry for all the questions, but you've been really helpful, thank you!
Is this best practice? Sorry for all the questions, but you've been really helpful, thank you!
-
Tim McEntee
- Posts: 57
- Joined: Thu May 26, 2016 8:46 am
Re: Using a process and functions
The intention of *heavyusage was for long running jobs that called a function many, many times. There is a high overhead in creating and destroying function variables a million times. Keeping the variables in memory would improve performance dramatically.
What you are doing with *heavyusage is not what it is intended for. I have not seen it used that way before.
But that is not to say that you shouldn't use it. It looks like a novel way to transfer a list from one reusable part to another. I might use it if I was transferring large lists.
What you need to be aware of is that when Program A calls your Heavyusage function B, then program A ends. Function B stays in memory as a sort of orphan. When Program C then calls function B any variables in function B will still be there and these values can accessed by Program C's usage of Function B.
If you are going to use this then I would keep the transfer close and specific. The source of truth for the list data should not be the function.
By keeping it close I mean the seeding call from reusable A happens and then resuable C accesses the function straight away. If you store then assume the list is still there after an hour, or all day it may have been updated with another call to that function by reusable A.
By keeping it specific I mean there is only one version of the function active in a session, so if you make the function generic then if reusable D is another program that seeds the list, then reusable B could access the function thinking that reusable A did the seeding. And how do you work out what went wrong.
What you are doing with *heavyusage is not what it is intended for. I have not seen it used that way before.
But that is not to say that you shouldn't use it. It looks like a novel way to transfer a list from one reusable part to another. I might use it if I was transferring large lists.
What you need to be aware of is that when Program A calls your Heavyusage function B, then program A ends. Function B stays in memory as a sort of orphan. When Program C then calls function B any variables in function B will still be there and these values can accessed by Program C's usage of Function B.
If you are going to use this then I would keep the transfer close and specific. The source of truth for the list data should not be the function.
By keeping it close I mean the seeding call from reusable A happens and then resuable C accesses the function straight away. If you store then assume the list is still there after an hour, or all day it may have been updated with another call to that function by reusable A.
By keeping it specific I mean there is only one version of the function active in a session, so if you make the function generic then if reusable D is another program that seeds the list, then reusable B could access the function thinking that reusable A did the seeding. And how do you work out what went wrong.