Instead of creating objects by writing:
obj: object [
name: "Fork"
id: 1020
]
I'd like to write something like...
obj: something-or-another [name id] ["Fork" 1020]
...and get the same result. An ideal solution would also permit:
obj: something-or-another [name: id:] ["Fork" 1020]
Easy enough to write a something-or-another
, but does this fit something already "in the box"?
I don't believe there's a baked-in way to do this. Not difficult though:
func [words values][
set words: context append map-each word words [to set-word! word] none values
words
]
I suppose I could break this down a little:
func [
"Creates an Object From a Block of Words, Assigns Values"
words [block!] "Words used to create object"
values "Value(s) to assign"
][
words: map-each word words [to set-word! word] ; The requisite set-words
append words none ; Initial value for all words
words: context words ; Create our object
set words values ; Assigns our value(s) to the object
words ; returns the object
]
You might employ a different method to interleave blocks, such as:
func [words [block!] values [block!]][
collect [
repeat index max length? words length? values [
keep words/:index
keep values/:index
]
]
]
Here's something that requires at least Rebol 3:
func [
"Create an object based on some words and values."
words [any-word! block!] "Word or block of words"
values [any-type!] "Value or block of values"
/local object
][
object: make object! either block? words [length? words] [1]
set bind/copy/new :words object :values
object
]
If you want to also allow setting unset values, try this:
func [
"Create an object based on some words and values."
words [any-word! block!] "Word or block of words"
values [any-type!] "Value or block of values"
/any "Allows setting words to any value, including unset"
/local object
][
object: make object! either block? words [length? words] [1]
apply :set [bind/copy/new :words object :values any]
object
]
Both of these create objects with self
, so if you want to create an object without self
you have to do some fancier tricks. See the selfless
proposal for details.
I wrote a similar function (Rebol2) just a few days ago:
build-object: func [
"Builds an object from a block"
names [block!] "Field names"
/values val [block!] "Initial values"
/local o name value
] [
o: copy []
names: compose names
o: either values [
parse names [
some [
set name [word! | set-word!]
(append o to-set-word name)
| skip
]
]
set/pad reflect o: context append o none 'words val
o
] [
if any [
parse names [
some [
set name [word! | set-word!]
(append o reduce [to-set-word name none])
]
]
parse names [
(clear o) some [
set name [word! | set-word!] set value any-type!
(append o reduce [to-set-word name :value])
]
]
] [context o]
]
o
]
To build your object you could write any of: (create a function as f: does ["x"]
)
build-object [name "Fork" id 1020]
build-object [name: "Fork" id: 1020]
build-object/values [name id] ["Fork" 1020]
build-object/values [name: id:] ["Fork" 1020]
build-object [name f]
build-object [name (f)] ;block is composed
build-object [name 5 id f]
build-object [name 5 id 'f]
You can also make objects with fields set to none
if you leave the values out, e.g. with
build-object [name id]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With