Basic mistreats Function name in Function body (sometimes)

Inside a function, the function name is the return value and behaves as a Local Variable …

Except sometimes it doesn’t. WTF?
(and I can’t see any way to attach the example code, so here it is):

REM	*****  BASIC  *****
Option Explicit

'''	Using the Function Name as a Local Variable works ...

Function bValidate() as boolean
	bValidate		= ThisComponent.supportsService("com.sun.star.sheet.SpreadsheetDocument")
	If NOT bValidate Then
		MsgBox "This macro works only on a spreadsheet"
	End If
End Function

Function bActivateSheet(ByVal sName as string) as boolean
	bActivateSheet	= bValidate()
''' Perfectly okay to use Function Name as Local Variable in 'If' statement
	If bActivateSheet Then
		ThisComponent.getCurrentController().setActiveSheet( _
				ThisComponent.getSheets().getByName(sName))
	End If
End Function

'''	BUT ONLY SOMETIMES
''' And I didn't care to spend any more hours tracking down whether it is an 
'''	issue involving an object or whether it is a syntax error

Function oCopySheet(ByVal sName as string, ByVal sTemp as string)
	dim	oController		as object,	oSheets			as object

	oController			= ThisComponent.getCurrentController()
	oSheets				= ThisComponent.getSheets()
	oSheets.copyByName(sName, sTemp, 32767)
	oCopySheet			= oSheets.getByName(sTemp)
	''' Stick a MsgBox right here and you can find out it is recursing
	''' ... and guess what I was doing ...

	''' One or more of these RECURSE rather than recognizing the Function Name as a Local Variable
	'''	and give the wonderfully useless runtime error message "Argument not optional"
	'''	Neither uses a function call SYNTAX
	oController.setActiveSheet(oCopySheet)
	oCopySheet.Unprotect("")
End Function

Sub TestActivate
	If bActivate(ThisComponent.getCurrentController().getActiveSheet().getName()) Then
		MsgBox "Redundantly Activated Active Sheet"
	Else
		MsgBox	"This won't happen unless you are not on a spreadsheet"
	End If
End Sub

Sub TestCopy
	oCopySheet("Sheet1", "SheetCopy")
End Sub

Sorry, I forgot to give its name rank and serial number:
LibreOffice 7.5…2 50(Build:2)
about:
Version: 7.5.6.2 (X86_64)
Environment: 8 threads; Linux 5.18

Ubuntu package version: 4.7.5.6_rc2-0ubuntu0.20.04.1-lo1
Calc: threaded

I think, the function will be called again (recursively), when you use its name in a command inside the function.

Use a temporary name (for example “TheResult” ) for usage inside the function, and at the end of the function pass the value to return it:

bValidate = TheResult

1 Like

Indeed, there is an inconsistency.

I would also expect the recursion where @Zizi64 mentioned. But the fact is - the recursion does not happen there. Yet, it happens in oCopySheet.Unprotect.

I think we need to review and sanitize the rules used there - so please file a bug report.

EDIT: tdf#150491. Lol - it was me who filed that already :wink:

3 Likes

@bValidate:
It is very questionable to put only one Assignment into the function mixed up with the msgbox, IMO this kind of function should be removed

@bActivateSheet

sub bActivateSheet(ByVal sName as string) as boolean
    doc = thisComponent
    If doc.supportsService("com.sun.star.sheet.SpreadsheetDocument") Then
        doc.getCurrentController().setActiveSheet( doc.getSheets().getByName(sName))
	End If
End Sub

mikekangaski -
Thank you, except your bug report focuses on VBA; there is no VBA history here.
I suspect VBA may require a function call syntax [function()] to distinguish function calls from return value reference (TL;DR). This problem exists from poor syntax or inconsistent choices by the compiler, and/or undocumented semantics.
If no one can point us to any documentation or simple rule, I will probably get around to filing a bug report when I have time, in a few months.


And if someone else (Mike?) files a bug report or updates/expands yours, it should be noted that the loss of many hours of work was because the error is reported at runtime, in the recursed instance of the function as it reaches for an unavailable argument. A function/sub declares a prototype; it would be nice if the compiler caught it at compile time and declared the error at the incorrect call, rather than waiting until runtime and missing arguments. It would have made the hours into minutes or seconds…
And, of course, correct documentation is a Good Thing.

karolus -
It is EXCEEDINGLY questionable to look at code which has been simplified and minimized at some effort, to show a specific problem in its bare form, and then reply “That’s not how you should code”.
If we were to be discussing coding form, why would one execute an operation that might fail and not return any status?
Why should the response (MsgBox on failure and status returned) be replicated multiple places throughout the 1000+ lines of original code? Do you think you could consistently deliver the same error MsgBox consistently each of the ten or fifteen times?
Please note your “rewritten and improved” sub does not do the same as the original function did. One might reference Chesterton’s fence …

This is a discussion to no avail - and it seems the questioner didn’t read my answer.
The central point is that LibreOffice Basic isn’t VBA.
E.g. it does not allow to use the function name like a local variable. VBA does.

Lupp -
Again, yes it does, as demonstrated in the first two functions, which successfully used the function name as a local variable. No documentation that I can find speaks to the question at hand.
VBA has nothing to do with it. LHS has nothing to do with it.

The central point is that there is INCONSISTENT behavior by the compiler.

And I read your response (non-answer) and specifically responded to each statement, one, two,three. The fact you did not like the responses do not invalidate them.

While “the loss of many hours” is irrelevant to a bug report (no emotions in bug tracker please, just the data that helps understand the problem), the important point is that this problem is different (even if a bit related), and should be filed separately. One issue for one problem please.

No it doesnt, the assignment to $FUNCTIONNAME is equal to return the assignment a local name doesnt exist.
inside a sub the assingment to $NAME_OF_SUB is simply a local symbol of the same Name as the Sub itself.

function i_am_a_function()
	i_am_a_function = "This is the return from Function"
end function

sub i_am_a_sub()
	i_am_a_sub = "sorry I am a local variable"
end sub

Sub Main
    on Error resume next
     msgbox( "calling function: " & i_am_a_function())
     msgbox("calling sub:   "  & i_am_a_sub())     
End Sub

Wrong. Its usage calls the function (or Sub) recursively.
Only as the left part of an assignment the function name can be used as if a variable.
If you want to have a (preliminary) return variable, you need to create one under its own name.

Lupp -
Wrong on the wrong, as demonstrated, and I had tested with the bValidate and then bActiveSheet functions to determine that, in THAT case, it did indeed behave as a local variable (forgetting that LO Basic allows sloppy sub/function call syntax without the parentheses).
The expression in an IF statement is a RHS, not LHS, so that theory is also incorrect.
Nor is it a preliminary return value - that works fine as expected (and documented) - set the preliminary value and change it later as needed. This is using the return value as a local variable, as in bValidate and bActivateSheet, but inconsistently not in oCopySheet.

Yes, a simple solution is to never use the Function name as a Local Variable - an it would be a Good Idea if that were to be DOCUMENTED (even if it were documented as inconsistent and therefore unpredictably unsafe).

Good and complete specification together with clear and complete documentation is of course desirable.
I don’t think there are many examples in the IT world that leave nothing to be desired insofar. As for LibreOffice, I would mainly like to have more detailed documentation and additional help for finding possible solutions as far as the API is concerned.
Basic itself is often a useful tool to make the API usable without much overhead. However, unlike VBA for MS Office components, it is not an essential part of the software. Other programming languages can also build bridges to the LibO API.
One may wish for something, but I doubt if the thesis that an actually illegal construct MUST lead to a reported error is respected by other software generally.

Concerning this dispute: I used LibO Basic for years now mainly as a short and wide bridge to the API. Without searching for respective documentation I took it as a matter of fact that a function name was not allowed to also be used as a local variable. The issue you brought up here simply didn’t occur to me.

You may report the problem as a bug, of course. You surely know the URL to use.

There is an issue/bug, what is reported now.
.
And there is a very easy workaround: DO NOT USE the name of the function/sub as a local variable inside the function/sub.
.
Use an another local/temporarly variable instead - as I suggested above.
Then you will not lose time when the trying if YOUR method works or not work actually in the StarBasic + LO API…