2013-08-21 9 views
5

Anstelle von Objekten durch Schreiben zu erstellen:Interleave-Blöcke oder Objekt aus zwei Blöcken (Feldnamen und Werte) machen

obj: object [ 
    name: "Fork" 
    id: 1020 
] 

Ich möchte so etwas wie schreiben ...

obj: something-or-another [name id] ["Fork" 1020] 

... und das gleiche Ergebnis erhalten. Eine ideale Lösung würde erlauben auch:

obj: something-or-another [name: id:] ["Fork" 1020] 

leicht genug, um einen something-or-another, zu schreiben, aber passt das schon etwas „in der Box“?

Antwort

3

Ich glaube nicht, dass es eine eingebackene Möglichkeit gibt, dies zu tun. Nicht schwierig, aber:

func [words values][ 
    set words: context append map-each word words [to set-word! word] none values 
    words 
] 

Ich glaube, ich könnte diese brechen ein wenig nach unten:

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 
] 

Sie könnten eine andere Methode verwenden Blöcke verschachteln, wie zum Beispiel:

func [words [block!] values [block!]][ 
    collect [ 
     repeat index max length? words length? values [ 
      keep words/:index 
      keep values/:index 
     ] 
    ] 
] 
+0

Das erste Ihrer Codebeispiele (die Funktion könnte einen Namen benötigen) ist kurz und sauber und es sieht für mich am besten aus. – Ladislav

1

Ich schrieb eine ähnliche Funktion (Rebol2) vor ein paar Tagen:

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 
] 

Um Ihr Objekt bauen Sie schreiben konnte Aktionen aus:

  • 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
  • (eine Funktion als f: does ["x"] erstellen)
  • build-object [name 5 id 'f]

Sie können auch Objekte mit Feldern machen auf none wenn Sie die Werte aus verlassen, zum Beispiel mit

build-object [name id] 
+0

Interessant, dass es mehr als einmal in kurzer Zeit kommen würde! Vielleicht ein Zeichen, dass es oft kommt, und etwas hier sollte standardisiert werden.Gibt es einen Grund, Ihre "Werte-Regel" so zu formulieren, wie sie von "jeder Art" abweicht? – HostileFork

+0

Es war für mein spezielles Bedürfnis. Aber du hast Recht, irgendeinen Typ verwendend! könnte nützlich sein. – endo64

+0

Ich schrieb eine andere Version mit Any-Type und einigen kleinen Korrekturen, sollte ich meine vorherige Antwort bearbeiten oder eine neue hinzufügen? – endo64

2

Hier ist etwas, das mindestens Rebol 3 erfordert: ungesetzt Werte zulassen möchten, versuchen Sie diese Einstellung, wenn Sie auch

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 
] 

:

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 
] 

Beide Objekte erstellen mit self, wenn Sie also ein Objekt ohne self erstellen möchten, müssen Sie ein paar raffiniertere Tricks machen. Einzelheiten finden Sie unter the selfless proposal.