3

If you build up a block structure, convert it to a string with MOLD, and write it to a file like this:

>> write %datafile.dat mold [
    [{Release} 12-Dec-2012]
    [{Conference} [12-Jul-2013 .. 14-Jul-2013]]
]

You can LOAD it back in later. But what about headers? If a file contains code, it is supposed to start with a header like:

rebol [
    title: "Local Area Defringer"
    date: 1-Jun-1957
    file: %defringe.r
    purpose: {
        Stabilize the wide area ignition transcriber
        using a double ganged defringing algorithm.
    }
]

If you are just writing out data and reading it back in, are you expected to have a rebol [] header, and extend it with any properties you want to add? Should you come up with your own myformat [] header concept with your own properties?

Also, given that LOAD does binding, does it make sense to use it for data or is there a different operation?

2 Answers2

4

Rebol data doesn't have to have a header, but is best practice to include one (even if it's just data).

Some notes:

  • SAVE is your best bet for serializing to file! or port! and has a mechanism for including a header.

  • MOLD and SAVE both have an /ALL refinement that corresponds to LOAD (without /ALL, some data from MOLD and SAVE cannot be reliably recovered, including Object, Logic and None values).

  • LOAD discards the header, though you can load it using the /HEADER refinement.

Putting this together:

save/all/header %datafile.dat reduce [next "some" 'data][
    title: "Some Data"
]

header: take data: load/header %datafile.dat

To use a header other than Rebol [], you'd need to devise a separate loader/saver.

rgchris
  • 3,698
  • 19
  • 19
  • If one is going to use the Rebol header, is there a convention to put custom fields unique to one's own data format? Or should those be in a separate header after the Rebol header? – HostileFork says dont trust SE Oct 08 '13 at 22:43
  • @HostileFork If it's valid metadata, I'd add it to the header. Only real snag is that you can't guarantee the custom field will be a word of a given header object, whereas you can always rely on the default set: Title, Name, Version, Date, File, Author, Needs, Options, Checksum. – rgchris Oct 08 '13 at 22:52
  • Actually, that's not strictly true. You can append to the prototype header object at `SYSTEM/STANDARD/HEADER` and your custom field will be included in every subsequent loaded header whether it's included in the header or not. – rgchris Oct 08 '13 at 22:56
  • I appreciate you mentioned save/all. Without it, there may be a problem with data like #[none], #[unset!], #[true], #[false]. However, it is not true that save without /all corresponds to DO. That is just a long said error. – Ladislav Oct 08 '13 at 23:12
  • @Ladislav fair point, it is not one to one. However, DO is closer to LOAD when recovering data from a plain SAVE that includes objects and none!/logic! literals. I appreciate this is not a reliable way to serialize data. Use /ALL. – rgchris Oct 09 '13 at 16:54
  • 1
    SAVE also has the advantage of supporting compression, which LOAD seamlessly decompresses. – BrianH Oct 09 '13 at 21:50
2

For the case of reading, construct works very well alongside load to prevent evaluation (of code as opposed to data):

prefs: construct/with load %options.reb default-prefs

It is:

Similar to context

obj: [
    name: "Fred" 
    age: 27 
    city: "Ukiah"
]

obj-context: context obj
obj-construct: construct obj

In this case, the same:

>> obj-context = obj-construct
== true

Different

when it comes to evaluating code:

obj-eval: [
    name: uppercase "Fred" 
    age: 20 + 7 
    time: now/time
]

obj-eval-context: context obj-eval
obj-eval-construct: construct obj-eval

This time parsing differently:

>> obj-eval-context = obj-eval-construct
false

>> ?? obj-eval-construct
obj-eval-construct: make object! [
    name: 'uppercase
    age: 20
    time: now/time
]

Aside:

This is the point I realize the following code wasn't behaving as I expected:

obj-eval: [
    title: uppercase "Fred" 
    age: 20 + 7
    city: "Ukiah"
    time: now/time
]

gives in red (and by extension, rebol2):

>> obj-eval-construct: construct obj-eval
== make object! [
    title: 'uppercase
    age: 20
    city: "Ukiah"
    time: now/time
]

lit-word! and lit-path! is different. TODO: question


It has also

Useful refinement /with

Which can be used for defaults, similar to make

Geeky I
  • 751
  • 6
  • 22