What is the difference between #Call & #Insert, apart from NoIndent they look identical

So when looking at the help documentation for #Call and #Insert, apart from #Insert having the extra NoIndent attribute, they look identical, but they are not and the help docs dont elucidate their differences.

So does anyone know what their differences are?

TIA

#INSERT was the original, and always injected code at the current indent position. That’s why it has the NOINDENT option.

#CALL was added later, and is essentially the same as #INSERT,NOINDENT.

So why was #CALL added? It’s considered a convention now that #INSERT should be used to denote the generation of code by the referenced #GROUP, whereas #CALL is used only for execution of template code.

I find that distinction helpful, as I want the intent of my code to be as readable and clear as possible. Regardless, you can use both as you see fit.

Isnt that supposed to be the other way around?

So I cant use #Call inside template prompts but I can use inserts

sheet,Hscroll
#Tab(‘&1 Overview’)
#Display(‘’)
#Button(‘Overview’),At(,175,12)
#Insert(%grpOverview)
#EndButton
#Button(‘Explorer Tools’),At(,175,12)
#Insert(%grpExplorerTools)
#EndButton
#EndTab
#Tab(‘&2 Include Files’)
#Insert(%grpTab2includefiles)
#EndTab
#Tab(‘&3 Inside Map Include Filenames’)
#Insert(%grpTab3InsideMapIncludeFiles)
#EndTab
#Tab(‘&4 Inside Map Module Prototypes’)
#Insert(%grpTab4InsideMapModulePrototypes)
#EndTab
#EndSheet

If I swap the above inserts with #Call the appgen complains.

As I mentioned, #INSERT existed first, so it’s used more often than it needs to be. I still use #INSERT within the #PROMPT area, as you’re suggesting. In a sense, I consider it as “generation of template code”, rather than “generation of Clarion code”. :wink:

Where I use #CALL is when I want to execute some template logic, and the called logic will not directly generate any code.

Don’t forget that there’s a third way to invoke a group–by using it in a template expression:

#SET(%MyVar, %MyGroup())

Alternatively, you could do that same thing using #CALL:

#CALL(%MyGroup), %MyVar

If your group had parameters, the alternate syntaxes vary accordingly:

#SET(%MyVar, %MyGroup(%Parm1, %Parm2))
#CALL(%MyGroup, %Parm1, %Parm2), %MyVar

I don’t believe you can use #INSERT to capture a return value.

and a sort of fourth way because it is an expression is inside ,WHERE()

#Tab('&1 Include Files'), Where(%DTR(%Tabs,'#Tab(''&1 Include Files'')'))

where %DTR is a #group that takes the parameters and sends them off to debugview and Returns %true

#Procedure(ClarionProc,'Clarion Procedure')
#Restrict,Where(%grpFirstProcedureIsTrue() )                                    #Call(%DT,%T,'#Restrict,Where(%grpFirstProcedureIsTrue()['& %grpFirstProcedureIsTrue() &'] )')
    #Accept                                                                     #Call(%DT,%T,'#Accept')
#EndRestrict                                                                    #Call(%DT,%T,'#EndRestrict')

In the above example the %DT group does not Return %True but the #Group %grpFirstProcedureIsTrue() does Return %True

I’ve been having to try code to see what is complained about and not, in the same way a Fuzzer would do this.

The Help shows #INSERT can return a value, but I searched the shipping templates and did not find any. I would guess it calls the same template library “thing” as #CALL so would work identically except NONDENT default.

Another way to get a kind of return value is passed by address *%Var

And when a CSV approach perhaps encapsulated with double quotes is employed for clarity to a single parameter Cstring passed by address, one starts to question if the single parameter is a single parameter for other parts of the template language like #RunDll.

#Group(%grpParseEquate,*%pIO1,*%pIO2)
#! This calls a procedure which passes a csv string back which is parsed into the two vars from
#! "WhenAccepted( %grpParseEquate(%EquateName,%EquateValue)"
#!
#Declare(%csvString)
#Declare(%commaPos)
#Declare(%csvStringLen)
#Set(%csvString,clip(%pIO1) &','& clip(%pIO2))
#RUNDLL('myrundll.dll', 'PROC3@FRsc',%csvString), release, win32
#Set(%commaPos,instring(',',%csvString,1,1) )
#Set(%csvStringLen,Len(Clip(%csvString)) )
#Set(%pIO1,Sub(%csvString,1,%commaPos-1) )
#Set(%pIO2,Sub(%csvString,%commaPos+1,%csvString - (%commaPos + 1) ) )