Roku Developer Program

Join our online forum to talk to Roku developers and fellow channel creators. Ask questions, share tips with the community, and find helpful resources.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
EnTerr
Roku Guru

Precedence: local vs global function?

What is the precedence (lookup order) when calling a function?

For example say i have defined function exec() in global scope and then inside another function or method i do:
exec = function(): return "bar": end function
exec()
Which function should be called?

I did a quick tests and seems that global one prevails but this is counter-intuitive. It is customary that binding be resolved to the most local/domestic definition - which in this case is the local assignment of anonymous fn. Doing it the other way risks unpredictable results - say as shown i define and use locally some worker function. All is well while there is no global exec() - but one day somebody adds exec() to a library i use and boom - weird things happen.
0 Kudos
10 REPLIES 10
RokuMarkn
Visitor

Re: Precedence: local vs global function?

This is just a special case of the general scoping issue that global function names cannot be hidden by local variables. It would be the same if your local exec were just an int or a string. I actually just submitted an enhancement request on this issue today.

--Mark
0 Kudos
EnTerr
Roku Guru

Re: Precedence: local vs global function?

"RokuMarkn" wrote:
This is just a special case of the general scoping issue that global function names cannot be hidden by local variables. It would be the same if your local exec were just an int or a string. I actually just submitted an enhancement request on this issue today.

Indeed:
BrightScript Debugger> ? exec              'global user fn
<bsTypedValue: Function>
BrightScript Debugger> exec = "ex exec" 'no complaint
BrightScript Debugger> ? exec 'but no change either
<bsTypedValue: Function>
Such behavior is on the strange side of things.

PS. talk about synchronicity :idea:
0 Kudos
EnTerr
Roku Guru

Re: Precedence: local vs global function?

RokuMarkn -
what was the word on this issue eventually?
Was it postulated that global functions will always trump locals?

This week i ran into it again.
0 Kudos
RokuKC
Roku Employee
Roku Employee

Re: Precedence: local vs global function?

Synchronicity again, as I've recently been looking into the topic of scope fixes and more well defined behavior. 8-)

We don't want built-in global functions to be overridable, as that can lead to security and integration issues.
(Where I'm referring to integration as combination of BrightScript from multiple providers, for example).

My preference would be to make it a compile error if there is a user-provided function of the same name as a global function or reserved name.
This only refers to top-level functions, of course, and not AA key names of function 'methods' etc.

There may need to be some compatibility nods to let existing code still run (at least in non-strict or non-sideloaded mode).
That would be for cases that are most likely getting by only despite not behaving as the developer intended.
0 Kudos
EnTerr
Roku Guru

Re: Precedence: local vs global function?

@RokuKC -
I let this steep in my head for a while. It's a curious and quite challenging issue. Challenging, because you have to preserve the behavior of big warehouse of existing apps, while replacing some of the plumbing/foundations underneath. RokuCo has done it before, e.g. the type changes in BrightScript3 ^. It's ungrateful job - last year i was thinking how it's easier on the developers of native libraries (on the example of Marmalade SDK), since these get bundled with the binary and later version change will only affect future builds of the app - unlike with upstream interpreter or "magic libraries"^^ like RAF which can suddenly and mindlessly "pull the rug from under" the app.

Libraries! Your point of view is interesting - i never thought about protecting library from interference by the client code. But IMHO even more important is the other direction - protect app code from getting screwed by library symbols.

Here is an example of such screw-up: viewtopic.php?f=34&t=75717 - what happened is that in a firmware update, a library suddenly defined a function already defined/used by the app and thus killed the channel! "SUB or FUNCTION defined twice. (compile error &had)" - that is a hard error with no way out of it, it leaves a published channel dead in the water. Back then, the specific issue was band-aided by prefixing all functions inside "v30/bslDefender.brs" to start with "df"

Like i pointed then, it's safer for the Co to add a new function to ifGlobal than to a "magic library", since paradoxically the latter may kill working apps. So i think some scoping for "Library" is in order - i.e. all functions inside included library get resolved to that context only and won't see later defined user symbols (that's to address your concern) and re-definition only causes warning and no fatal error. I'd love to be more constructive but you have removed viewing pcode from the console <dirty-look/>...

(^) i might be the only person outside the Co to know there being 6 different internal types of strings in B/S, as exemplified by "a", box("a"), "a"+"b", ["a"][0], ["a"+"b"][0], [box("a")][0]. Seems like a tetanic effort for little payoff. Still, i am in awe.
(^^) by "magic libraries" i mean libraries that may magically update/change themselves beyond developer's control. Which is what, in B/S i think everything included using the "Library" statement?
0 Kudos
EnTerr
Roku Guru

Re: Precedence: local vs global function?

How does the graphical scenes interface exporting relate to this?

I mean if some API for limiting visibility is already there, it can be used here. Hopefully without catching "the XMLs". Like say statement "EXPORTS fn1, fn2, fn3..." at the very end of the file (or beginning but extra work for function-hoisting).

The good news is that (a) the functionality seems to be already available and (b) since there are only what - 3? - BrightScript libraries in the known universe, updating them is trivial with no effect to the existing 3k channels.

PS. if expanding the list of reserved words is a concern, then can re-use an existing one or use pragmas

'
' LIBRARY foobar.brs
'
function expo_fun(...)
....
end function

DIM expo_fun
@EXPORTS expo_fun
'@EXPORTS expo_fun
The last one won't trip badly written editor plugins but then again, writing LIBRARY is internal to the Co
0 Kudos
EnTerr
Roku Guru

Re: Precedence: local vs global function?

Today i find myself again needing to override global user function (i.e. something i wrote, "function foo(): ...") with a local one (i.e. "foo = function(): ...") while in the current/local scope - and i still can't! Is there any movement in the "local vs global" fight?

One could argue that "normally" this is something that shouldn't be needed and such contortions should even be suppressed. There is nothing normal in my situation though - finding that RokuCo has yanked a documented method call out of 7.2 in absolutely unprofessional way, leaving a gaping hole that kills the app:
Member function not found in BrightScript Component or interface. (runtime error &hf4)

I could out-maneuver this pothole if local vars were trumping globals.
0 Kudos
belltown
Roku Guru

Re: Precedence: local vs global function?

"EnTerr" wrote:
RokuCo has yanked a documented method call out of 7.2

What did they yank?
0 Kudos
EnTerr
Roku Guru

Re: Precedence: local vs global function?

"belltown" wrote:
"EnTerr" wrote:
RokuCo has yanked a documented method call out of 7.2
What did they yank?

I'd rather not point here the specific call to spare public embarrassment to both the Co. and myself.

Suffice it to say, when i first read the method description in the API, that "raised eyebrows" with me. But then i thought "well, they know better - if they say it's an okay thing to do, then it is" - and used it. I was satisfied it's present in 7.0 and 7.1 but "just in case" it got deprecated/phased-out, i added a guard `if` to protect in case it suddenly started returning `invalid`. Little could i imagine a method "vanish" from the API with no advance warning, no explanation and no stub-ing either!
0 Kudos