REBOL 3 Docs Guide Concepts Functions Datatypes Errors
  TOC < Back Next >   Updated: 3-Aug-2010 Edit History  

REBOL 3 Functions: protect

protect  value  /deep  /words  /values  /hide

Protect a series or a variable from being modified.

Arguments:

value [word! series! bitset! map! object! module!]

Refinements:

/deep - Protect all sub-series/objects as well

/words - Process list as words (and path words)

/values - Process list of values (implied GET)

/hide - Hide variables (avoid binding and lookup)

See also:

unprotect   secure   set  

Contents

Description

The protect function provides the following features:

Synopsis

The protect argument and refinements provide these various protections:

Argument Refinement Protection provided
word! or path! cannot set the word (variable)
word! or path! /hide cannot bind to the word (variable)
string! cannot modify the string
block! cannot modify the block
block! /deep cannot modify block or any series within it
block! /words cannot set listed words or paths (variables)
block! /hide cannot bind to listed words or paths
object! cannot modify object or set its words (variables)
object! /deep cannot modify object, set its words, or modify any of its series values

Protecting series (strings and blocks)

For example to use protect to prevent modification to a string:

test: "text"
protect test
append test "a"
** Script error: protected value or series - cannot modify

The text string itself is now read-only. Any attempt to modify it will result in that error message.

This also applies to other series:

test: [100 "example" 10:20]
protect test
append test 1.2
** Script error: protected value or series - cannot modify

But notice:

print append test/2 "x"
examplex

So, series within the block are still modifiable.

To protect all series found within a block, use the /deep refinement:

test: [100 "example" 10:20]
protect/deep test
print append test/2 "x"
** Script error: protected value or series - cannot modify

Protecting objects and modules

It can also be applied to objects and modules, where its meaning becomes: do not let the fields of the object be modified. However, the contents of those fields can still be modified.

person: make object! [
     name: "Bob"
     age: 32
]
protect person
person/name: "Ted"
** Script error: protected variable - cannot modify: name

However, you can still modify the contents of the name string:

append person/name "a"
print person/name
Boba

To prevent that, you call protect with the /deep refinement to protect all series within the object:

person: make object! [
     name: "Bob"
     age: 32
]
protect/deep person
append person/name "a"
** Script error: protected value or series - cannot modify

Protecting variables (words)

Protect can also be used to prevent a variable word from being modified using a set operation.

test: "This word is protected!"
protect 'test
test: 123
** Script error: protected variable - cannot modify: test

Hiding variables (words)

To make a variable private, use the /hide refinement. In effect, this prevents any further bindings to the variable. It also blocks attempts at select, in, get, mold, and form, as well as reflect access.

For example, here is an object that defines a password variable that is hidden. Once the object has been created, the pass variable is not accessible, except with the functions defined prior to the protect.

manager: object [

    pass: none

    set-pass: func [pw][
        print "setting password..."
        pass: pw
        exit ; return nothing
    ]

    get-pass: does [
        checksum/secure to-binary pass
    ]

    protect/hide 'pass
]

The password can be accessed with the provided functions:

manager/set-pass "bingo"
setting password...
print manager/get-pass
#{E410B808A7F76C6890C9ECACF2B564EC98204FDB}

But any other access is not allowed:

probe manager/pass
** Script error: cannot access pass in path manager/pass
probe get in manager 'pass
none
probe select manager 'pass
none
probe words-of manager
[set-pass get-pass]

For security reasons, once hidden, a variable cannot be unhidden.

Compatibility

Non-compatibility with R2

When using a block with protect, the meaning is not to protect the words of the block, but to protect the block series itself.

If you need the behavior of R2, use the /words refinement.

For example:

protect/words [test this]

Will protect the test and this variables.

Related articles

(From the A43 release.)


  TOC < Back Next > REBOL.com - WIP Wiki Feedback Admin