2013-08-21 9 views
5

Zamiast tworzenia obiektów pisząc:przeplatać bloki lub uczynić obiekt z dwóch bloków (nazwy pól i wartości)

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

Chciałbym napisać coś jak ...

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

... i uzyskaj taki sam wynik. Idealnym rozwiązaniem byłoby również zezwolić:

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

dość łatwo napisać something-or-another, ale robi to pasuje coś już „w polu”?

Odpowiedz

3

Nie wierzę, że jest to wypieczony sposób. Nie trudno jednak:

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

Przypuszczam, że to może rozbić trochę:

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 
] 

Można stosować różne metody, aby przeplatać bloki, takie jak:

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

Pierwszy z przykładów kodu (funkcja może wymagać nazwy) jest krótki i czysty i wygląda dla mnie najlepiej. – Ladislav

1

pisałem podobna funkcja (Rebol2) kilka dni temu:

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 
] 

budować swój obiekt można napisać żadnej z: (utworzyć funkcję jako 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]

Można także obiekty z polami ustawionymi na none jeśli zostawisz wartości na zewnątrz, na przykład z

build-object [name id] 
+0

Interesujące, że pojawi się więcej niż jeden raz w krótkim czasie! Może znak, że często się pojawia, a coś tu powinno być znormalizowane.Czy istnieje powód, aby wyrazić swoją "wartość-regułę" w ten sposób, a nie "różnicę" od 'any-type!'? – HostileFork

+0

To było dla mojej specjalnej potrzeby. Ale masz rację, używając dowolnego typu! może być przydatne. – endo64

+0

Napisałem inną wersję za pomocą dowolnego typu i kilka drobnych poprawek, czy powinienem edytować poprzednią odpowiedź, czy dodać nową? – endo64

2

Oto coś, co wymaga co najmniej 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 
] 

Jeśli chcesz, aby umożliwić również ustawienie wartości ustawione, spróbuj tego:

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 
] 

Oba tworzyć obiekty z self, więc jeśli chcesz utworzyć obiekt bez self, musisz zrobić kilka bardziej wyszukanych trików. Szczegóły: the selfless proposal.

Powiązane problemy