Search code examples
objectrebolrebol3

How to extend object with multiple functions in one call?


In Rebol 3 you can dynamically add keys and values to objects with append:

>> foo: object [x: 10]

>> append foo [y: 20 z: 30]
== make object! [
    x: 10
    y: 20
    z: 30
]

But if you try that with functions, it doesn't seem to work:

>> foo: object [x: 10]

>> append foo reduce [y: does [print "y"] z: does [print "z"]]
** Script error: invalid argument: make function! [[][print "y"]]
** Where: append
** Near: append foo reduce [y: does [print "y"] z: does [print "z"]]

You can add a function with extend:

>> foo: object [x: 10]

>> extend foo 'y does [print "y"]

>> foo/y
y

But that only lets you add one at a time. How can you add a block of arbitrary keys/values to an object, with some of them functions?


Solution

  • As extend is just a mezzanine,

    >> source extend
    extend: make function! [[
       {Extend an object, map, or block type with word and value pair.}
       obj [object! map! block! paren!] "object to extend (modified)"
       word [any-word!]
       val
    ][
      if :val [append obj reduce [to-set-word word :val]]
      :val
    ]]
    

    you can with ease define your own extend or a new function

    extends: make function! [  [{Extend an object}
       obj  [object!]
       funcblk [block!]  "with pair(s) of functionname and function"
    ] [
       foreach [name funcon] funcblk [append obj reduce [to-set-word name get funcon]]
    ]]
    

    and then you are able to do

    >> r: does [print "y"] s: does [print "z"]
    >> extends foo [y r z s]
    == make object! [
       x: 10
       y: make function! [[][print "y"]]
       z: make function! [[][print "z"]]
    ]
    

    or for short

    >> append foo reduce [quote y: does [print "y"] quote z: does [print "z"]]
    == make object! [
        x: 10
        y: make function! [[][print "y"]]
        z: make function! [[][print "z"]]
    ]