rebol document

REBOL/Core Changes

Core Versions 2.3.0 - 2.5.6
Including /View, /SDK, and /Command

Contents:

1. Core 2.5.6
1.1 Command Line Startup (Fixes CGI/shell scripts)
1.2 Implied Quit
1.3 Corrupt Datatype Failure
1.4 Help Native! Fixed
1.5 Get on NONE
1.6 Set-Browser-Path
1.7 DO On Command Line
1.8 FIND/Any Bug Fixed.
1.9 Molding Empty File Names
2. Core 2.5.5
2.1 Main Purpose
2.2 New Core License
2.3 Startup Files (user.r and rebol.r)
2.4 How Scripts are Started
2.5 Command Line Terminator (CR)
2.6 Changes to SECURE
2.7 MOLD/Flat Refinement
2.8 Truncation of Series Index (when Past Tail)
2.9 AT on PORTs
2.10 Added SIXTH Through TENTH Functions
2.11 Lines Longer Than 4 KB in Direct/Lines Mode
2.12 DECODE-CGI Handles Duplicate Names
2.13 ALTER Fixed
2.14 Network Errors in TRY (Net-Error Throw)
2.15 Extended FTP Directory Paths
2.16 STATS for SYSTEM/STATS
2.17 PURL Captured
3. Core 2.5.3
3.1 Credits
3.2 MAKE-DIR Rewritten
3.3 New Bitset Functions: CLEAR, LENGTH?, EMPTY?
3.4 Changes to SKIP Function
3.5 ARRAYs Initialized with Block Values
3.6 Added PARSE BREAK Word
3.7 Fix to OPEN on Network Ports
3.8 Fixed Crash on Modified Functions
3.9 CHANGE Accepts Any Type Value
3.10 Unset Object Variables (on Exit)
3.11 Added BUILD-MARKUP Function
3.12 Revised BUILD-TAG Function
3.13 Revised DECODE-CGI Function
3.14 UNPROTECT Fixed
3.15 ALTER added to Core
3.16 SYSTEM Word Protected
3.17 Error Message for Word Context
3.18 Fixed Crash on Future Dates
4. Core 2.5.2
4.1 CONSTRUCT Object Creator
4.2 LOAD Change (Important)
4.3 HELP Expanded
4.4 SUFFIX? Function Added
4.5 SIGN? Function Added
4.6 COMPONENT? Function Added
4.7 SEND Function Updated
4.8 Miscellaneous Fixes
5. Core 2.5.1
5.1 Source Code Form for Values of NONE, TRUE, etc.
5.2 Less Aggressive Evaluation (Important!)
5.3 COMPOSE/ONLY Inserts Blocks
5.4 REMOVE-EACH - Easy Series Element Removal
5.5 ATTEMPT for Error Handling
5.6 EXTRACT Function Updated
5.7 SAVE to Memory
5.8 SEND Refinements /Subject /Attach
5.9 Difference for Date/time
5.10 System Port Added
6. Core 2.5.0
6.1 New Sort Function
6.2 File Modes
6.3 Serial Port Access
6.4 Objects
6.5 Mold and Load Changes
6.6 File and Port Changes
6.7 Network Protocol Change (APOP, IMAP)
6.8 Data Series Changes
6.9 Math Related Changes
6.10 Command Line Changes
6.11 Console
6.12 Control
6.13 Interpreter
6.14 Other Changes
7. Interpreter Fixes
8. Networking Fixes
9. Other Function Fixes
10. Summary of New Features in 2.3
11. Summary of Enhancements in 2.3
12. Summary of Fixes in 2.3
13. New Functions and Refinements in 2.3
13.1 Pair Datatype
13.2 Make-dir/deep
13.3 Unique
13.4 Does
13.5 Offset?
13.6 Load/Markup
13.7 Repend
13.8 Replace/case
13.9 ??
13.10 To-pair
14. Enhancements in 2.3
14.1 Parse Block
14.2 POP handler change
14.3 Tab Completion
14.4 Load's /Next Refinement
14.5 Query Function
14.6 Functions Accepting Pair Values
14.7 Random Function
14.8 System/options/path
14.9 What Function
14.10 If, Any, and All Functions
14.11 Help
15. Fixes in 2.3
15.1 Split-path Function
15.2 Network activity interruptible
15.3 Trim/lines
15.4 To-word Function
15.5 To-block Function
16. Other Changes (From Addendum Document) in 2.3

1. Core 2.5.6

Miscellaneous fixes made during the version 2.5.6 releases of the /SDK, /Command, and /SDK/Command products.

1.1 Command Line Startup (Fixes CGI/shell scripts)

REBOL ignores CR characters (13) in script files, but a problem occurred if a CR appeared on the command line that started REBOL. REBOL would display HELP information. This problem has been fixed and solves the problem that may occur when you used an FTP binary transfer of a CGI script to your Linux/Unix web server.

1.2 Implied Quit

All REBOL products are now consistent in what they do when a script has finished running, but did not execute a QUIT. They now now force a QUIT at the end of the script. If you want to go to the REBOL console, put a HALT in your script.

1.3 Corrupt Datatype Failure

In some situations REBOL would crash at the end of a script with a "corrupt datatype" error. This was caused by optimizations made in 2.5.3 that freed unused internal structures. The problem would only occur when a script caused memory recycling and did not include a QUIT or HALT at its end. This has been fixed.

1.4 Help Native! Fixed

Requesting HELP on NATIVE! has been fixed (the native! word has been restored).

1.5 Get on NONE

A GET of NONE is now allowed and will return NONE.

print get none

This makes it easier to write code that fetches values from an object when the word within the object may be missing. For example, the code below will no longer cause an error if the word is missing from the object:

value: get in object 'word

This makes code simpler for cases like CGI object form values:

cgi: construct decode-cgi read-cgi
name: any [get in cgi 'name "default"]

In the example above, if the cgi/name does not exist, the default string is used. No error will occur if the name is missing from the CGI object.

1.6 Set-Browser-Path

The SET-BROWSER-PATH function now accepts REBOL filename format. It will also accept a string that is in local OS file format (when provided as a string! type). You can also set it to NONE.

The SET-BROWSER-PATH function will also return it's prior setting.

If you wish to disable this function (for security reasons), you can set it to NONE or unset the function.

set-browser-path: none

unset 'set-browser-path

1.7 DO On Command Line

The --do option is processed again on the command line. This allows you to pass expressions to be executed from the shell command line. For example:

rebol --do "probe system/options/args"

Note that --do now happens after the rebol.r and user.r files are evaluated (letting you initialize your own custom functions and values) but before the script on the command line is evaluated.

The --do option can be used to define variables prior to the execution of your script. For example:

rebol make-website.r --do "verbose: true"

would set the VERBOSE variable to TRUE at the start of execution. To set the default value in the script, you might use code such as:

if not value? 'verbose [verbose: false]

1.8 FIND/Any Bug Fixed.

A serious error was reported related to using FIND with the /any refinement (wildcards). For some cases FIND/any would return a valid string rather than NONE. For example:

find/any next "abc" "d"

returned "c". This problem has been fixed.

1.9 Molding Empty File Names

MOLDing an empty filename resulted in source code that could not be loaded. In rare cases, this might case a SAVE to create a file that LOAD could not handle. Molding an empty file name now outputs the characters %"" to avoid this problem. This fixes the problem in MOLD, SAVE, and PROBE.

2. Core 2.5.5

2.1 Main Purpose

The primary purpose of the Core 2.5.5 release is to bring REBOL/Core into closer compatibility with the new Mac OS X and REBOL/SDK kernels.

2.2 New Core License

REBOL/Core licensed has changed to allow personal, educational, or commercial use of the CORE software free of charge.

Note that this license change only applies to REBOL/Core (and will be added to the next release of REBOL/View), but it does not apply to REBOL/SDK, /Command, /IOS or other REBOL commercial products.

2.3 Startup Files (user.r and rebol.r)

Beta V2.5.4 did not evaluate the rebol.r and user.r files. V2.5.5 evaluates them again, although using a slightly different method. This should not affect your program. The order is still:

  1. Check the current directory first.
  2. Check the system/options/home directory second.

This allows you to have a single standard rebol.r file (and optionally a user.r file) that is shared by all users on multiuser systems.

2.4 How Scripts are Started

The method used to start initial scripts has been modified.

This change will have no affect on your programs, but it will produce a better error message on script errors by eliminating the error line that refers to the problem being "Near do-boot". That line was confusing to new users, because do-boot was not part of their script file.

2.5 Command Line Terminator (CR)

REBOL no longer shows Usage info if a CR char is passed from a Unix shell on the shell command line.

Although REBOL scripts properly read and load with respect to the CR (ASCII 13) character, some operating systems will pass the CR as a command line argument, causing older versions of REBOL to print its usage help information.

For example, you might see a problem with a CGI shell script starting with:

#!/home/user/rebol -cs
REBOL [...]

that was written on a Windows system and transferred to Linux without converting line terminators.

This case has been fixed.

2.6 Changes to SECURE

Beta V2.5.4 did not set SECURE prior to running scripts (in other words, it functioned like REBOL/Base).

With V2.5.5 security is being set again, although with a slight change: by default you can now write to a script's target directory. For example, if you run:

REBOL /home/test/script.r

REBOL will startup with WRITE access to /home/test. All other directories will be set to READ only (with WRITE ask).

This change makes it easier for users to write scripts that write and update local data files without the need to provide a -S command line option, but it still protects the rest of your files.

Note that the +S command line option has also been changed. Previously, +S meant SECURE QUIT, which was almost useless because your REBOL would QUIT as soon as it tried to read its rebol.r and user.r files. Now +S means SECURE ASK, so running with:

rebol +s script.r

Will prompt the user for all READ/WRITE operations for files and networking. A safe mode of operation, but less strict than before.

In addition, the --secure options should also work again now:

rebol --secure allow script.r
rebol --secure ask script.r

2.7 MOLD/Flat Refinement

The /flat refinement allows you to MOLD code and data without line indentation, making the resulting string smaller (for sending over a network, storing as compressed data, encapping, etc.).

For example:

blk: [
    name [
        first "Bob"
        last "Smith"
    ]
    options [
        colors [
            red
            green
            blue
        ]
    ]
]

>>print mold blk
[
    name [
        first "Bob"
        last "Smith"
    ]
    options [
        colors [
            red
            green
            blue
        ]
    ]
]

>> print mold/flat blk
[
name [
first "Bob"
last "Smith"
]
options [
colors [
red
green
blue
]
]
]

2.8 Truncation of Series Index (when Past Tail)

The handling of an "past the tail" series index has been changed.

In prior versions of REBOL, referring to a series past its tail would cause an error:

>> a: "ABC"
== "ABC"
>> b: next a
== "BC"
>> clear a
== ""
>> insert b "X"
** Script Error: Out of range or past end
** Near: insert b "X"

In some situations, this problem could become difficult to detect, because nearly any reference to B would cause the error.

>> tail? b
** Script Error: Out of range or past end
** Near: tail? b

As a result, the "past end" handling has been relaxed. For many functions, the index will now truncate to the current tail of the series:

>> a: "ABC"
== "ABC"
>> b: next a
== "BC"
>> clear a
== ""
>> tail? b
== true

2.9 AT on PORTs

The AT function (similar to the SKIP function) now works for the Port datatype.

2.10 Added SIXTH Through TENTH Functions

Five new ordinal functions have been added:

sixth
seventh
eighth
ninth
tenth

The benefit of these function becomes more clear when you consider using them to pick values from a series (instead of using an object field).

name-of: :first
age-of:  :second
date-of: :third
...
product-of: :ninth
...
if empty? product-of record [print "missing product"]

The line above is much more readable than:

if empty? ninth record [print "missing product"]

Here's a handy utility function for creating such named accessors:

ordain: func [
    "Defines ordinal accessors (synonyms)."
    words [block!] /local ords
][
    ords: [first second third fourth fifth
        sixth seventh eighth ninth tenth]
    foreach word words [
        set word get first ords
        ords: next ords
    ]
]

The above example would then be simplified to:

ordain [name-of age-of date-of ... product-of]
...
if empty? product-of record [print "missing product"]

Question: Would you like to see ordain become a regular function in REBOL? Tell us via Feedback.

2.11 Lines Longer Than 4 KB in Direct/Lines Mode

Earlier versions of REBOL did not properly expand their internal line buffers beyond 4 KB for files opened in direct/lines mode. As a result, lines longer than 4 KB (no line terminators for more than 4 KB) would not be read correctly and would cause an end of file. This problem has been fixed in the current release.

2.12 DECODE-CGI Handles Duplicate Names

With increased use of REBOL for CGI scripts, we've expanded the DECODE-CGI function to handle duplicate name fields.

For example, checklists used in web forms may return multiple values for a single variable. DECODE-CGI will now make these multivalued returns into blocks:

>> cgi-str: {name=bob&option=view&option=email&}
>> decode-cgi cgi-str
== [name: "bob" option: ["view" "email"]]

2.13 ALTER Fixed

A serious error in the ALTER function (a data set flagging function, see updated docs in The REBOL Dictionary) caused it to malfunction. This problem has been fixed.

2.14 Network Errors in TRY (Net-Error Throw)

The NET-ERROR function used THROW for errors, rather than just letting the error throw itself. This caused some types of network errors to bypass a higher level catch when using TRY.

This meant that if you used a TRY around sections of your code, certain network errors (such as an SMTP problem) may be thrown past it, which would cause the error to be passed all the way out to user at the console. This was a problem for SDK scripts, and has been fixed.

2.15 Extended FTP Directory Paths

When using FTP URLs, there was no easy way to provide a full path from the root directory.

For example, your logon directory may be:

/home/luke/

but you want to refer to:

/var/log/

In the new release, you can use a double slash URL to provide the absolute directory path:

read ftp://user:pass@host//var/log/messages

(Please tell us if you have any problems using this format.)

2.16 STATS for SYSTEM/STATS

The STATS function is now directly accessible. You no longer need to use SYSTEM/STATS.

In addition, the STATS function now more accurately computes memory usage.

2.17 PURL Captured

The variable PURL used in DECODE-URL is now a local variable rather than a global.

3. Core 2.5.3

3.1 Credits

Thanks go to these contributors for their feedback, suggestions, or solutions:

Andrew Martin
"Anton"
Cal Dixon 
Carl Sassenrath
Ernie van der Meer
Gregg Irwin
Ladislav Mecir
Maarten Koopmans
"Mr. Martin Mr. Saint"
Reichart Von Wolfsheild

Did we miss your feedback or contribution to fixes or improvements? If so, tell us at: http://www.rebol.com/feedback.html.

It is not always possible to get every change into each new release, but if you have found a bug that's causing you problems, please let us know and we'll do our best to fix it. Provide a very short, repeatable example of the problem, and if you have a fix to the problem, send that along as well. (You'll see the fix happen much faster that way.)

3.2 MAKE-DIR Rewritten

The MAKE-DIR function has been rewritten and now works correctly. In addition, it has been relaxed to not cause an error when the specified directory exists. Use the EXISTS? function if you need to check that.

3.3 New Bitset Functions: CLEAR, LENGTH?, EMPTY?

Three new functions (actions) have been added to bitsets:

The CLEAR function quickly clears all bits to zero.

The LENGTH? function returns the number of bits in the bitset (always multiple of 8).

The EMPTY? function returns TRUE if any bit is set, otherwise it returns FALSE. (Note that EMPTY? is the same function as TAIL?; therefore, TAIL? also returns the same results, but the word has no meaning for bitsets.)

Bitsets are used as high performance logic arrays for character sets and hashes.

Examples:

>> items: make bitset! 40
== make bitset! #{0000000000}

>> length? items
== 40

>> empty? items
== true

>> insert items 10
== make bitset! #{0004000000}

>> empty? items
== false

>> clear items
== make bitset! #{0000000000}

>> empty? items
== true

>> empty? negate items
== false

3.4 Changes to SKIP Function

There are three changes to SKIP that you should note:

1. SKIP now handles decimal offsets correctly. Values are truncated down to lower integer value. (Note that decimal offsets should be used with caution because 1.9999999 is not the same as 2.0 when it comes to indexing.)

>> skip "abc" 1.9999999
== "bc"
>> skip "abc" 2.0
== "c"

2. SKIP can have a logic offset. It is made consistent with PICK and AT when used with logic offsets.

>> pick [red green] true
== red
>> skip [red green] true
== [red green]
>> at [red green] true
== [red green]

>> pick [red green] false
== green
>> skip [red green] false
== [green]
>> at [red green] false
== [green]

For logic offsets, SKIP is identical to AT.

3. SKIP on images will offset pixels, not RGBA bytes. This is consistent with AT, PICK, and POKE. If you are currently using skip on images, this change will affect your code.

3.5 ARRAYs Initialized with Block Values

If a block value is provided as the initial element value in the ARRAY function, each element should be the block, not the contents of the block.

In addition, if the initial value is a SERIES of any type (e.g. string, block, email, url) it will be deep copied into each array element (that is, the value of each element will be unique, not shared).

As an example:

>> a: array/initial [2 3] [1 2]
== [[[1 2] [1 2] [1 2]] [[1 2] [1 2] [1 2]]]
>> append a/1/2 3
== [1 2 3]
>> a
== [[[1 2] [1 2 3] [1 2]] [[1 2] [1 2] [1 2]]]

3.6 Added PARSE BREAK Word

Within some types of PARSE loops such as ANY and SOME, it can sometimes be difficult to write rules that terminate the loop. This happens primarily when using general rules that try to capture "all other cases" within the loop. For example, code such as:

parse item [
    any [
        "word" (print "got word")
        | copy value [to "abc" | to end]
            (print value)
    ]
]

will end up looping forever because the second rule within the ANY will always succeed, and the ANY will never terminate.

To help solve this problem, the BREAK keyword was added to the parse dialect. Its use is simple. When the BREAK word is encountered within a rule block, the block is immediately terminated regardless of the current input pointer. Expressions that follow the BREAK within the same rule block will not be evaluated.

The above example can now be written as:

parse item [
    any [
        "word" (print "got word")
        | copy value [to "abc" | to end]
            (print value) break
    ]
]

The ANY loop will be terminated after the second rule.

Generally, for ANY rule blocks that need to terminate at the end of the input stream, you can add an END check followed by the BREAK keyword, such as in this example:

parse item [
    any [
          end break
        | "word" (print "got word")
        | copy value [to "abc" | to end]
            (print value)
    ]
]

3.7 Fix to OPEN on Network Ports

OPEN on network port under some versions of Windows32 would fail due to an incorrect error code returned from WinSock library (as documented by Microsoft). Fixed.

3.8 Fixed Crash on Modified Functions

Fixed the crash that happened when modifying a function's value while evaluating its arguments. For example, the code below:

a: func [x] [print x]
b: func [] [a: 42]
a b

no longer causes a crash.

Note that modifying a function while it is evaluating may produce odd results that may vary between implementation versions and should generally be avoided.

3.9 CHANGE Accepts Any Type Value

To be consistent with INSERT, the CHANGE function allows a new value to be any datatype (ANY-TYPE!).

Users should be aware that a missing value argument will result in a CHANGE value of UNSET!, not an error.

For example:

>> a: [10]
== [10]
>> do [change a]
== []
>> probe a
[unset]
== [unset]

3.10 Unset Object Variables (on Exit)

If exit occurs during object evaluation, unassigned variables not copied from parent object are unset. Fixes the "end" bug where the first variable was set to the END! datatype.

>> probe make object! [exit a: b:]
== make object! [
    a: unset
    b: unset
]

3.11 Added BUILD-MARKUP Function

This function was inspired by the EREBOL concept of Maarten Koopmans and Ernie van der Meer. Essentially, the idea is that REBOL makes a powerful PHP style markup processor for generating web pages and other markup text.

The BUILD-MARKUP function has been added to support this operation, and will become a standard part of every REBOL implementation.

The BUILD-MARKUP function takes markup text (e.g. HTML) that contains tags that begin with "<%" and end with "%>". It evaluates the REBOL code within each tag (as if it were a REBOL block), and replaces the tag with the result. Any REBOL expression can be placed within the tag. As PHP has shown, this is a very useful technique.

For example:

== build-markup "<%1 + 2%>"
>> "3"

== build-markup "<B><%1 + 2%></B>"
>> "<B>3</B>"

== build-markup "<%now%>"
>> "2-Aug-2002/18:01:46-7:00"

== build-markup "<B><%now%></B>"
>> "<B>2-Aug-2002/18:01:46-7:00</B>"

Supplying a <%now%> tag to BUILD-MARKUP inserts the current date/time in the output.

Here's a short example that generates a web page from a template and a custom name and email address:

template: {<HTML>
    <BODY>
    Hi <%name%>, your email is <i><%email%></i>.<P>
    </BODY>
    </HTML>
}

name: "Bob"
email: bob@example.com
page: build-markup template

Don't forget the two % characters within the tag. It's a common mistake.

The value that is returned from the tag code is normally "joined" into the output. You can also use FORM or MOLD on the result to get the type of output you require. The example below loads a list of files from the current directory and displays them three different ways:

Input: "<PRE><%load %.%></PRE>"
Result: {<PRE>build-markup.rchanges.txt</PRE>}

Input: "<PRE><%form load %.%></PRE>"
Result: {<PRE>build-markup.r changes.txt</PRE>}

Input: "<PRE><%mold load %.%></PRE>"
Result: {<PRE>[%build-markup.r %changes.txt]</PRE>}

If the evaluation of a tag does not return a result (for example using code such as print "test"), then nothing is output. In this case, the output of PRINT will be sent to the standard output device.

Input: {<NO-TEXT><%print "test"%></NO-TEXT>}
test
Result: "<NO-TEXT></NO-TEXT>"

The BUILD-TAG function can be used within the tag for converting REBOL values into markup output:

Input: {<%build-tag [font color "red"]%>}
Result: {<font color="red">}

Tags can set and use variables in the same way as any REBOL script. For example, the code below loads a list of files from the current directory, saves it in a variable, then prints two file names:

Input: "<PRE><%first files: load %.%></PRE>"
Result: {<PRE>build-markup.r</PRE>}

Input: "<PRE><%second files%></PRE>"
Result: {<PRE>changes.txt</PRE>}

Note that variables used within tags are always global variables.

If an error occurs within a tag, an error message will appear as the tag's result. This allows you to see web page errors from any HTML browser.

Input: "<EXAMPLE><%cause error%></EXAMPLE>"
Result: {<EXAMPLE>***ERROR no-value in: cause error</EXAMPLE>}

If you do not want error messages to be output, use the /QUIET refinement. The example above would result in:

Result: "<EXAMPLE></EXAMPLE>"

3.12 Revised BUILD-TAG Function

The previous version of BUILD-TAG generated poor results for most input combinations. It has been replaced by a new function that was contributed by Andrew Martin. This function produces better results, but ones that are different from the previous function. If you are currently using BUILD-TAG, you will need to adjust your code.

In:  [input "checked" type "radio" name "Favourite" value "cat"]
Old: {<input="checked" type="radio" name="Favourite" value="cat">}
New: {<input checked type="radio" name="Favourite" value="cat">}

In:  [html xml:lang "en"]
Old: {<html="xml:lang"="en">}
New: {<html xml:lang="en">}

In:  [body text #FF80CC]
Old: {<body text="FF80CC">}
New: {<body text="#FF80CC">}

In:  [a href %Test%20File%20Space.txt]
Old: {<a href="Test File Space.txt">}
New: {<a href="Test%20File%20Space.txt">}

In:  [/html gibber %Froth.txt]
Old: {</html gibber="Froth.txt">}
New: "</html>"

In:  [?xml version "1.0" encoding "UTF-8"]
Old: {<?xml version="1.0" encoding="UTF-8">}
New: {<?xml version="1.0" encoding="UTF-8"?>}

In:  [html xmlns http://w3.org/xhtml xml:lang "en" lang "en"]
Old: {<html xmlns="http://w3.org/xhtml"="xml:lang"="en" lang="en">}
New: {<html xmlns="http://w3.org/xhtml" xml:lang="en" lang="en">}

In:  [html xmlns http://w3.org/xhtml/ xml:lang "en" lang "en"]
Old: {<html xmlns="http://w3.org/xhtml/"="xml:lang"="en" lang="en">}
New: {<html xmlns="http://w3.org/xhtml/" xml:lang="en" lang="en">}

3.13 Revised DECODE-CGI Function

Several bugs have been fixed in DECODE-CGI. More specifically, the function handles empty attribute assignments. Here are some examples:

Input:   "name=val1&name=val2"
Decoded: [name: "val1" name: "val2"]

Input:   "name1=val1&name2&name3=&name4=val3"
Decoded: [name1: "val1" name2: "" name3: "" name4: "val3"]

Input:   "name1="
Decoded: [name1: ""]

Input:   "name2&"
Decoded: [name2: ""]

Input:   "name3=&"
Decoded: [name3: ""]

Input:   "name4=val"
Decoded: [name4: "val"]

Input:   "name5=val&"
Decoded: [name5: "val"]

The new function is based on Andrew Martin's contribution. Thanks!

3.14 UNPROTECT Fixed

Attempting to UNPROTECT a block containing any value other than a word could cause a crash. Now non-word values are ignored.

3.15 ALTER added to Core

The ALTER function found only in View is general purpose and has been made available in all version of REBOL.

3.16 SYSTEM Word Protected

To help prevent an accidental beginner mistake that is difficult to debug, the SYSTEM and REBOL words are now protected. If you need to change them, use UNPROTECT first.

3.17 Error Message for Word Context

The error message "word not defined in this context" has been changed to "word has no context" to better indicate that the word has never been defined (more precisely, never been bound) in the context of an object, function, or global environment.

3.18 Fixed Crash on Future Dates

Prevents startup crash caused by error in Microsoft Windows time functions when running with system date set to greater than 2036.

4. Core 2.5.2

4.1 CONSTRUCT Object Creator

We've added a "light-evaluation" object creator to provide a higher level of security for imported data objects. The function is called CONSTRUCT and it makes new objects, but without a normal evaluation of the object's specification (as is done in the MAKE and CONTEXT functions).

When you CONSTRUCT an object, only literal types are accepted. Functional evaluation is not performed. This allows your code to directly import objects (such as those sent from unsafe external sources such as email, cgi, etc.) without concern that they may include "hidden" side effects using executable code.

CONSTRUCT is used in the same way as the CONTEXT function:

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

but, no evaluation takes place. That means object specifications like:

obj: construct [
    name: uppercase "Fred"
    age: 20 + 7
    time: now
]

do not produce their evaluated results.

The CONSTRUCT function is useful for importing external objects. For example, loading preference settings from a file can done with:

prefs: construct load %prefs.r

Similarly, you can use CONSTRUCT to load a CGI or email response.

To provide a template object that contains default variable values (similar to MAKE), use the /WITH refinement. The example below would use an existing object called standard-prefs as the template.

prefs: construct/with load %prefs.r standard-prefs

The CONSTRUCT function will perform evaluation on the words TRUE, FALSE, NONE, ON, and OFF to produce their expected values. Literal words and paths will also be evaluated to produce their respective words and paths. For example:

obj: construct [
    a: true
    b: none
    c: 'word
]

The obj/a value would be logical TRUE, obj/b would be NONE, and obj/c would be WORD.

4.2 LOAD Change (Important)

Script header objects are now created by the CONSTRUCT function and they are no longer evaluated.

This change provides a greater level of default security when the LOAD function is used to load REBOL data. The change should affect very few scripts (only those that depend on evaluated header variables -- rare.)

The LOAD function can be used safely without the need to use LOAD/ALL to inspect a script header prior to evaluation.

4.3 HELP Expanded

Help can now be used to explore the fields of an object in a user-friendly format. For example, typing this line at the prompt:

help system

will produce this result:

SYSTEM is an object of value:
   version         tuple!    1.0.4.3.1
   build           date!     1-May-2002/13:31:11-7:00
   product         word!     Link
   components      block!    length: 45
   words           object!   [unset! error! datatype! context! native
   license         string!   {REBOL End User License Agreement IMPORT
   options         object!   [home script path boot args do-arg link-
   user            object!   [name email home words]
   script          object!   [title header parent path args words]
   console         object!   [history keys prompt result escape busy 
   ports           object!   [input output echo system serial wait-li
   network         object!   [host host-address]
   schemes         object!   [default Finger Whois Daytime SMTP POP I
   error           object!   [throw note syntax script math access co
   standard        object!   [script port port-flags email face sound
   view            object!   [screen-face focal-face caret highlight-
   stats           native!   System statistics. Default is to return 
   locale          object!   [months days]
   user-license    object!   [name email id message]

This works for other types of objects as well as user-created objects. The code below would display the contents of the text-face object created by a View layout:

out: layout [text-face: text "test"]

help text-face

Sub-objects can also be viewed. They are specified as paths. For example, to see the options object of the system object:

help system/options

The result would look something like this:

SYSTEM/OPTIONS is an object of value:
   home            file!     %/d/rebol/link/
   script          file!     %/d/rebol/link/ranch/utilities/console.r
   path            file!     %/d/rebol/link/ranch/
   boot            file!     %/d/rebol/link/rebol-link.exe
   args            none!     none
   do-arg          none!     none
   link-url        string!   "tcp://localhost:4028"
   server          none!     none
   quiet           logic!    true
   trace           logic!    false
   help            logic!    false
   install         logic!    false
   boot-flags      integer!  2064
   binary-base     integer!  16
   cgi             object!   [server-software server-name gateway-int

In addition, the search feature in help now provides more information about matches that were made. If you type:

help "to-"

You will now see:

Found these words:
   caret-to-offset native!   Returns the offset position relative to 
   offset-to-caret native!   Returns the offset in the face's text co
   to-binary       function! Converts to binary value.
   to-bitset       function! Converts to bitset value.
   to-block        function! Converts to block value.
   to-char         function! Converts to char value.
   to-date         function! Converts to date value.
   to-decimal      function! Converts to decimal value.
   to-email        function! Converts to email value.
   to-event        function! Converts to event value.
   to-file         function! Converts to file value.
   to-get-word     function! Converts to get-word value.
   to-hash         function! Converts to hash value.
   to-hex          native!   Converts an integer to a hex issue!.
   to-idate        function! Returns a standard Internet date string.
   to-image        function! Converts to image value.
   to-integer      function! Converts to integer value.
   to-issue        function! Converts to issue value.
   to-list         function! Converts to list value.
   to-lit-path     function! Converts to lit-path value.
   to-lit-word     function! Converts to lit-word value.
   to-local-file   native!   Converts a REBOL file path to the local 
   to-logic        function! Converts to logic value.
   to-money        function! Converts to money value.
   to-none         function! Converts to none value.
   to-pair         function! Converts to pair value.
   to-paren        function! Converts to paren value.
   to-path         function! Converts to path value.
   to-rebol-file   native!   Converts a local system file path to a R
   to-refinement   function! Converts to refinement value.
   to-set-path     function! Converts to set-path value.
   to-set-word     function! Converts to set-word value.
   to-string       function! Converts to string value.
   to-tag          function! Converts to tag value.
   to-time         function! Converts to time value.
   to-tuple        function! Converts to tuple value.
   to-url          function! Converts to url value.
   to-word         function! Converts to word value.

4.4 SUFFIX? Function Added

The SUFFIX? function is a helper function that returns the file "extension" portion of a filename or URL. For example:

>> suffix? %into.txt
== %.txt

>> suffix? http://www.rebol.com/docs.html
== %.html

>> suffix? %test
== none

>> suffix? %test.it/file
== none

SUFFIX? can be useful when selecting files from a directory. The example below will only select html and htm files:

foreach file load %. [
    if find [%.html %.htm] suffix? file [
        browse file
    ]
]

4.5 SIGN? Function Added

The SIGN? function returns a positive, zero, or negative integer based on the sign of its argument.

print sign? 1000
print sign? 0
print sign? -1000

The sign is returned as an integer to allow it to be used as a multiplication term within an expression:

new: 2000 * sign val

if size > 10 [xy: 10x20 * sign num]

4.6 COMPONENT? Function Added

COMPONENT? is a helper function that checks for the existence of a named REBOL component.

if component? 'crypt [print "Encryption available."]

if not component? 'sound [print "No sound."]

4.7 SEND Function Updated

The SEND function now includes a /SHOW refinement that will show all TO recipients in the header. By default, recipients are not normally shown.

send/show [bob@example.com fred@example.com] message

In addition the FROM field will include the sender's name as well as an email address. The string in system/user/name is used as the from address. For example, if:

system/user/name: "Fred Reboller"

Then when the email is sent, the from field will now appear as:

From: Fred Reboller <fred@example.com>

If system/user/name is NONE or empty, it will not be used.

Finally, some problems in the /ATTACH refinement have been fixed. Attachments of the form:

send/attach user content [[%file.txt "text message"]]

should work properly now. See 2.5.1 notes on SEND for more information about /ATTACH.

4.8 Miscellaneous Fixes

4.8.1 TYPE? (As used in PARSE)

Fixed the problem reported in the TYPE? function that caused the datatype error in PARSE. Code of the form below will work properly now:

parse [34] reduce [type? 34]
parse [34.5] reduce [type? 34.5]

4.8.2 MOLD/ALL

Fixed the problem with function molding when /ALL refinement is provided.

load mold/all context [test: func [arg] [print arg]]

4.8.3 FTP

Two fixes:

When connecting to a Microsoft IIS based FTP server Rebol did not recognize folders correctly. They were marked as type 'directory but no slash was appended to the file name as done with other types of FTP servers.

In FTP soft-links can now be identified. They can now return an file type of 'LINK.

Thanks: Cal and Reichart at Prolific.com for submitting the above FTP fixes.

5. Core 2.5.1

5.1 Source Code Form for Values of NONE, TRUE, etc.

To better support persistent values between SAVE, MOLD, and LOAD, a new syntactic element has been added to REBOL.

In the past, the source code representation of values like NONE and TRUE required evaluation in order to convert those words into their actual values. For example:

load "NONE"

would return the word NONE, not the value none. This required that your code either evaluate the result (with DO, REDUCE, or TRY) or manually convert the NONE word with code such as:

if value = 'none [value: none]

Thus, if you were storing REBOL data using MOLD or SAVE functions, when you read the data back in, you would need to either evaluate it (e.g. with REDUCE) or add checks for a few specific types of words (as shown above).

To better handle this situation with the literal expression of NONE, TRUE, FALSE, and other values that require evaluation, a new syntactic form has been added to the language:

#[datatype value]

Where datatype indicates the datatype and value provides its value. For simple datatypes such as NONE, TRUE, and FALSE the shorthand form:

#[word]

is also allowed. For example:

#[none]

expresses the value NONE, not the word NONE, even with unevaluated code or data. Similarly,

#[true]
#[false]

express the values of TRUE and FALSE within non-evaluated code.

The LOAD, DO, and other source translating functions have been expanded to accept this new syntax. The example below helps show the change:

block: load " none #[none] true #[true] "

foreach value block [print type? value]

word
none
word
logic

The literal expression of REBOL objects is also allowed by this new format. For example the non-evaluated expression:

#[object! [name: "Fred" skill: #[true]]]

is equivalent evaluating:

make object! [
    name: "Fred"
    skill: true
]

Thus, a persistent (mold/load symmetric) form of objects now becomes available to programmers.

To create or save source code or data using these new datatype expressions, the MOLD and SAVE functions have been given a new refinement called /ALL. This refinement will output the new #[] format for necessary values. For example:

mold/all reduce ["Example" true none time]

word return the string:

["Example" #[true] #[none] 5-May-2002/9:08:04-7:00]

Similarly, using SAVE/ALL would store the above expression to a file.

5.2 Less Aggressive Evaluation (Important!)

Variables are no longer aggressively evaluated.

In pervious versions of REBOL, variables that held set-words, parens, paths, and other types of evaluative datatypes would be evaluated on reference. That is no longer the case.

For example, in earlier versions, if you wrote:

a: first [b/c/d]
print a

the result would be an evaluation of b/c/d. This evaluation caused problems because it is more common to reference such data, not evaluate it. For instance, you want to be able to write:

data: ["test" A: mold/only (10 + 2.5)]

foreach value data [print value]

and smoothly traverse the elements of the data block as simple values. You would not want those values to self evaluate.

This change to evaluation has some deeper implications. For example, it affects any function that specifies literal values within arguments. For example, code such as:

f: func ['word] [print word]

The REBOL design definition of a literal function argument is to accept the argument always as a literal value and NOT evaluate it. However, in the actual implementation it turned out that an evaluation would normally occur when the variable was referenced. (As part of the PRINT in this case.)

For instance, if you passed:

f a/b/c

within the function, the reference to the word would cause the path to be evaluated at that point. Hence, if you referred to the word argument three times, each time it would be evaluated.

This implicit and "aggressive" evaluation, while interesting, was not intuitive and created to hard to find errors with difficult to interpret error messages.

Consider the case where the set-word datatype might be passed as the argument:

f test:

The set word is then evaluated where WORD appeared (in the PRINT line), and it would require an argument. The code would produce an error message that would tell you that the set required an argument. Yet, you would see no set within your code. It would look like an interpreter flaw, when in fact it was doing precisely what you asked.

Since the vast majority of REBOL programs do not rely on this type of evaluation, we've taken it out. This cleans up the semantics of literal arguments, but it also means that where programs depend on passing non-literals and assume that evaluation occurs, they do not. That will break some code, but it is rare. (For example, in the entire source code base of REBOL Technologies, there was only one such case.)

5.3 COMPOSE/ONLY Inserts Blocks

The COMPOSE function now has an /ONLY refinement similar to the INSERT/ONLY refinement. When /ONLY is specified, blocks that are inserted are inserted only as blocks, not as the elements of the block (the default). A REDUCE on the block is not required.

For example:

>> block: [1 2 3]

>> compose [example (block)]
== [example 1 2 3]

>> compose [example (reduce [block])]
== [example [1 2 3]]

>> compose/only [example (block)]
== [example [1 2 3]]

5.4 REMOVE-EACH - Easy Series Element Removal

The new function REMOVE-EACH works in a similar fashion to FOREACH and makes removing values from strings, blocks, and other series much easier.

Also, in most cases REMOVE-EACH is many times faster than using a WHILE loop and the REMOVE function.

The format of REMOVE-EACH is identical to FOREACH except that it uses the result of the block expression to determine removal. REMOVE-EACH iterates over one or more elements of a series and evaluates a block for each. If the block returns FALSE or NONE, nothing is removed, but if the block returns any other value, the items or items are removed.

remove-each value series [expression]

Similar to FOREACH, REMOVE-EACH can operate on multiple elements from the series (and uses the appropriate skip to get to the next set of elements):

remove-each [val1 val2 val3] series [expression]

Note that in addition to modifying the series, REMOVE-EACH also returns the series as its result.

Here are a number of examples.

To remove the odd numbers from block:

>> blk: [1 22 333 43 58]
>> remove-each item blk [odd? item]
== [22 58]
>> probe blk
== [22 58]

To remove all numbers greater than 10 from block:

>> blk: [3 4.5 20 34.5 6 50]
>> remove-each item blk [item > 10]
== [3 4.5 6]
>> probe blk
== [3 4.5 6]

To remove all directories from a directory listing:

>> dir: load %.
>> remove-each file dir [#"/" = last file]
== [%calculator.r %clock.r %console.r %find-file.r...]

To keep only the directories in the listing:

remove-each file load %. [#"/" <> last file]

To remove keep only the .doc files from the listing:

remove-each file load %. [not suffix? ".doc"]

Here is an example of a block that uses multiple values:

blk: [
    1 "use it"
    2 "rebol"
    3 "great fun"
    4 "the amazing bol"
]

remove-each [num str] blk [odd? num]

remove-each [num str] blk [not find str "bol]

REMOVE-EACH also removes characters from a string:

>>  str: "rebol is fun to use"

>>  remove-each chr str [chr = #"e"]
== "rbol is fun to us"

>>  remove-each chr str [find "uno " chr]
== "rblisfts"

5.5 ATTEMPT for Error Handling

The ATTEMPT function is a shortcut for the common REBOL idiom:

error? try [block]

The format for ATTEMPT is:

attempt [block]

ATTEMPT is useful in the cases where you either do not care about the error result or you want to make simple types of decisions based on the error.

attempt [make-dir %fred]

ATTEMPT returns the result of the block if an error did not occur. If an error did occur, a NONE is returned.

In the line:

value: attempt [load %data]

the value may be set to NONE if the %data file cannot be loaded (e.g. it's missing or contains an error). This allows you to write conditional code such as:

if not value: attempt [load %data] [alert "Problem"]

Or, even simpler:

value: any [attempt [load %data] 1234]

In this line, if the file cannot be loaded, then the value is set to 1234.

5.6 EXTRACT Function Updated

The EXTRACT function now includes an /INDEX refinement to allow you to specify what "column" you want to extract. For example:

data: [
    10 "fred" 1.2
    20 "bob" 2.3
    30 "ed" 4.5
]

>> probe extract/index data 3 2
== ["fred" "bob" "ed"]

If index is not supplied, then the first column is extracted.

In addition, the extract function has been fixed to properly extract blocks from a block series.

5.7 SAVE to Memory

The SAVE function can now write its results into memory. This is useful because the SAVE function contains formatting refinements that are found no where else.

To use SAVE to write to memory, specify a binary value rather than a file name. For example:

bin: make binary! 20000 ; (auto expands if necessary)

image: load %fred.gif

save/png bin image

Now the BIN binary holds the PNG formatted image. It was not necessary to write it to a file and read it back in.

5.8 SEND Refinements /Subject /Attach

The SEND function used for sending email has been extended to easily allow a subject line to be specified with a /SUBJECT refinement. This is a handy shortcut. For example:

letter: read %letter.txt

send/subject luke@rebol.com letter "Here it is!"

The above example will send the text of the letter with a subject line as specified. If the /SUBJECT refinement is not given, then the first line of the letter would be used as the subject.

In addition, the SEND function can now include attachment files by providing an /ATTACH refinement. A single file or multiple files can be attached. The specified files can be read from disk or can be provide as a filename and data. The formats are:

send/attach user letter file

send/attach user letter [file1 file2 ...]

send/attach user letter [[%filename data] ...]

You can also combine the last two above formats.

Example attachments are:

user: luke@rebol.com
letter: read %letter.txt

send/attach user letter %example.r

send/attach user letter [%file1.txt %file2.jpg]

send/attach user letter compose/deep [
    [%options.txt (mold system/options)]
]

5.9 Difference for Date/time

The DIFFERENCE function will now provide the time difference (hours, minutes, seconds) between two date/time values.

>> difference now 1-jan-2000
== 20561:20:26

Normally, when you subtract date/time the result is the number of days, not time:

>> now - 1-jan-2000
== 856

5.10 System Port Added

The system port component was added. This component allows direct access to various OS-specific features. For example, the system port can catch Unix and Linux termination signals and perform a controlled shutdown. Under Win32, this port can be used to access win-messages.

More information about the System Port component will be provided as a separate document.

6. Core 2.5.0

6.1 New Sort Function

Several changes and additions have been made to SORT to add functionality, including reverse sorting, hierarchical sorting (sorting on more than one field), sorting of only part of a series, stable sorting (items that are "equal" are not swapped during sorting), and easier specification of sort criteria (without the need for a custom comparator function). The new SORT function is fully backward-compatible.

6.1.1 Terminology

 RecordA single logical item in the series to sort. Usually a character if the series to sort is a string, or a value if the series to sort is a block. If the /skip refinement is used then a record consists of multiple, consecutive elements in the series.
 FieldA part of a record. With the /skip refinement and a skip length of n a field is one of n elements in the record. If the /skip refinement is not used and the series to sort is a block which contains sub-blocks, then a field is one item of a sub-block (NOT the complete sub-block). This allows field-wise sorting of blocked records. In all other cases a field is identical to a record (i.e. each record has exactly one field).
 Field offsetAn integer specifying the offset of a field within a record. For a record consisting of n fields a field offset can be between 1 and n.

6.1.2 Arguments

In addition to the series to sort, the new sort action accepts the following refinements. New behavior is marked with [NEW].

 /caseSort case-sensitive. This only has an effect for fields of type string or character.
 /skip sizeTreat series as records of fixed size. size is of type integer.
 /allUsed in combination with the /skip refinement. [NEW] By default only a single field in a record is used for comparison. If the /all refinement is used then all fields in a record are used for comparison.
 /compare comparatorSpecify a custom comparator. This can be a field offset (type integer [NEW]), a comparator function, or a comparator block [NEW]. See below.
 /reverseSort in reverse. [NEW]
 /part sizeSort only part of a series. (Similar to the use of the /part refinement in copy or change [NEW]).

6.1.3 Comparators

Sorting is performed by comparing and swapping elements, i.e. comparators define the sort order. The following comparators are supported:

  • No comparator (i.e. no /compare refinement). In this case the first field in each record is used for comparison. If the /all refinement is used then all fields in each record are used for comparison. /case and /reverse are observed normally.
  • Field offset (integer) [NEW]. Specifies the field to use for comparison. If the /all refinement is used as well then the specified field is the first field to use, and all subsequent fields are used as well. /case and /reverse are observed normally.
  • Function. Function called by the sort action to compare two records. The records are passed as arguments, and the function needs to return -1, 0 or 1, if the first record is smaller than, equal to or greather than the second record, respectively. [NEW] For backward compatibility the function may also return true or false, where true indicates that the first record is less than or equal to the second record, and false indicates that the first record is greater than the second record. /case is ignored. /reverse is observed normally, i.e. /reverse inverts the meaning of the comparator function. If the /skip refinement is used then the argument passed to the comparison function only consists of the first field in the record, not the complete record. This is for backward compatibility with the old sort function. In order to pass the complete record, in a block, use the /all refinement.
  • Block [NEW]. Comparison dialect specifying the type of comparison in more detail. See below.

Comparison Refinements

The following items can appear in a comparison block:

 field offset (integer)Specifies the offset of the next field to compare. Fields are compared in the order specified.
 reverse (word)Sets the comparison for all subsequently specified fields to reverse.
 forward (word)Sets the comparison for all subsequently specified fields to forward (opposite of reverse).
 case (word)Makes the comparison for all subsequently specified fields case-sensitive.
 no-case (word)Makes the comparison for all subsequently specified fields case-insensitive (opposite of case).
 to (word) field offset (integer)Specifies a range of fields to compare, e.g. [1 to 5] compares fields one to five.

With comparison blocks the /all, /case and /reverse refinements slightly change their behaviors: /all is equivalent to adding "to max-field" to the end of the comparison block, i.e. when the end of the comparison block is reached comparison continues until the end of the record is reached. /case specifies that the default case mode (until a case or no-case word is reached) is case-sensitive. Otherwise it is case-insensitive. /reverse reverses the resulting list as a whole, and is independent of the reverse/forward words in the comparison block.

Examples

a: [10 "Smith" "Larry" 20 "Smith" "Joe" 80 "Brown" "Harry" 50 "Wood" "Jim"]
sort/skip a 3     ; sorts on the first field (number)
[10 "Smith" "Larry" 20 "Smith" "Joe" 50 "Wood" "Jim" 80 "Brown" "Harry"]
sort/skip/compare a 3 2     ; sorts on the second field (last name)
[80 "Brown" "Harry" 10 "Smith" "Larry" 20 "Smith" "Joe" 50 "Wood" "Jim"]
sort/skip/compare/all a 3 2  
; sorts on the second field and following fields (last name and first name)
[80 "Brown" "Harry" 20 "Smith" "Joe" 10 "Smith" "Larry" 50 "Wood" "Jim"]
sort/skip/reverse a 3     ; sorts on the first field (number), in reverse
[80 "Brown" "Harry" 50 "Wood" "Jim" 20 "Smith" "Joe" 10 "Smith" "Larry"]
sort/skip/compare a 3 [2 reverse 3]
; sorts on the last name forward, and the first name in reverse
[80 "Brown" "Harry" 10 "Smith" "Larry" 20 "Smith" "Joe" 50 "Wood" "Jim"]

6.2 File Modes

GET-MODES and SET-MODES functions have been added for file and network ports. Two new port actions are introduced:

 get-modesReturn current modes for an open port.
 set-modesChange modes for an open port.

The get-modes function has the following syntax:

get-modes: native [
    {Return mode settings for a port}
    target [file! url! block! port!]
    modes [word! block!]
]

The block being passed in consists of words defining which modes should be queried. Each word corresponds to one mode. get-modes returns a block which contains pairs of mode names and current mode settings.

Example:

>> get-modes someport [direct binary]
== [direct: true binary: false]

indicating that someport is opened in direct and non-binary (text) mode.

Alternatively a single word can be passed in, in which case get-modes returns the value directly, without putting it into a name-value block.

Example:

>> get-modes someport 'binary
== false

As another alternative a name/value-paired block can be passed in, of the same format as the block get-modes returns. In that case the values are ignored.

Example:

>> get-modes someport [direct: none binary: none]
== [direct: true binary: false]

The set-modes function has the following syntax:

set-modes: native [
    {Change mode settings for a port}
    target [file! url! block! port!]
    modes [block!]
]

The block being passed in consists of name-value pairs describing the modes to be changed. A block returned by get-modes can be passed as an argument to set-modes. set-modes returns the port that was passed as an argument.

Example:

>> set-modes someport [direct: false binary: false]

The mode block accepted by set-modes is actually an object-style initialization block and allows multiple names to reference the same value.

Example:

>> set-modes someport [direct: binary: false]

6.2.1 Getting Lists of Modes

get-modes supports a few "special" modes, which do not return mode settings for a specific port, but rather a set of modes that is applicable for a file (or directory, socket etc.). These are "file-modes", "copy-modes", "network-modes" and "port-modes". If any of these modes are specified in a get-modes request then the response contains a block of matching modes which are available on the current filesystem.

>> get-modes somefileordir 'port-modes
== [direct binary lines no-wait (...a few more...) ]

>> get-modes somefileordir 'file-modes
== [file-note creation-date archived script (...a few more...) ]

>> get-modes someudpsocket 'network-modes
== [broadcast multicast-groups type-of-service]

The above example is for an Amiga. Note that the mode block returned by any of these special requests is identical for all files and directories within a filesystem (and all sockets within a scheme), i.e. it varies per platform and possibly per filesystem and scheme, but not per file or socket. The purpose of this feature is only to provide a mechanism to obtain a list of supported modes, not to obtain the actual mode settings. To obtain the actual mode settings for a port the returned block has to be used in another call to get-modes:

>> get-modes somefileordir get-modes somefileordir 'file-modes
== [file-note: "cool graphics" creation-date: 1-Jan-2000 
    archived: true script: false]

The difference between "file-modes" and "copy-modes" is:

 file-modesReturn all modes of the underlying data (typically a file), regardless of how it was opened.
 copy-modesSame as file-modes, but only return those modes which are safe to copy, i.e. which can (and should) be included in a set-modes call when creating a new file, in order to create an exact clone of an existing file. If a platform provides file properties which are not safe to copy or which necessarily vary on copied files (e.g. Unix inodes) then those modes would show up in the block returned by file-modes, but not by copy-modes.

Copying all file properties from file1 to file2 can be done with the following call:

>> set-modes file2 get-modes file1 get-modes file1 'copy-modes

6.2.2 Modes Available

File-modes

  • status-change-date, modification-date, access-date, backup-date, creation-date: REBOL date. modification-date is available on all platforms. status-change-date is available in Unix. access-date is available in Unix and Windows. creation-date is available in Windows and MacOS. backup-date is available in MacOS. All modes are settable and gettable, except that modification-date and access-date are not settable in Elate.
  • owner-name, group-name: REBOL string (user/group name). Available in Unix.
  • owner-id, group-id: REBOL integer (user/group id). Available in Unix and AmigaOS (>=V39).
  • owner-read, owner-write, owner-delete, owner-execute, group-read, group-write, group-delete, group-execute, world-read, world-write, world-delete, world-execute: REBOL logic. All -read, -write and -execute modes are available in Unix, BeOS, QNX and Elate. owner-read, owner-write, owner-execute and owner-delete are available in AmigaOS. All group- and world- modes are available in AmigaOS >=V39. owner-write is also available in Windows (mapped to the inverse of the Windows "read-only" bit).
  • comment: REBOL string (file comment). Available in AmigaOS only.
  • script, archived, system, hidden, hold, pure: REBOL logic (additional flags). Script, hold and pure are available in AmigaOS only. Archived is available in AmigaOS and Windows. System and hidden are available in Windows only.
  • type, creator: REBOL string. Available in MacOS only.

Platforms which only support a single file date export it via modification-date. Similarly, platforms which do not support multi-user file access modes make the file access modes available via owner-read/write/delete/execute.

Port-modes

  • read, write, binary, lines, no-wait, direct: REBOL logic. Binary, lines and no-wait are settable.

Network-modes

  • broadcast: REBOL logic. UDP only. Setting this to true allows sending broadcasts from a socket. All platforms except BeOS.
  • multicast-groups: REBOL block of blocks. UDP only, describes which multicast groups a socket has joined. Each sub-block consists of two IP addresses (tuples): the multicast group and the IP address of the interface on which the multicast group was joined. Typically available in MacOS, Windows, most Unix platforms, QNX and AmigaOS (Miami/MiamiDx only). Availability is determined at runtime and varies with the OS version and TCP/IP protocol stack version.
  • type-of-service: REBOL integer. UDP and TCP. This is the value of the 8-bit "TOS" field in IP headers. Typical values are 0 (default), 2 (minimize cost), 4 (maximize reliability), 8 (maximize throughput) and 16 (minimize latency), but the interpretation of this field is up to the TCP/IP stack and intermediate routers, and not enforced by REBOL. All platforms except BeOS.
  • keep-alive: REBOL logic. TCP only. Setting this to true forces TCP to send "keep-alive" packets after a certain period of time (typically 4 hours). All platforms except BeOS.
  • receive-buffer-size, send-buffer-size: REBOL integer. UDP and TCP. Size of receive and send buffer within the TCP/IP stack. Default values and allowed ranges vary widely between platforms. Primarily useful for UDP. Increasing this values usually does NOT improve performance. All platforms except BeOS.
  • multicast-interface: REBOL string. UDP only. The default interface to use for multicasting. Same platforms as multicast-groups.
  • multicast-ttl: REBOL integer. UDP only. The time-to-live value (maximum propagation distance) of multicasts. Same platforms as multicast-groups.
  • multicast-loopback: REBOL logic. UDP only. If set to true sent multicasts are looped back to the local socket. Same platforms as multicast-groups.
  • no-delay: REBOL logic. TCP only. Disables the Nagle algorithm. Most protocols perform better if this is set to false. It should only be set to true if a protocol is interactive in nature AND relies on precise event timing in combination with queueing (e.g. X11). All platforms except BeOS.
  • interfaces: REBOL block of objects. Each object represents one network interface and currently contains the following fields: "name": interface name (on some platforms this is a dummy name). "address": local IP address. "netmask": subnet mask. "broadcast": broadcast address. "remote-address": remote IP address for point-to-point interfaces. "flags": a block of words describing interface properties, currently supported words are "broadcast" (interface supports broadcasting), "multicast" (interface supports multicasting), "loopback" (interface is the loopback interface) and "point-to-point" (interface is a point-to-point interface, as opposed to a multi-drop interface). Some values may be none (e.g. "remote-address" on a multi-drop interface). In Windows all interfaces appears as multi-drop (including PPP), with dummy netmasks. Available in all platforms, except BeOS, Elate, WinCE. Not settable.

6.2.3 Using File Forks

The /custom refinement to read, open and write allows access to different forks of a file (currently useful for MacOS only).

open/custom %myfile [fork "name"] ; Specify which fork to open.

The specified fork name defines which fork to open:

If no fork is specified (no fork specifier in the custom block or none is passed instead of "name"), then for non-Mac platforms the file is opened normally. For Mac the data fork is opened. If the /new refinement is used then the file size is reset to zero bytes. For Mac this means that all forks are reset to zero bytes. (Note: this behavior has changed from Core 2.3. Previously open/new on Macintosh would only reset the size of the data fork, and there was no way to reset the size of the resource fork.)

If a fork is specified by name then that fork is opened. If the /new refinement is used then the size of only that fork is reset to zero bytes. If the fork does not exist (and, for write access, cannot be created) on the current filesystem then an error is thrown.

Non-Mac platforms only have a single fork named "data". Mac platforms have two forks, named "data" and "resource".

6.2.4 Finding All Forks

This is done using the mode mechanism, in a way similar to finding all supported modes.

>> get-modes somefile 'forks
== ["data" "resource"]

Example above on Mac. For all other platforms only ["data"] would be returned.

6.3 Serial Port Access

This specification describes the creation and operation of serial communication ports within REBOL. Serial ports were supported in version 2.3 but were not documented.

6.3.1 Specifying a Serial Port

Serial ports are created in the same manner as other ports within REBOL. The scheme name for serial ports is "serial:". URL's are encoded with the different fields separated by slashes. For example,

port: open serial://port1/9600/8/none/1

The order of values in the serial URL scheme is not significant, as the type of field can be determined by the content. (Note, you can also use a MAKE PORT object rather than a URL to specify a serial port.)

The specification of a serial port may include the device number, the communication speed, the number of data bits, the parity and number of stop bits. The specification information can be specified directly by setting the appropriate fields within the port specification object or by creating a URL which contains the same information. Any field not specified will be given a default value.

The default serial port settings are:

device: port1
speed: 9600
data-bits: 8
parity: none
stop-bits: 1

Within a port specification, the various parameters are stored in the following object fields:

host:           device
speed:          speed
data-bits:      data bits
parity:         parity
stop-bits:      stop bits

The portN specification is an indirect reference to the communication device. It refers to the Nth device defined in the System/ports/serial block. This block is initialized by default depending on the system being used and can be modified in user.r to reflect any local requirements.

For example, on Windows the block might be defined as:

System/ports/serial: [ com1 com2 ]

or if COM1 is being used by the mouse, it might just be:

System/ports/serial: [ com2 ]

On unix-style systems, the block might be defined as:

System/ports/serial: [ ttyS0 ttyS1 ]

or if the first device should correspond to COM2:

System/ports/serial: [ ttyS1 ttyS0 ]

Thus, the ports can be specified in a machine indpendent manner while the machine specific definition can be controlled using the serial definition block in System/ports/serial.

6.3.2 Operation

Serial ports are always opened as direct ports in much the same way as console and network ports. They may be opened as either /STRING or /BINARY with the default being /STRING. They are opened by default as asynchronous, but may be made synchronous by using the /WAIT refinement. When operating asynchronously, any attempts to copy data from the port will return NONE if no data is present. When operating synchronously, the copy will block until data is available.

Data can be written to the port using the INSERT native. Data can be read from the port using the PICK, FIRST or COPY natives with the usual ramifications. As usual with direct ports, the REMOVE, CLEAR, CHANGE and FIND functions are not supported.

The UPDATE function can be used to change port parameters. For example, to change the speed after an initial connection has been established, you could just do:

ser-port: open serial://9600
ser-port/speed: 2400
update ser-port

Changing the device number or the System/ports/serial and calling UPDATE will have no effect. Once the port has been opened with a particular device, the device can't be changed.

There are two additional port fields that can't be set with a URL, but can be set in a port specification block or by manually changing them. The RTS-CTS field specifies whether hardware handshaking should be used on the port. The default is ON. To change the default, do:

ser-port/rts-cts: off
update ser-port

A timeout value can be specified by modifying the timeout field in the port structure. The timeout value only applies to serial ports that are opened with the /wait refinement. When the timeout expires, a serial port timeout error will be generated. To set the timeout value do:

ser-port/timeout: 10        ; 10 second timeout

Serial ports work properly with the WAIT native.

6.4 Objects

  • SYSTEM/LOCALE object added. Currently has month and day names. *Weekdays are separate strings in system/locale/days.
  • CONTEXT function added as a shortcut to MAKE object!.
  • You can now QUERY an object. QUERY will return a block containing the fields that have been modified in an object since its creation or since it was last passed to QUERY/clear. QUERY will return none if there have not been any changed fields. QUERY/clear will clear the modified state of all the fields in an object.
  • Objects now accept LOGIC! values as arguments for to pick (for consistency with blocks).

6.4.1 Make Object Object

You can now make an object out of two other objects, a "template object" and a "spec object". When making a new object out of two other objects, the bindings of words coming only from the "spec object" will be maintained, words shared by both the template object and the spec object will take their values from the spec object. This will cause some differences in behavior because the block spec approach is lexical and the object spec approach is definitional.

6.4.2 Third Object

You can use THIRD on the object to get back a block of set-word value pairs from the object:

z: make object! [a: 99 b: does [a + 1]]
t: third z
== [a: 99 b: func [][a + 1]]

The block returned from THIRD on an object is like an object spec block, however the set-words are bound to their object. This block is like a snapshot of the object's values at that time. You can also use the returned block to set values in the object:

set first t 199
z/b
== 200

6.5 Mold and Load Changes

  • MOLD/only does not produce the outermost [] in the resulting string.
  • Molding a recursive block or object will print [...] when on the second instance of the recursive item. So, you can now PRINT MOLD SYSTEM !
  • Molding strings greater that 50 characters containing unbalanced "{" characters are now reloadable.
  • Added /all refinement to LOAD. LOAD/all of a script does not evaluate the REBOL header. LOAD/all always returns a block.
  • LOAD/next/header results in a block with the evaluated header followed by the rest of the script as a string.
  • Loading strings with CTRL chars greater than CTRL-Z now allowed.
  • Added script HEADER/CONTENT field. When set TRUE, the script's entire source text can be accessed from SYSTEM/SCRIPT/HEADER/CONTENT (when evaluated with DO) or from the header object (when loaded with LOAD/header or LOAD/next/header). This allows your script to access other data that may be part of its script file (e.g. the REBOL archive format, RIP).

LOAD function refinement combinations:

LOAD/Refinement

Eval Header?

Returns

load

yes

returns script (data). If file contains a single value (like 1234), then this returns just that value. If there are multiple values, then it returns a block.

load/next

no

[first-val { rest of script }] -- returns a value followed by a string. This refinement lets you parse REBOL files, one value at a time (for operations like pretty printing and colorizing.)

load/next/header

yes

[header-obj {rest of script}] -- same as load/next but includes the evaluated header object.

load/header

yes

[header-obj rest of script] -- returns the script, starting with the REBOL header as the first value.

load/all

no

[all of script as data] -- returns the script, always as a block, even if it's just a single value (very handy for cases where you always want data as a block, even if it's a single value).

load/next/all

no

[first-val { rest of script }]

load/header/all

yes

[header-obj rest of script]

load/next/header/all

yes

[header-obj {rest of script}]

The ALL refinement will be ignored when other refinements are present.

6.6 File and Port Changes

  • Added asynchronous wait-able DNS for Unix and Windows. For example: open dns:///async, then insert/wait/copy.
  • Asynchronous HTTP better supported. You can open/direct/no-wait an HTTP request and use WAIT and COPY to receive the results as they arrive.
  • WAIT [0 port] now returns the port if it has data, none otherwise.
  • Added WAIT/all refinement, which causes wait to return a block of all ports that have data.
  • The /no-wait refinement allows a port to be opened in non-blocking mode. COPY on a non-blocking port returns an empty string unless the end of the port has been reached, in which case it returns none.
  • WAIT now supports port handlers (http, tcp etc.) in /direct mode.
  • Added AWAKE field in port-specs and root protocol to specify a block or function called when wait is about to wake up. Used to implement background processing.
  • WAIT works correctly on /lines ports opened without /with.
  • TO-LOCAL-FILE and TO-REBOL-FILE functions can be used to convert to and from the local OS file path formats.
  • Added local-port, remote-ip and remote-port fields to port spec for consistent values independent of port creation.
  • MAKE-DIR/deep creates all needed directories in a long path.
  • CONNECTED? native for most platforms.
  • Fixed incorrect port-id assignment on accepted sockets.
  • Fixed bug that would prevent UDP listen sockets from responding to packets from different origins.
  • SPLIT-PATH was modified to properly split the path and target of a file path.

6.7 Network Protocol Change (APOP, IMAP)

  • Added APOP - Authentication for pop:// that does not send passwords to the server in clear text.
  • Added imap:// protocol. URL format and behavior identical to pop://, plus additional URL formats specified in RFC 2192.
  • Fixed SEND when /header and no FROM address is given
  • Fixed do-send to change email lines with only a single "." to have two periods so those emails will not blow out anymore.

6.8 Data Series Changes

  • HASH! and LIST! datatypes now offer more complete, consistent, reliable, and faster operation.
  • The SELECT, FIND, UNION, INTERSECT, EXCLUDE, DIFFERENCE, and UNIQUE functions accept a /skip refinement to specify data size.
  • UNIQUE accepts the /case refinement.
  • TO-BINARY of tuples now uses the tuple values instead of forming the tuple.
  • JOIN on binary values now joins as binaries, not FORMed strings.
  • FIND now works on all types of functions properly.
  • FIND/REVERSE works for bitsets.
  • Pick on objects and functions with negative number fixed.
  • Fixed bug in ENBASE that could cause invalid characters to be inserted into a base-64-encoded string.
  • Removed /only refinement from DIFFERENCE (EXCLUDE is equivalent).
  • MINIMUM-OF and MAXIMUM-OF series. You can use MINIMUM-OF and MAXIMUM-OF on a single series argument which will return the series offset to the least or greatest contained value respectively. Eg:
minimum-of reduce [pi .099 10 * 100]
== [0.099 1000]   

maximum-of reduce [pi .099 10 * 100]
== [1000]

6.9 Math Related Changes

  • Added CHECKSUM/secure and RANDOM/secure, producing cryptographically secure checksums and random numbers respectively.
  • Added CHECKSUM/hash and CHECKSUM/method (same as checksum/secure, but with a selectable algorithm: 'md5 or 'sha1), and checksum/key (calculates a keyed message digest). MD5 added as an alternative checksum algorithm.
  • Subtraction of a date! value months bug fixed.
  • Time! values can convert to integers and decimals.
  • NOW/precise returns greater precision on time. Useful for timing events.

6.10 Command Line Changes

  • REBOL startup command line now accepts "--" to signal the end of startup switches. Remaining items on the command line are arguments to be passed to the REBOL script. This also allows REBOL to start without a script but with arguments passed.
  • When starting from the command line, system/script/args == string of all args, system/options/args == block of separate args. All items following the specification of the script are considered arguments.
  • REBOL now deals with arbitrary amount of command line arguments-- no fixed size.

6.11 Console

  • Console tab completion now completes as much of the defined word or file path as possible.
  • Added proper console reinitialization code when REBOL is woken up after Ctrl-Z followed by "fg" (for Unix and shells with job control).
  • File name completion in the console is now case-insensitive for operating systems that have case-insensitive file systems (Windows, AmigaOS etc.)
  • Screen now gets cleared on first console output, not signon message.

6.12 Control

  • A BREAK used in the first block of a WHILE will cause a BREAK from the while loop.
  • CATCH and THROW work more reliably in more cases.
  • FOREACH returns correct value on empty series.

6.13 Interpreter

  • Binding speed greatly improved for top-level words.
  • Indefinite extent fixed for many cases (the USE function).

6.14 Other Changes

  • HAS function added as a shortcut to define functions with local variables but no arguments.
  • Fixed CONFIRM to throw error on bad pick operation.

7. Interpreter Fixes

The following internal interpreter problems have been fixed.

  1. Series Expansion: Significant performance and memory problem has been fixed resulting in many times greater speed in some types of uses. This change speeds up MOLD and SAVE by many times.
  2. Lit-path! comparison works properly
  3. Time zone bug in date comparison fixed
  4. Handling of "--" in command line arguments
  5. Tab expansion of words in console
  6. Component version numbers added to the boot message
  7. Increased the global word limit to 8000
  8. Potential crash during expansion and recycling of hash! values
  9. Potential crash when recycling open, unreferenced ports
  10. Port cleanup to close ports in the correct order

8. Networking Fixes

The following fixes were made to networking:

  1. DNS - Unix only: fixed lockup when DNS helper process dies unexpectedly.
  2. DNS - Unix only: DNS helper process no longer remains a "zombie" if the main process is killed.
  3. FTP - conflicts with generic proxy setups fixed
  4. FTP - allow more response codes from CWD command in FTP
  5. HTTP - proxy authentication added
  6. HTTP - POST linefeed conversion problem fixed
  7. HTTP - forwarding fixed where host name in header was not updated
  8. POP - will try APOP if port/algorithm is set to 'apop (workaround for bug in some POP servers).
  9. TCP - On Windows only: TCP listen sockets no longer allow multiple listeners on the same port. Workaround for bug in Windows TCP/IP stack regarding SO_REUSEADDR.

9. Other Function Fixes

Fixes to natives and functions include:

  1. COMPRESS/DECOMPRESS - series offsets are now allowed
  2. DEBASE - potential crash fixed
  3. DEBASE - series offsets are now allowed
  4. FIND - when using bitset with chars greater than 127
  5. FIND/MATCH/CASE - fixed
  6. LOAD/MARKUP - potential crash fixed
  7. MAKE - potential crash with make object! object! fixed
  8. MAKE-DIR/DEEP - fixed bug
  9. SET-MODES - fixed file date setting when no time value is provided
  10. SORT - handles hashed blocks now, and potential crashes fixed
  11. UNION, INTERSECT, etc. - series offsets are now allowed on the second argument

10. Summary of New Features in 2.3

The following table shows a summary of new features in REBOL/Core 2.3:

  • load/markup refinement - returns a block of tags and text
  • repend function - reduces argument before appending
  • replace/case - allows case sensitive replace
  • ?? function - prints useful debugging function
  • to-pair function - converts values into pairs
  • pair datatype - new datatype that represents vectors and coordinates
  • offset? function - returns the offset between series positions
  • does function - shortcut for creating functions without arguments
  • unique function - returns a series with duplicates removed
  • functions accepting pair! - many existing functions now accept the pair value
  • make-dir/deep refinement - allows creation of multiple depth directories

11. Summary of Enhancements in 2.3

The following table shows a summary of enhancements made to existing functions and global objects in REBOL/Core 2.3:

  • help function - information is formatted differently. Help can now perform searches over internal documentation
  • http user-agent - Http handler now allows setting the http user-agent
  • value/selector return - returns the set value, not the aggregate value
  • random function - now operates on negative values and tuples
  • system/options/path - indicates directory the running rebol script is in
  • what function - changed the way functions are listed; they are sorted now
  • build-tag - accepts a wider range of values
  • parse - to parse blocks and strings
  • if, any and all functions - changed false return values to none
  • pop handler - contains information on messages sizes
  • and, or, xor - AND, OR, and XOR now work on binary types. The resulting binary will be as long as the longest of the two binary values. The bitwise operations use the binary value's offset to determine where to start.
  • functions accepting pair! - many functions now accept the pair value
  • query function - changed to allow the querying of objects to determine changed words
  • load/next - changed behavior with respect to script header
  • tab completion - changed to show a list of possibilities upon hitting tab twice

12. Summary of Fixes in 2.3

The following table shows a summary of fixes incorporated into REBOL/Core 2.3:

  • to-block function - fixed to work properly on path literals
  • to-word function - fixed to properly convert set-word values into word values
  • trim/lines - fixed so that it removes all extra white space
  • Networking - Network activity can now be interrupted with the escape key
  • split-path function - fixed so that the lowest level path splits correctly

13. New Functions and Refinements in 2.3

The following new functions and refinements are incorporated in to REBOL/Core 2.3:

13.1 Pair Datatype

Pairs are datatypes used to describe the (x,y) coordinates of a point. This datatype is most commonly used to describe graphical objects and their screen positions, sizes offsets, etc. A pair datatype consists of two values separated by an upper or lowercase 'x' as in 10x20. Example: A: 10x20, defines A as a pair datatype consisting of the coordinates x=10, y=20. These values can be individually accessed using the refinements /x and /y as in: print A/x, which would print the value 10.

13.2 Make-dir/deep

Using the /deep refinement for make-dir will cause all directories in the supplied path to be created if those directories do not already exist.

The following example uses make-dir/deep to create a long directory structure:

probe dir? %/c/abc
false
make-dir/deep %/c/abc/def/ghi/jkl/mno/pqr/stu/vwx/yz/
probe dir? %/c/abc
true
probe dir? %/c/abc/def/ghi/jkl/mno/pqr/stu/vwx/yz/
true

If make-dir/deep fails any directories that were created before failing will be removed.

13.3 Unique

Unique accepts a series argument and returns another series. The result of unique is a copy of the passed in series with out any duplicate items.

Here are some examples demonstrating the behavior of unique:

probe unique "abcabcabc"
"abc"
probe unique [1 2 3 3 2 1 2 3 1]
[1 2 3]

The /case refinement may be used with unique to make the operation case sensitive.

13.4 Does

Use does to create functions with out arguments or locally defined words. For example:

get-script-dir: does [probe system/options/path]
probe get-script-dir
%/usr/local/rebol/

13.5 Offset?

Offset? takes two series as arguments and returns the distance between their two indexes.

The following example shows offset? being used on the same series:

colors: ["red" "green" "blue" "yellow" "orange"]
colors-2: skip colors 3
probe offset? colors colors-2
3

The example below shows how offset? can also be used with two different series:

str: "abcdef"
blk: skip [a b c d e f] 4
probe offset? str blk
4

13.6 Load/Markup

Using the /markup refinement for load causes the string, file or URL argument to be treated as markup data. (Files and URLs are first read in as strings by load.) All tags found in the argument to load/markup will be converted to a tag! value, and all other non tag data is left as a string. The result of load/markup is a block of tag! values and strings.

The next example demonstrates the behavior of Load/markup:

probe load/markup {<head> 123 abc <head>}
[<head> { 123 abc  } </head>]

13.7 Repend

Repend is short for "reduce append". Repend takes two arguments. The first argument is a series. The second argument to repend is reduced before it is appended to the first argument.

Here are some examples of using Repend:

a: "AA" b: "BB" c: "CC"
probe repend [] [a b c]
["AA" "BB" "CC"]
probe repend "" [a b c]
"AABBCC"

13.8 Replace/case

The replace function now has a /case refinement that forces case sensitive replacements. By default replace is case insensitive.

This example demonstrates using replace on a block without /case:

probe replace/all [A a B b A a B b] 'A 'C
[C C B b C C B b]

This example demonstrates replace on a block with /case:

probe replace/all/case [A a B b A a B b] 'A 'C
[C a B b C a B b]

This example demonstrates using replace on a string without /case:

probe replace/all "ABCabcDEFdefABCabcDEFdef" "abc" "xxx"
"xxxxxxDEFdefxxxxxxDEFdef"

This example demonstrates using replace on a string with /case:

probe replace/all/case "ABCabcDEFdefABCabcDEFdef" "abc" "xxx"
"ABCxxxDEFdefABCxxxDEFdef"

13.9 ??

?? accepts one argument of any data type.

As an aid to debugging, if a word is supplied to ?? that word will printed out along with the mold of its value. Like the behavior of probe, ?? returns the unevaluated value of its argument so that ?? can be used transparently within arbitrary REBOL expressions.

When ?? is used directly on a non word value the molded value is printed and the unevaluated value is returned.

The next example demonstrates using ?? on a word defined to a block:

blk: ["a" block 'of [values]]
?? blk
blk: ["a" block 'of [values]

The next example demonstrates using ?? on a word defined as a function:

?? probe
probe: func [
    {Prints a molded, unevaluated value and returns the same value.}
    value
][
    print mold :value :value
]

The next example demonstrates using ?? on a non word value:

?? 12:30pm
12:30

13.10 To-pair

To-pair accepts one argument of any data type.

To-pair attempts to convert the supplied argument into a pair value.

The next example demonstrates using to-pair with a block:

probe to-pair [11 11]
11x11

The next example demonstrates using to-pair with a string:

probe to-pair "11x11"
11x11

14. Enhancements in 2.3

14.1 Parse Block

Under REBOL/Core 2.3 parse can be used on blocks. The ability to create dialects in REBOL is enhanced through the ability to parse blocks.

Refer to the User's Guide for more information on using parse with blocks.

14.2 POP handler change

The POP mail handler has been enhanced to store the total size of messages and the sizes of individual messages. The total size of messages can be found stored as an integer representing bytes in the POP port's locals object under the total-size field. Individual message sizes are stored as a block of message numbers and byte sizes in the port's locals object under the sizes field. Examples:

Total size of all messages in a POP connection:

pop: open pop://login:pass@mail.site.com/
size: probe pop/locals/total-size
735907
print join to-integer size / 1024 "K"
718K

Sizes of individual messages:

pop: open pop://login:pass@mail.site.com/
sizes: pop/locals/sizes
foreach [mesg-num size] sizes [
    print [
        "Message" mesg-num "is" join to-integer size / 1024 "K"
    ]
]
Message 1 is 2K
Message 2 is 2K
Message 4 is 1K
Message 5 is 9K
Message 6 is 1K
Message 7 is 678K
Message 8 is 1K

14.3 Tab Completion

Tab completion for the REBOL console has been expanded to show a list of possible matches when pressing tab a second time.

To see the behavior of REBOL's tab completion, type fun at the REBOL prompt and then hit the tab key. Tab completion will expand fun to func. Hitting the tab key once more will show the following: function!, function?, func and function as possible matches for the word you are typing in.

14.4 Load's /Next Refinement

The behavior has changed for load's /next refinement. Load/next will not skip over a REBOL script header. To load a script header as an object using the /next refinement, include the /header refinement. Examples:

Saving a simple script to the file simple.r:

save %simple.r [
    REBOL [
        title: "simple"
        file:  %simple.r
        ]
    print "simple script"
]

Using load/next on a simple script:

script: probe load/next %simple.r
[
    REBOL { [
    title: "simple"
    file: %simple.r
]
print "simple script"}]
probe load/next second script
[[
        title: "simple"
        file: %simple.r
    ] {
print "simple script"}]

Using load/next/header on a simple script:

script: probe load/next/header %simple.r
[
    make object! [
        Title: "simple"
        Date: none
        Name: none
        Version: none
        File: %simple.r
        Home: none
        Author: none
        Owner: none
        Rights: none
        Needs: none
        Tabs: none
        Usage: none
        Purpose: none
        Comment: none
        History: none
        Language: none
    ] {
print "simple script"}]
probe load/next second script
[
    print { "simple script"}]

14.5 Query Function

Query now accepts objects, returning a block of modified words in that object or none.

The block returned from using query on an object contains the words which have been modified since the object's creation or since it was last passed to query/clear.

The words in the returned block are bound to the context of the object. Using query, changes to an object can be tracked.

The following example illustrates the use of query on objects:

Defining an object:

obj: make object! [
    field-one: "string"
    field-two: 123
    field-three: 11:11:01
]

Using query on obj immediately after the object was created will return none:

probe query obj
none

Using query after a field within obj has changed:

obj/field-two: 456
obj/field-three: 12:12:02
mod: query obj<br>
probe get mod/1
456
probe get mod/2
12:12:02

Query returned a block of modified words bound to obj.

Use query/clear to reset the modified state of the object.

The next example demonstrates clearing the modified state of the fields in obj:

query/clear obj<br>
probe query obj
none

Query on obj returned none because the modified state was reset using query/clear.

14.6 Functions Accepting Pair Values

Following is a list of the functions that have been extended to accept pair values:

  • Addition Functions + and Add
probe 12x12 + 12x12
24x24
probe add 11x11 11
22x22
  • Subtraction Functions - and Subtract
probe 24x24 - 12x20
12x4
probe subtract 24x24 12
12x12
  • Multiplication Functions * and Multiply
probe 12x12 * 12x12
144x144
probe multiply 12x12 24
288x288
  • Division Functions / and Divide
probe 12x12 / 2x4
6x3
probe divide 24x24 4
6x6
  • Remainder Functions // and Remainder
probe 24x24 // 5x3
4x0
probe remainder 24x24 10
4x4
  • Minimum Functions Min and Minimum
probe min 12x12 12x11
12x11
probe minimum 23x24 24x24
23x24
  • Maximum Functions Max and Maximum
probe max 12x12 12x11
12x12
probe maximum 23x24 24x24
24x24
  • Negate Function
probe negate 12x12
-12x-12
probe negate 12x0
-12x0
  • Absolute Functions Abs and Absolute
probe abs -12x-24
12x24
probe absolute -12x24
12x24
  • Zero? Function
probe zero? 12x0
false
probe zero? 0x0
true
  • Pick, First and Second Functions
probe pick 24x12 1
24
probe pick 24x12 2
12
probe pick 24x12 3 ; anything beyond 2 returns NONE
none
probe first 24x12
24
probe second 24x12
12
  • Reverse Function
probe reverse 12x24
24x12

14.7 Random Function

The random function now takes negative values. When a negative value is used, random returns a number between -1 and the negative value. Examples:

loop 5 [print random -5]
-5
-5
-3
-3
-5
loop 5 [print random -$5]
-$4.00
-$5.00
-$3.00
-$5.00
-$3.00

14.8 System/options/path

The word path has been added to the system/options object. System/options/path is the directory where the current REBOL script was executed from. Example:

print system/options/path
/C/REBOL/

14.9 What Function

What now alphabetically sorts the list of defined functions printed.

14.10 If, Any, and All Functions

If, any and all now return none as a "fail" value where they had previously returned false.

Here are some examples of the new return value:

val: 10
probe if val = 100 [print "matched"]
none
val: 10
probe any [val = 100 val = 1000 val = 10000]
none
set [val1 val2 val3] [10 100 2000]
probe all [val1 = 10 val2 = 100 val3 = 1000]
none

14.11 Help

Use the help function to get the description, arguments, and refinements for all functions, or to inspect other REBOL values. Type help and the function name at the prompt:

>> help cosine
USAGE:
    COSINE value /radians
DESCRIPTION:
     Returns the trigonometric cosine in degrees.
     COSINE is a native value.
ARGUMENTS:
     value -- (Type: number)
REFINEMENTS:
     /radians -- Value is specified in radians.

Help can also be used to search REBOL's internal documentation. Here is an example of using help with a word:

>> help path
Found these words:
    clean-path     (function)
    inst-path      (object)
    lit-path!      (datatype)
    lit-path?      (action)
    make-dir-path  (function)
    path!          (datatype)
    path?          (action)
    set-path!      (datatype)
    set-path?      (action)
    split-path     (function)
    to-lit-path    (function)
    to-path        (function)
    to-set-path    (function)

15. Fixes in 2.3

Here are the fixes made since version 2.3.

15.1 Split-path Function

When splitting the lowest level of a file path (%. or %/), the second value in the returned block will be none. When splitting a file (%file), the first value in the returned block will be the current directory (%./) and the second value the file itself (%file).

Here are some examples of using split-path:

probe split-path %.
[%./ none]
probe split-path %./
[%./ none]
probe split-path %/
[%/ none]
probe split-path %file.txt
[%./ %file.txt]

15.2 Network activity interruptible

Network activity may now be interrupted by pressing the escape key (esc).

A known exception is network activity on the BeOS version of REBOL/core which currently is not interruptible with the escape key.

15.3 Trim/lines

Trim/lines now removes all extra white space in a string, compressing all occurrences of whitespace into single spaces.

The following example demonstrates the behavior of trim/lines:

str: {
    line one
        line two
    line five
    line eight
}
probe trim/lines str
"line one line two line five line eight"

15.4 To-word Function

To-word now accepts set-word values as an argument.

The behavior of to-word with a set-word as an argument is demonstrated in the following example:

probe to-word first [data: "string of data"]
data
probe type? to-word first [data: "string of data"]
word!

15.5 To-block Function

When a path literal is used as an argument to to-block, a block is returned containing the path components as words.

The following example demonstrates the use of to-block with a literal path value:

probe to-block 'system/options/path
[system options path]

16. Other Changes (From Addendum Document) in 2.3

  • REBOL 2.3 has an additional +q (non-quiet) command line flag
  • DIFFERENCE renamed EXCLUDE, though DIFFERENCE is retained as a synonym for EXCLUDE
  • IF has a new /else refinement
  • PARSE now accepts any series instead of just a string
  • TRACE has a new /function refinement which allows you to trace function calls
  • SLASH and BACKSLASH are pre-defined values
  • DIRIZE is a function which turns a file into a directory if the file is not a directory already
  • APPEND has new /only refinement which behaves like INSERT/only
  • The system object contains a COMPONENTS block for future additions
  • The systen object now contains user/home which holds the location of the $HOME environment variable
  • These fields have been added to ports: localip, localservice, remoteservice, lastremoteservice, direction, key, strength, algorithm, block-chaining, init-vector. Some of these fields are necessary for security features of other REBOL products.
  • The words action! and unset! no longer are unset.
  • system/options/home/public/ is writeable by default
  • The following other datatypes exist in REBOL/core 2.3 although they are not all usable: event! library! struct! routine! image!
  • when a path is used to set a value in a datatype, and the datatype is a scalar, it sets it in the scalar that was used in the path. i.e., date/minute: 1 now data/minute will give 1
  • Read or load of %/ now returns drives on WIN32 and Amiga.
  • Molding an object! with a field set to a literal word value is now handled correctly
  • UDP listen ports work now
  • Support has been added for COPY using UDP ports
  • Scripts can now specify the version and product required to run the script in the REBOL header NEEDS field
  • RANDOM now works on tuples
  • Poking a tuple is now clipped at 0 and 255
  • New native connected? attempts to determine if the computer is connected to the internet
  • The following are functions and natives found in REBOL 2.3 which are disabled: FREE BROWSE LAUNCH

Updated 15-Apr-2005 - Copyright REBOL Technologies - Formatted with MakeDoc2
REBOL.com Documents Manual Dictionary Library Feedback