Is it possible to assign an anonymous function to a global associative array property?

1.1k views Asked by At

New to roku/brightscript development: Is it possible to add an object to the global associative array (accessible by all components), that has a method defined as one of the properties, and call that method?

Main.brs:

function Main()
    init()
end function

function init()    
    screen = createObject("roSGScreen") 
    m.port = createObject("roMessagePort")
    screen.SetMessagePort(m.port)

    scene = screen.CreateScene("MainController")
    screen.show()

    o = {
        getName: function() as string
            return "John"
        end function
    }

    setUpGlobal(screen)
    m.global.addFields({mainMethods: o})        

    while(true)
        msg = wait(0, m.port)
        msgType = type(msg)

        if msgType = "roSGScreenEvent"
            if msg.isScreenClosed() then exit while
        end if    
    end while        
end function

function setUpGlobal(p_screen as Object)
    m.global = p_screen.getGlobalNode()
    m.global.id = "GlobalNode"
end function

.. then in another MainController, after running a task and returning data...

MainController.brs

function init()
    loadConfig()
end function


function loadConfig()
    m.config = createObject("roSGNode", "Configurator")
    m.config.observeField("done", "onConfigLoaded")
    m.config.observeField("fail", "onConfigError")
end function 


function onConfigLoaded()
    print "config loaded: " + m.global.mainMethods.getName()
end function


function onConfigError()
    print "config failed to loaded"
end function

When it hits line 16 of MainController, I get this:

Member function not found in BrightScript Component or interface. (runtime error &hf4) in pkg:/components/MainController.brs(16)

This is just a general test of what can/can't be done so please don't comment on whether this is "good practice" or not. I just want to know if it's possible and if so, what am I missing here? Thanks for any help

3

There are 3 answers

1
Nas Banov On BEST ANSWER

You can have functions as roAssociativeArray values. In fact that is how OO methods are done in BrightScript.

However, you cannot assign functions to fields of a Roku Scene Graph object (roSgNode derivatives)! Either directly or indirectly (nested). It's a limitation of the (current?!) implementation.

You can see list of the field types supported by RSG here https://sdkdocs.roku.com/pages/viewpage.action?pageId=1608549

Yes, it does say to support assocarray and (as of lately) array - but there is a caveat to that! When you assign (or even access) compound objects between threads, a deep copy is made and only the "supported" types make it through - and as you experienced, function is not one of them. All unrecognized data is currently silently dropped, with not even whisper of a warning - so buyer beware.

See https://forums.roku.com/viewtopic.php?f=34&t=96955&p=541965#p541965 for more. Feel invited to add your voice in Roku's developer forum, requesting support of function type by RSG - they tend to listen if enough people complain.

1
Eugene Smoliy On

You can't pass functions in node's fields. Only data. If you check m.global.mainMethods.getName value right after setting it, it will be invalid.

0
Jonny On

I think you can do this with anonymous functions.

https://developer.roku.com/en-gb/docs/references/brightscript/language/program-statements.md#anonymous-functions

q = { 
    starring : Function(o, e)
        str = e.GetBody()
        print "Starring: " + str 
        toks = box(str).tokenize(",")
        For Each act In tok
            actx = box(act).trim()
            If actx <> "" Then
                print "Actor: [" + actx + "]"
                o.Actors.Push(actx)
            End If
        End For
        Return 0
    End Function 
} 

q.starring(myobj, myxml)