Question

I feel like I understand MAKE as being a constructor for a datatype. It takes two arguments... the first the target datatype, and the second a "spec".

In the case of objects it's fairly obvious that a block of Rebol data can be used as the "spec" to get back a value of type object!

>> foo: make object! [x: 10  y: 20  z: func [value] [print x + y + value] ]
== make object! [
    x: 10
    y: 20
]

>> print foo/x
10

>> foo/z 1
31

I know that if you pass an integer when you create a block, it will preallocate enough underlying memory to hold a block of that length, despite being empty:

>> foo: make block! 10
== []

That makes some sense. If you pass a string in, then you get the string parsed into Rebol tokens...

>> foo: make block! "some-set-word: {String in braces} some-word 12-Dec-2012"   
== [some-set-word: "String in braces" some-word 12-Dec-2012]

Not all types are accepted, and again I'll say so far... so good.

>> foo: make block! 12-Dec-2012
** Script error: invalid argument: 12-Dec-2012
** Where: make
** Near: make block! 12-Dec-2012

By contrast, the TO operation is defined very similar, except it is for "conversion" instead of "construction". It also takes a target type as a first parameter, and then a "spec". It acts differently on values

>> foo: to block! 10
== [10]

>> foo: to block! 12-Dec-2012
== [12-Dec-2012]

That seems reasonable. If it received a non-series value, it wrapped it in a block. If you try an any-block! value with it, I'd imagine it would give you a block! series with the same values inside:

>> foo: to block! quote (a + b)
== [a + b]

So I'd expect a string to be wrapped in a block, but it just does the same thing MAKE does:

>> foo: to block! "some-set-word: {String in braces} some-word 12-Dec-2012"   
== [some-set-word: "String in braces" some-word 12-Dec-2012]

Why is TO being so redundant with MAKE, and what is the logic behind their distinction? Passing integers into to block! gets the number inside a block (instead of having the special construction mode), and dates go into to block! making the date in a block instead of an error as with MAKE. So why wouldn't one want a to block! of a string to put that string inside a block?

Also: beyond reading the C sources for the interpreter, where is the comprehensive list of specs accepted by MAKE and TO for each target type?

Was it helpful?

Solution

MAKE is a constructor, TO is a converter. The reason that we have both is that for many types that operation is different. If they weren't different, we could get by with one operation.

MAKE takes a spec that is supposed to be a description of the value you're constructing. This is why you can pass MAKE a block and get values like objects or functions that aren't block-like at all. You can even pass an integer to MAKE and have it be treated like an allocation directive.

TO takes a value that is intended to be more directly converted to the target type (this value being called "spec" is just an unfortunate naming mishap). This is why the values in the input more directly correspond to the values in the output. Whenever there is a sensible default conversion, TO does it. That is why many types don't have TO conversions defined between them, the types are too different conceptually. We have fairly comprehensive conversions for some types where this is appropriate, such as to strings and blocks, but have carefully restricted some other conversions that are more useful to prohibit, such as from none to most types.

In some cases of simple types, there really isn't a complex way to describe the type. For them, it doesn't hurt to have the constructors just take self-describing values as their specs. Coincidentally, this ends up being the same behavior as TO for the same type and values. This doesn't hurt, so it's not useful to trigger an error in this case.

There are no comprehensive docs for the behavior of MAKE and TO because in Rebol 3 their behavior isn't completely finalized. There is still some debate in some cases about what the proper behavior should be. We're trying to make things more balanced, without losing any valuable functionality. We've already done a lot of work improving none and binary conversions, for instance. Once they are more finalized, and once we have a place to put them, we'll have more docs. In the meanwhile most of the Rebol 2 behavior is documented, and most of the changes so far for Rebol 3 are in CureCode.

OTHER TIPS

Also: beyond reading the C sources for the interpreter, where is the comprehensive list of specs accepted by MAKE and TO for each target type?

May not be that useful, since it's red specific:

But it does at least mention if the behaviour is similar or different from rebol

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top