Header Bar

The Easiest Programming Language: REBOL

By: Nick Antonaccio
Updated: 11-13-2013

REBOL is the easiest computer programming language to learn.

Beginners can build practical applications with it in just a few hours.

Experienced professional coders can use it to become immediately productive in ways that aren't possible using other commercial development tools.

Children can even learn REBOL, more easily than BASIC and other "educational" tools, without disappointing technical ceilings that limit creative ability.

REBOL is a tiny (1/2 megabyte) interpreter that uses "Domain Specific Language" (DSL) technology and a combination of other truly unique syntax and design strategies to make simple work of every imaginable coding task. Compare this tutorial to texts about any other programming language, and you'll quickly discover that REBOL is a remarkably concise and practical tool, regardless of your skill level. For immediately productive development, there is nothing else like REBOL, anywhere.

REBOL is now completely free and open source. REBOL was an expensive closed source niche product for many years, but it's recent open source release is allowing it to gain momentum on new platforms, including Android.

See business-programming.com for a complete 850 page text that covers R2 in-depth, or learnrebol.com for a text about R3 (the newest open source version that also works on Android).

Contents:

1. Introducing REBOL
2. A Crash Course Introduction to REBOL
2.1 Installing and Running Programs
2.2 Opening REBOL Directly to the Console
2.3 A Whirlwind Tour of Short Code Examples to Whet Your Appetite
2.4 Getting Down to Business
2.5 Databases, Flash Applets, Network Apps, Web Apps, Native DLL Apps and MORE!
2.6 There's So Much More to See
2.7 A Telling Comparison
3. Learning How Everything Works
4. Get a FREE Private REBOL Programming Lesson With Nick Antonaccio
5. More Programs to Look Through
6. One Last Note About Choosing Programming Languages to Learn

1. Introducing REBOL

There is absolutely no programming language easier to learn than REBOL. Despite it's extraordinary simplicity, REBOL is powerful enough to be used for all types of professional application development, critical business system programming, web site development, file and network utility development, games, graphics, media programming, and more. REBOL is significantly faster to learn than Python, Ruby, Visual Basic, PHP, Lua, and other popular scripting languages (and many many times easier and more productive than Java and C), but it covers much of the same common practical ground as those tools. Even "non-programmers" can immediately use REBOL to create multi-platform desktop, mobile, and web applications of all kinds, for business and personal use. REBOL is a free, open source, tiny (1/2 megabyte) download that you can install and start using in less than a minute. It's balanced combination of simplicity, flexibility, and power are unmatched by any other language.

If you're an entrepreneur or business person who wants to improve office productivity and capability in ways that aren't possible using spreadsheets, boxed software packages, Filemaker/Access, or manual calculations, pen and paper, etc., REBOL is the simplest solution for creating cost saving custom applications which improve and enable business processes of all types. If you're an IT professional or the local tech guru searching for a powerful scripting tool to manage and interact with a wide range of common computing technology, including web site scripting and distributed network application creation, REBOL is the easiest tool to provide that power. If you're looking for a fun language to teach children, which will do more than just demonstrate fundamental concepts, there is nothing more immediately understandable and directly usable than REBOL. REBOL requires far less wading through complex, foreign, and confusing initial learning "cruft", than any other language, and it enables even children to actually accomplish real programming goals, without the disappointing or boring technical limits found in "teaching" tools.

REBOL includes amazingly simple to use GUI, graphic, network, email, math, parse, and other capabilities built in - no external libraries required. It's all included in the 1/2 meg download. And REBOL's learning curve is fast. There is only one "series" format to learn, and the exact same functions apply to managing tables of data, text strings, network ports, emails, graphic display lists, files, etc.

REBOL not only replaces other commercial desktop and mobile development languages such as Visual Basic, C, and Java, it also allows you to do all the same things as web server scripting languages such as PHP, Perl, Python, and Ruby. But that's not all - it also functions as a graphic and multimedia platform such as Flash, and replaces DBMSs such as Access, SQLite, and MySQL, a variety of system utility applications, and more, all with one simple paradigm.

REBOL was designed from the ground up, more than any other commercial development tool, to be simple and powerful, and it achieves that mix of capabilities in a way that is not comparable with any other tool. The end result is that you'll find yourself building real REBOL apps very quickly. There's nothing else like it.

This tutorial demonstrates a huge number of REBOL program examples, most of which are only 5 - 10 lines long. See http://business-programming.com for a free 850 page text that teaches how to program more than 100 business related applications in REBOL, from the ground up. Replace complex spreadsheets, database apps, boxed commercial products, and time consuming manual paper work, quickly and easily. No previous coding experience is required.

An older series of 68 YouTube video tutorials about REBOL (10 hours of video) is also available. The tutorial at learnrebol.com shows how to create desktop, web, and Android apps with Rebol version 3 (R3).

See the section below to get a free private video conference lesson about REBOL programming, with Nick Antonaccio.

2. A Crash Course Introduction to REBOL

2.1 Installing and Running Programs

To get started, download and install REBOL/View from http://www.rebol.com/download-view.html (it takes just a few seconds - the whole program is less than 1 Megabyte).

Once it's installed, run REBOL (Start -> Programs -> REBOL -> REBOL View), then click the "Console" Icon.

Type "editor none" at the prompt - that will run REBOL's built in text editor.

At this point, you are ready to start typing in REBOL programs. Copy/paste each example from this tutorial into the REBOL editor to see what the code does. Try it right now. Paste the following code into the REBOL editor, then press [F5] on your keyboard to save and run the program. You can save the file using the default "temp.txt" file name, as prompted, or rename it if you'd like. If you see the REBOL security requestor, select "Allow all":

REBOL []
alert "Hello World!"

If you save your program with a ".r" extension in the file name (i.e., "myprogram.r"), then you can also click your saved program's file icon, and it will run just like any normal executable (.exe) file. Try saving the program above on your desktop as "hello.r", then run it by clicking the hello.r icon on your desktop with your mouse.

2.2 Opening REBOL Directly to the Console

Before typing in or pasting any more code, adjust the following option in the REBOL interpreter: click the "User" menu in the graphic Viewtop that opens by default with REBOL, and uncheck "Open Desktop On Startup". That'll save you the trouble of clicking the "Console" button every time you start REBOL.

Setting your email account information and other user settings, is also recommended at this point.

To actually send and receive email with REBOL scripts, you must set your account username and password with code. You can use the following lines in any email scripts (replace "username" and "password" with your own email account info):

REBOL []
system/schemes/default/user: "username"
system/schemes/default/pass: "password"

Type "editor %rebol.r" into the REBOL console, save the above lines to the rebol.r file (with your edited username/password), and that code will run automatically every time you open the REBOL interpreter.

2.3 A Whirlwind Tour of Short Code Examples to Whet Your Appetite

You've already seen some code that alerts the user with a popup message:

alert "Hello World!"

This line of code sends an email to joe@site.com:

send joe@site.com "Hi Joe!"

You can paste short snippets of code like that directly into the REBOL interpreter console - there's no need to run the REBOL multiline editor that you saw in the previous section:

This line writes all the messages read from a user's inbox, to a file named "myemail.txt". Try editing this code to download your own mail (this could take a while if your inbox is full):

write %myemail.txt read pop://user@site.com

You can read the email file downloaded above using REBOL's built in text editor:

editor %myemail.txt

This next example prints the number of days between two dates:

print 24-jan-2013 - 17-feb-1972

This line prints the number of dates between now and 17-feb-1972. Try changing the code to calculate the number of days you've been alive:

print now - 17-feb-1972

This code prints the number of days between two dates requested from the user:

print request-date - request-date

You can just as easily perform calculations with many other types of values, and REBOL automatically understands how to compute appropriate responses:

print 10:30pm - 5:18am

print now/time - 8:00am

print 23x12 - 34x12

print 192.168.1.1 + 0.0.255.1

print 29.99 / 7

print $29.99 / 7

Requesting all sorts of data input from users, popping up messages, and performing other common interactive routines are simple tasks. Notice that text can be concatenated, or joined together, using the "join" word:

alert "Hello world"

alert join "Current Date and Time: " now

request-date

request-pass

request-text

request-text/title "What is your Name?"

request-file

request-list "Choose a color:" ["Red" "Green" "Blue"]

request ["Size:" "Small" "Medium" "Large"]

request-color

This example alerts the user with some joined text. The second part of the joined text is a bit of "Favorite Thing" text requested from the user:

alert join "My favorite thing is " request-text/title "Favorite Thing:"

This code requests the user to pick a list of files, and sends the info read from the first file in that list, to several email addresses:

send [joe@aaa.com ann@bbb.com] read first request-file

You can easily open the web browser to a specified URL, or a URL requested by the user:

browse http://re-bol.com

browse request-text/default "http://rebol.com"

You can run command line programs from REBOL:

call/show "notepad.exe c:\config.sys"

call "echo ^G"

call/show request-text/title/default "Enter OS Command:" "dir C:\Windows"

Play sounds:

insert s: open sound:// load %/c/windows/media/tada.wav wait s close s

insert s: open sound:// load request-file/only wait s close s

Read and write, from and to, the system clipboard:

print read clipboard://

write clipboard:// "Open notepad and try pasting now!"

Compressing and decompressing data also only takes one line of code:

editor compress read http://rebol.com

Try saving the above file as %temp.txt in the editor, and then run the following line of code. You'll see that the compressed data above is only 2456 bytes, while the decompressed data below is 7407 characters long:

editor decompress load %temp.txt

REBOL makes it easy to manage all sorts of useful data. You can read and write data, from and to, web sites (you need a user name and password to actually write to a web server), and read info from Time, DNS, News, Mail, and other types of servers:

print read http://rebol.com

print read daytime://time.nist.gov

print read dns://msn.com

print read dns://localhost

print read nntp://news.grc.com

print read pop://user@site.com

print read ftp://user:pass@site.com/index.html

write ftp://user:pass@site.com/index.html "Web site coming soon..."

This line writes to the system clipboard the HTML code in the web page read from rebol.com. Try pasting text into Notepad, or any other editor (using the Edit -> Paste menu), after running this line:

write clipboard:// read http://rebol.com

REBOL's built in text editor lets you easily, read, alter, and save data back to any readable/writable source:

editor clipboard://

editor request-file/only

If you have access to a web server, you can try creating and/or editing some pages on your web site (change the username, password, and file name, and be careful not to overwrite any critical file information!):

editor ftp://user:pass@site.com/index.html

You can perform all sorts of other useful actions and computations that are far more complex and verbose in other programming languages:

checksum read %file.txt   ; compute a checksum to ensure download validity

replace/all "xaxbxcxd" "x" "q"   ; replace all occurrences of "x" with "q"

parse "asdf#qwer&zxcv" "#&"               ; split strings at character set

trim/all "  asdf89w   we   "                      ; remove all white space

print dehex "a%20space"                  ; convert from URL encoded string

print to-url "a space"                     ; convert to URL encoded string

print detab "tab    separated"                    ; convert tabs to spaces

print enbase/base "a string" 64  ; convert string or bin to base 64, 16, 2

print encloak "my data" "my pass"  ; encrypt and decrpyt data (AES, blow-

print decloak "iz" "my pass"  ; fish and other formats also supported

read-cgi            ; neatly parse all data submitted from a web page form

There are hundreds of amazing data management operations you can accomplish in REBOL with just one line, but things get much more interesting when you put together such functionality with simple code that creates windowed user interfaces. The words "view layout" are used in REBOL to create a graphic user interface (GUI) window:

view layout [size 600x440]

You can add "widgets" such as text entry fields, text areas, text selection lists, images, push buttons, etc., to a window, very easily. For multi-line programs like the one below, be sure to paste each program into the REBOL editor and press [F5] to see the code run. Notice that a header and title have been added - the header is required when saving and running REBOL programs in the editor:

REBOL [title: "Widgets"]
view layout [
    field
    area
    text-list
    image logo.gif
    btn
]

Adding action and interactivity to widgets in program windows is also dead simple. Just put the actions you want a widget to perform, right next to the widget code, inside square brackets:

REBOL [title: "Widgets Alive!"]
view layout [
    field "Type Here"              [alert join "You typed: " value]
    text-list data ["1" "2" "3"]   [alert join "You selected: " value]
    area "Multi^/line^/text"       [alert value]
    image logo.gif                 [alert "You clicked the nice logo"]
    btn "Click Me"                 [alert "You clicked the button"]
]

The program below is a nice real world, practical application example. It saves text field data to a CSV (comma separated value) file, which can be opened by spreadsheets and many other types of business programs. It can be used as the basis for entering and saving categorical units of data of almost any type: contact info, personal notes, inventory item lists, sales receipts, etc. Notice that the window layout contains 2 text fields and a button displaying the text "Save Fields". When the button is clicked, a file named "fields.csv" is written to (appended with) the joined contents of each of the text fields. When that's done, the user is alerted with a message that the data has been saved. Reading through the code, it should be fairly straightforward to follow what's happening, even if you don't know anything more about REBOL programming. Try adjusting it to add the contents of a third text field to each row of saved data:

REBOL [title: "Text Field Saver"]
view layout [
    f1: field
    f2: field
    btn "Save Fields" [
        write/append %fields.csv rejoin [
            f1/text "," f2/text newline
        ]
        alert "Saved"
    ]
]

Here's a simple windowed email program. Try changing the window header title, and add a button that reads email from an account:

REBOL [title: "Send Email"]
view layout [
    text "Email:"
    f: field "joe@site.com" 
    text "Message:"
    a: area
    btn "Send" [
        send to-email f/text a/text
        alert "Sent"
    ]
]

Here's a version of the classic "15 square" sliding tile game. Click on tiles to slide them into the adjacent empty space. The goal is to rearrange the letters into alphabetical order. Try changing the letters "abcdefghijklmno" on each tile to the numbers 1-15:

REBOL [title: "Puzzle"]
view  layout [
    origin 0x0  space 0x0  across 
    style p button 60x60 [
        if not find [0x60 60x0 0x-60 -60x0] face/offset - x/offset [exit]
        temp: face/offset  face/offset: x/offset  x/offset: temp
    ]
    p "O"   p "N"   p "M"   p "L"   return
    p "K"   p "J"   p "I"   p "H"   return
    p "G"   p "F"   p "E"   p "D"   return
    p "C"   p "B"   p "A"   x: p white edge [size: 0]
]

This program displays live video from an online web cam. The camera stream can be changed at any point by editing the .jpg URL address (a Google search will turn up thousands of other available .jpg camera URLs):

REBOL [title: "Video"]
url: http://cam.luzern.org/axis-cgi/jpg/image.cgi?resolution=320x240
view layout [
    image 640x480 rate 0 feel [
        engage: func [f a e] [
            if a = 'time [
                f/image: load url
                show f
            ]
        ]
    ]
]

This is a paint/doodle app that lets you draw on the screen with your mouse. Most of this example is "boilerplate" code (stock code that you just need to memorize and reuse in similar programs), to watch for mouse activity and other dynamic user actions. Try changing the color of the drawing area to tan, and have the program print the mouse coodinate (the "e/offset" value), every time the mouse is moved:

REBOL [title: "Paint"]
view layout [
    s: area white feel [
        engage: func [f a e] [
            if a = 'over [append s/effect/draw e/offset  show s]
            if a = 'up [append s/effect/draw 'line]
        ]
    ] effect [draw [line]]
    btn "Clear" [s/effect/draw: copy [line] show s]
]

You've already seen how the number of days between any 2 dates can be computed with a single line of code. This program presents a nice windowed graphic user interface to allow users to select dates. The button text changes to show each of the user-selected dates. Try joining the words "Start date: " and "End date:" to the appropriate button texts:

REBOL [title: "Days Between"]
view layout [
    btn 200 "Start" [face/text: s: request-date]
    btn 200 "End" [
        face/text: e: request-date
        f/text: e - s
        show f
    ]
    text "Days Between:"
    f: field
]

Here's a calculator app. Notice that most of the code is simply button names that appear on screen. The rest of the program sets up the layout, and then 2 lines of code perform all the thoughtful work, including an error check to ensure the program doesn't crash in situations such as attempted divide-by-zero. Try adding a button to compute the remainder of division operations (create a new button with the modulo characters "//"). Using any other programming language, creating a simple applications like this typically requires at least a few dozen hours of learning:

REBOL [title: "Calculator"]
view layout [
    origin 0  space 0x0  across
    style btn btn 50x50 [append f/text face/text  show f]
    f: field 200x40 font-size 20 return
    btn "1"  btn "2"  btn "3"  btn " + "  return
    btn "4"  btn "5"  btn "6"  btn " - "  return
    btn "7"  btn "8"  btn "9"  btn " * "  return
    btn "0"  btn "."  btn " / "   btn "=" [
        attempt [f/text: form do f/text  show f]
    ]
]

You've already seen a one line example that plays a .wav sound file. This jukebox program allows the user to change folders and automatically list all .wav files, select which files to play with the mouse, and it checks for errors (such as attempted playing of 2 simultaneous files), etc. Watch what happens if you remove the "attempt" word and the following enclosed square brackets, and try changing the start directory to a folder of your choice, on your hard drive:

REBOL [title: "Jukebox"]
change-dir %/c/Windows/media 
do list: [remove-each file files: copy read %. [%.wav <> suffix? file]]
view layout [
    waves: text-list data copy files [
        attempt [insert s: open sound:// load value wait s close s]
    ]
    btn "Dir" [
        attempt [change-dir request-dir] 
        do list
        waves/data: copy files
        show waves
    ]
]

Here's a simple video game example. Use the space bar to change direction, and try to catch the falling pieces. The game is over when you've dropped more pieces than you've caught. Be careful - the more you catch, the speedier the game play gets! High scores are saved to a file and displayed in sorted order, from lowest to highest. The "s" variable holds the score, the "p" variable holds the speed, and the "d" variable holds the directional motion of the player piece. Try changing some of the variable values, such as the start speed, so that the game begins at a slower pace. Then, try saving high scores to a file stored on an FTP server, so that all players can compare ranked scores online. You can make all those changes without adding any new lines of code:

REBOL [title: "Catch Game"]
s: 1   p: 3   d: 10   n: now/time   random/seed now 
r: func [x] [y/offset: random 500x-20   p: p + .1   s: s + x]
view/new center-face g: layout/size [
   t: text 200 y: image logo.gif #" "[d: negate d] at 350x415 z: btn blue 
] 600x440  forever [
   y/offset/2: y/offset/2 + round p   z/offset/1: z/offset/1 - d 
   z/offset/1: switch/default z/offset/1[0[0 + d]550[550 + d]][z/offset/1]
   if overlap? z y [r +1]   if y/offset/2 > 420 [r -1]
   t/text: form now/time - n  wait .01  show g  if s = 0 [
      write/append %h "" save %h sort/skip append h: load %h reduce 
      [t/text request-text/title "Name:"]2 request-list "High Scores:" h q
   ]
]

Here's a little math test app. To make it easier or harder, try changing the range of random numbers, and adjust the question to perform subtraction, multiplication, division, and other types of operations:

REBOL [title: "Math Test"]
random/seed now
x: does [rejoin [random 10 " + " random 20]]
view layout [
    f1: field x
    text "Answer:"
    f2: field [
        alert either f2/text = form do f1/text ["Yes!"]["No"]
        f1/text: x  show f1  focus f2
    ]
]

If you want to interest boys in programming, try adding some adjectives and nouns to the next program, and change it to generate insults:

REBOL [title: "Compliment Generator"]
random/seed now
view layout [
    x: area "brilliant rare unique talented exceptional"
    y: area "genius champion winner success achiever"
    btn "Compliment" [
        alert rejoin [
            "You're a "
            first random parse x/text none " "
            first random parse y/text none "!"
        ]
    ] 
]

REBOL has many graphic and image editing capabilities built in. Here are just a few:

REBOL [title: "Image Effects"]
view layout [
    pic: image load http://re-bol.com/palms.jpg
    text-list data [
        "Invert" "Grayscale" "Emboss" "Blur" "Sharpen" "Flip 1x1"
        "Rotate 90" "Tint 83" "Contrast 66" "Luma 150" "None"
    ][
        pic/effect: to-block value
        show pic
    ]
]

These 2 examples demonstrate REBOL's "draw" dialect. Experiment with some of the draw commands to create a picture of your own. You can see how it works just by reading the code (edit the commands between the "draw" block):

REBOL [title: "Random Drawing"]
view layout [
    box 400x400 black effect [
        draw [
            pen red
            line 0x400 400x50
            pen white
            box 100x20 300x380
            fill-pen green
            circle 250x250 100
            pen blue
            fill-pen orange
            line-width 5
            spline closed 3 20x20 200x70 150x200
            polygon 20x20 200x70 150x200 50x300
        ]
    ]
]

REBOL [title: "Cube With Gradient"]
view layout [
    box 400x220 effect [
        draw [
            fill-pen 200.100.90
            polygon 20x40 200x20 380x40 200x80
            fill-pen 200.130.110
            polygon 20x40 200x80 200x200 20x100
            fill-pen 100.80.50
            polygon 200x80 380x40 380x100 200x200
        ]
        gradmul 180.180.210 60.60.90
    ]
]

This little script shows how easily the draw dialect can manipulate images. Again, everything outside the draw block is "boilerplate" code (you can copy/paste it, and simply change the screen size, color, etc.). This particular example adds window features such as tight spacing (no border), no title bar, and centered window placement. Since there is no close button in this window, you'll need to use the [ALT]+F4 keys to end the program:

REBOL [title: "Image Contort"]
view/options center-face layout/tight [
    box 400x400 black effect [
        draw [
            image logo.gif 10x10 350x200 250x300 50x300
        ]
    ]
] [no-title]

There's a small paint program created by Frank Sievertsen and Graham Chiu. This fun and useful app is created entirely with REBOL draw, and it's only 238 lines of code!:

REBOL [title: "Paint"]
do http://re-bol.com/paintplus.r
paint none []

NOTE: You can load saved images and/or drawing edits in the program above, using this line of code:

paint load %myimage.png load %edits.txt

To see a bit more about what's possible with REBOL draw dialect, take a look at these examples by talented developers in the REBOL community:

REBOL [title: "Draw Examples"]
do http://re-bol.com/rd3_jet.r
do http://re-bol.com/christmas_drive.r
do http://re-bol.com/raycasting.r
do http://re-bol.com/rotate.r
do http://re-bol.com/quick_hack.r
do http://re-bol.com/imagination.r

Here's a tiny text editor program that allows you to read, edit, and save any text file. To create the program window and widgets, this program uses a GUI library called "RebGUI" which is imported directly from re-bol.com (you must have an Internet connection available to run this example). Notice that the RebGUI library uses the word "display", with some options, instead of "view layout", to create the program window. There are some nice features enabled by RebGUI, such as undo/redo editing in the text area, automatic screen and widget resizing, simple menus, built in spell check in the text area (press CTRL+S), and controlled handling of how the program is closed (so users don't accidentally lose changes before saving). Try adding a "Quit" menu option:

REBOL [title: "Text Editor"]
do http://re-bol.com/rebgui.r
display/maximize/close "Text Editor" [
    menu #LHW data [
        "File" [
             "    Open    " [a/text: read request-file/only  show a]
             "    Save    " [write request-file/only/save a/text]
         ] 
    ] return
    a: area #LHW
] [question "Really Close?"] do-events

NOTE: If you want to make the program above run without having to download the rebgui.r file each time, just replace the following line with the actual code found at http://re-bol.com/rebgui.r. You can copy and paste that code from your browser, or from "editor http://re-bol.com/rebgui.r" in REBOL:

do http://re-bol.com/rebgui.r

2.4 Getting Down to Business

The examples above are cute and interesting, but programming languages aren't useful (beyond being instructive and fun) unless they can help you get work accomplished. The short script below is a great introduction to the powerful business capabilities available in REBOL. This program downloads a Paypal account file from the web (at http://re-bol.com/Download.csv), parses apart the data in each line (splitting at the comma character), calculates the sum of all money values in the "Gross" transactions column (col #8), and alerts the user with the total. This is the sort of work most commonly accomplished with spreadsheet applications. Copying and pasting these several lines of code, however, takes less time than downloading the file with a browser, opening a spreadsheet program, importing the data, and summing the numbers with a formula. It also only needs to be written once, and executed any time the live data changes. Using a spreadsheet would require a complete download/import/run cycle for every change to the data source. Complex conditional and algorithmic evaluations, nearly impossible to accomplish with a spreadsheet, would require only a few lines of code added to this example. If you want to total other columns, just change the number 8, to the column that you'd like to total. If you want to work with a local file stored on your hard drive, change the URL to %SomeFileOnYourHardDrive.csv. If you want to work with values that are not money, try changing the "to-money" word to "to-decimal" (or to-time, to-date, etc.). This report starts with the second row, because the first row is just a list of column labels. To begin reporting at line 1, change the number 2 to a 1:

REBOL [title: "Paypal Reports"]    
sum: $0
foreach line at read/lines http://re-bol.com/Download.csv 2 [
    sum: sum + to-money pick (parse/all line ",") 8
]
alert join "Total Gross Sales: " sum

You can introduce any sort of logic you want to the code above. This variation only prints rows that contain the text "Saoud" in the name column (col #4). Try changing the search to "John Smith":

REBOL [title: "Paypal Reports #2"]
foreach line at read/lines http://re-bol.com/Download.csv 2 [
    row: parse/all line ","
    if find row/4 "Saoud" [print join row newline]
]
halt

This variation prints the Gross transaction values (col #8), for transactions in which the time value (col #2) is between midnight and noon. Try changing the search times to afternoon:

REBOL [title: "Paypal Reports #3"]
foreach line at read/lines http://re-bol.com/Download.csv 2 [
    row: parse/all line ","
    time: to-time row/2
    if (time >= 0:00am) and (time <= 12:00pm) [print row/8]
]
halt

This example parses all but the first line of the Paypal data file, and creates a list of all the names in col #4. Then it determines a list of all unique names found in that list, and prints the number of times each unique name is found in the names column:

REBOL [title: "Paypal Reports #4"]
names: copy []
foreach line at read/lines http://re-bol.com/Download.csv 2 [
    append names fourth parse/all line ","
]
foreach name unique names [
    count: 0
    foreach n names [if name = n [++ count]]
    print rejoin [name ":  " count newline]
]
halt

REBOL can do many more useful things which Excel can't even dream of accomplishing. Here's a fully functional web page editor. This little GUI program can be used to edit live web pages on the Internet, with a simple little GUI interface (to use this script, you need to know the username, password, and path of a file on a web server to which you have access):

REBOL [title: "Web Page Editor"]
view layout [
    f: field 600 "ftp://user:pass@site.com/public_html/page.html"
    a: area 600x350 
    across 
    btn "Load" [a/text: read to-url f/text  show a]
    btn "Save" [write to-url f/text a/text  alert "Saved"]
]

This FTP program provides even more web site maintenance functionality. It allows the user to browse, click, and edit all the files in any folder on any web server. Just type a URL path to browse (you must have access to a web server, and know the username/password). Type a file name at the end of the path to automatically create a new file. Click any listed files to view, edit, and save changes back to the web server. You could actually create and manage an entire commercial web site using this little program alone:

REBOL [title: "FTP Tool"]
view  layout [
    f: field 600 "ftp://user:pass@site.com/public_html/" [
        either dir? to-url value [
            t/data: sort read to-url value 
            show t
        ][
            editor to-url value
        ]
    ]
    t: text-list 600x400 [editor to-url join f/text value]
]

This calendar app allows the user to select a day from the calendar. Events for the day are typed into a text area and then appended to a text file. The user can go back any time and view/edit/save events for any day. You could actually use this app to reliably manage your schedule. If you need to move the entire application and data to another computer, just copy this tiny REBOL program and the saved text file (named "schedule"), to a USB drive, send it by email, etc. Try changing the date display on each schedule page to bold text, so that it stands out more clearly:

REBOL [title: "Calendar"]
do cal: [
    write/append %schedule ""
    date: request-date
    view layout [
        text form date 
        a: area form select to-block (
            find/last load %schedule date
        ) date 
        btn "Save" [
            write/append %schedule rejoin [date mold a/text]
            unview 
            do cal
        ]
    ]
]

This program creates a graphic bar chart from a list of numbers. It uses a library called "q-plot" which is imported directly from re-bol.com (you must have an Internet connection available to run this example). Try changing the number list:

REBOL [title: "Q-Plot Bar Chart"]
do http://re-bol.com/q-plot.r
view quick-plot [
    600x400
    bars [5 3 8 2 10 3 4 9 5 7]
]

This pie chart example adds features such as a title, labels, and some exploded sections. Try adjusting the features - it's simple enough to figure out without instruction:

REBOL [title: "Exploded Pie Chart"]
do http://re-bol.com/q-plot.r
view quick-plot [
    400x400
    pie [10 3 6 1 8] labels [A B C D E] explode [3 5]
    title "Exploded Sections C and E" style vh2
]

This program draws a chart using REBOL's powerful native GUI drawing capabilities. No downloaded library is required. This code just puts box widgets on the screen that are sized for each value in the data block. Try changing the width and length of the boxes:

REBOL [title: "Chart"]
data: [12 3 9 38 1 23 18]
gui: copy [backdrop white]
foreach val data [append gui compose [box blue (as-pair (val * 10) 40)]]
view layout gui

This script uses REBOL's native graphics abilities to display the chart in a movable 3D view (use the "asdfghjkl" keys to adjust the camera angle and position). Try adjusting the data to plot labels and values computed by the earlier Paypal Reports examples:

REBOL [title: "3D Graph"]
graph-data: [
    ["Jan"  11.0]
    ["Feb"  22.0]
    ["Mar"  25.0]
    ["Apr"  55.0]
    ["May"  35.0]
    ["Jun"  75.0]
    ["Jul"  20.0]
    ["Aug"  33.0]
    ["Sep"  21.0]
    ["Oct"  55.0]
    ["Nov"  65.0]
    ["Dec"  45.0]
]
do http://re-bol.com/r3dchart.r

This example demonstrates how to use Google's powerful web API to display graphs. The graph you see output by this code is created by Google's live web servers. The REBOL code you see here is much simpler to understand and use than the native API made available by Google (check out the documentation here):

REBOL [title: "Google Charts"]
do http://reb4.me/r/google-charts.r
browse chart [
    title: "Chart Example"
    type: 'pie
    size: 350x150
    labels: ["Red" "Green" "Blue"]
    data: [50 40 10]
    colors: reduce [red green blue]
    area: [color solid 244.244.240]
]

This program demonstrates how to display a grid of spreadsheet-like table data. Many features, such as automatic sorting, saving data to different formats, and more are automatically enabled. Try expanding the data set to include 4 rows and 4 columns of values:

REBOL [title: "Grid"]
headers: ["Numbers" "Text" "Dates"]
x: [
    [1  "1"  "1-1-2012"]
    [11 "11" "1-2-2012"]
    [2  "2"  "1-3-2012"]
]
do http://re-bol.com/gridlib.r

Here's a full screen slide show presentation example. It just uses REBOL's native GUI layout language to present text, images, and other items on screen (the size of the user's screen is found in the value "system/view/screen-face/size"). Try adding a page that includes any other windowed (GUI) program you've seen so far in this text:

REBOL [title: "Simple Presentation"]
slides: [
    [
        at 0x0 box system/view/screen-face/size white [unview]
        at 20x20 h1 blue "Slide 1"
        box black 2000x2
        text "This slide takes up the full screen."
        text "Adding images is easy:"
        image logo.gif
        image stop.gif
        image info.gif
        image exclamation.gif
        text "Click anywhere on the screen for next slide..."
        box black 2000x2
    ]
    [
        at 0x0 box system/view/screen-face/size effect [
            gradient 1x1 tan brown
        ] [unview]
        at 20x20 h1 blue "Slide 2"
        box black 2000x2
        text "Gradients and color effects are easy in REBOL:"
        box effect [gradient 123.23.56 254.0.12]
        box effect [gradient blue gold/2]
        text "Click anywhere on the screen to close..."
        box black 2000x2
    ]
]
foreach slide slides [
    view/options center-face layout slide 'no-title
]

Here's a slightly more complex email app than the little sender you saw earlier. Click the "Server settings" button, and you can enter all your email account information to read and send emails from any server (notice that most of the lengthy code in this program is simply there to collect account information from the user). Try adding some code that joins the current date and time to the subject line of any sent email:

REBOL [title: "Email"]
view layout[
    h1 "Send:"
    btn "Server settings" [
        system/schemes/default/host: request-text/title "SMTP Server:"
        system/schemes/pop/host:     request-text/title "POP Server:"
        system/schemes/default/user: request-text/title "SMTP User Name:"
        system/schemes/default/pass: request-text/title "SMTP Password:"
        system/user/email: to-email request-text/title "Your Email Addr:"
    ]
    a: field "user@website.com"
    s: field "Subject" 
    b: area
    btn "Send"[
        send/subject to-email a/text b/text s/text
        alert "Sent"
    ]
    h1 "Read:" 
    f: field "pop://user@site.com"
    btn "Read" [editor to-url f/text]
]

While you're thinking about email, here's a little script that opens an account and displays the first 20000 characters of each individual message. Try changing the code to read the first 50000 characters in each email, and alert the user with the word "Done" after the last email is displayed. If you can do that, try integrating this code into the program above, inside the "Read" button's action block:

REBOL [title: "Email"]
email: open pop://user:pass@site.com
repeat count length? email [
    print join newpage "Press [ESC] to quit..."
    editor copy/part email/:count 20000
]

Here's a card file program that can be used to save and browse categorical information of any type, like a Rolodex. Try changing the text labels and the file name "%c" to store different types of info:

REBOL [title: "Card File"]
write/append %c ""
view center-face g: layout [
    h3 "Name:"   x: field   h3 "Info:"   z: area wrap   across
    btn "Save" [do-face d 1  save %c  repend f [x/text z/text]]
    btn "Load" [
        c: request-list" Select:" extract (f: load %c) 2
        if c = none [return]
        x/text: first find f c  z/text: select f x/text  show g
    ]
    btn "New" [x/text: copy ""  z/text: copy ""  show g  focus x]
    d: btn "Delete" [
        if true = request "Sure?" [
            remove/part (find (f: load %c) x/text) 2 save %c f alert "ok"
        ]
    ]
]

Here's a small but fully functional cash register application. Try adjusting it to include a yes/no sales tax field, to automatically compute sales tax, only for items that are taxable:

REBOL [title: "Minimal Cash Register"]
view gui: layout [
    style fld field 80
    across
    text "Cashier:"   cashier: fld 
    text "Item:"      item: fld 
    text "Price:"     price: fld [
        if error? try [to-money price/text] [alert "Price error" return]
        append a/text reduce [mold item/text tab price/text newline]
        item/text: copy "" price/text: copy ""
        sum: 0
        foreach [item price] load a/text [sum: sum + to-money price]
        subtotal/text: form sum
        tax/text: form sum * .06
        total/text: form sum * 1.06 
        focus item
        show gui
    ]
    return
    a: area 600x300
    return
    text "Subtotal:"   subtotal: fld 
    text "Tax:"        tax: fld 
    text "Total:"      total: fld
    btn "Save" [
        items: replace/all (mold load a/text) newline " "
        write/append %sales.txt rejoin [
            items newline cashier/text newline now/date newline
        ]
        clear-fields gui
        a/text: copy ""             
        show gui             
    ]
]

This report program computes a sum of all sales made on the current day, using the program above. Try to adjust it to provide reports for a list of dates:

REBOL [title: "Daily Total"]
sales: read/lines %sales.txt
sum: $0
foreach [items cashier date] sales [
    if now/date = to-date date [
        foreach [item price] load items [
            sum: sum + to-money price
        ]
    ]
]
alert rejoin ["Total sales today: " sum]

Here's a shopping list app. Too add an item, just type into the text field and press [Enter]. The program checks the list to prevent duplicate entries. To remove any item from the list, click the chosen line in the text-list widget. The "Sort" button sorts the list alphabetically. You can save and reload lists by clicking the "Save" and "Load" buttons:

REBOL [title: "Shopping List"]
view layout [
    t: text-list 500x400 [remove find t/data value  show t]
    f: field 500 [
        if not find t/data value [append t/data copy value] show t focus f
    ]
    across
    btn "Save" [save %shopping.txt t/data  alert "Saved"]
    btn "Load" [t/data: load %shopping.txt  show t]
    btn "Sort" [sort t/data  show t]
]

This version of the program above adds some features to create a useful to-do list. Additional buttons are added to allow selected items to be shifted to any position in the list. File requestors are added to allow the user to save and load different file names. A "Print" button is added to send the screen list to the system default image application, to print a paper copy. A number of error checks are also added, just in case the user cancels save/load operations, tries to shift item positions without first selecting an item, etc.:

REBOL [title: "To Do"]
view/new gui: layout [
    t: text-list 500x400
    across
    f: field [if not find t/data v: value [append t/data copy v] focus f]
    btn "Del"  [remove find t/data t/picked]
    btn "Up"   [attempt [move/to z: find t/data t/picked (index? z) - 1]]
    btn "Down" [attempt [move/to z: find t/data t/picked (index? z) + 1]]
    btn "Load" [attempt [t/data: load request-file/file/only %todo.txt]]
    btn "Save" [attempt [
        save request-file/save/file/only %todo.txt t/data
        alert "Saved"
    ]]
    btn "Print" [save/png %todo.png to-image gui  call/show %todo.png]
] 
forever [wait .1  show gui  if not viewed? gui [quit]]

Here's a timer application that requests from the user a number of seconds to wait, displays a running timer count, and then beeps 5 times to alert the user when the time has passed:

REBOL [title: "Timer"]
call ""
seconds: to-integer ask "Seconds: " 
repeat i seconds [print join newpage i  wait 1] 
loop 5 [call/wait "echo ^G"  wait 1]

Here are a few slightly more complicated application examples. The first one makes use of menu and tab panel widgets to layout a complex program interface. Take note of just how much interactivity and functional screen design is presented in this relatively short bit of code. You can probably figure out most of what the code does, without much help. Try adding a new "time" item to the "options" menu, which alerts the user with the current time, when selected. Also try copying any of the previous windowed (GUI) programs in this text, to a new tab panel:

REBOL [title: "Menu and Tab Panel"]
do http://re-bol.com/cyphremenu.r
view/options layout  [
    across space 0x0 origin 0x0
    mn: menu with [
        size: 470x20  
        data: [
            " File " [
                "Open" # "Ctrl+O" [request-file]
                "Save" # "Ctrl+S" [request-file/save]
                bar
                "Exit" [quit]
            ]
            " Options " [
                "Preferences" sub [
                    "Colors" [alert form request-color]
                    "Settings" [request-text/title "Enter new setting:"]
                ]
                "About" [alert "Menu Widget by Cyphre"]
            ]
        ]
    ]
    below
    at 10x25 my-tabs: tab-panel data [
        "Fields"   [
            h1 "Tab Panel by Cyphre" field field area area btn "Ok"
         ]
        "Data List"  [
            t1: text-list 400x430 data system/locale/months [alert value]
        ]
    ]
] [resize]

This is a parts database app, but it could just as easily be converted to hold receipts, contacts, or any other information, just by changing the text labels. Try adjusting it to store Name, Address, and Phone info:

REBOL [title: "Parts"]
write/append %data.txt ""
database: load %data.txt
view center-face gui: layout [
    text "Parts in Stock:"
    name-list: text-list blue 400x100 data sort (extract database 4) [
        if value = none [return]
        marker: index? find database value
        n/text: pick database marker
        a/text: pick database (marker + 1)
        p/text: pick database (marker + 2)
        o/text: pick database (marker + 3)
        show gui
    ]
    text "Part Name:"       n: field 400
    text "Manufacturer:"    a: field 400
    text "SKU:"      p: field 400
    text "Notes:"      o: area  400x100
    across
    btn "Save" [
        if n/text = "" [alert "You must enter a Part name." return]
        if find (extract database 4) n/text [
            either true = request "Overwrite existing record?" [
               remove/part (find database n/text) 4
            ] [
               return
            ]
        ]
        save %data.txt repend database [n/text a/text p/text o/text]
        name-list/data: sort (extract copy database 4)
        show name-list
    ]
    btn "Delete" [
        if true = request rejoin ["Delete " n/text "?"] [
            remove/part (find database n/text) 4
            save %data.txt database
            do-face clear-button 1
            name-list/data: sort (extract copy database 4)
            show name-list
        ]
    ]
    clear-button: btn "New" [
        n/text: copy  ""
        a/text: copy  ""
        p/text: copy  ""
        o/text: copy  ""
        show gui
    ]
]

Here's a complete spreadsheet application, originally written in REBOL by Carl Sassenrath, which can inherently use the entire REBOL language and all it's features to process cell data (math, graphics, Internet connectivity, file and network port data access, parse ability, native dialogs and GUI widgets to enable user input, and all other general purpose capabilities of the language are available to functions in this tiny 68 line program):

REBOL [Title: "Rebocalc" Authors: ["Carl Sassenrath" "Nick Antonaccio"]]
csize: 100x20  max-x: 8  max-y: 16
pane: []
xy: csize / 2 + 1 * 1x0
yx: csize + 1 * 0x1
layout [
    cell: field csize edge none [enter face compute face/para/scroll: 0x0]
    label: text csize white black bold center
]
char: #"A"
repeat x max-x [
    append pane make label [offset: xy text: char]
    set in last pane 'offset xy
    xy: csize + 1 * 1x0 + xy
    char: char + 1
]
repeat y max-y [
    append pane make label [offset: yx text: y size: csize * 1x2 / 2]
    yx: csize + 1 * 0x1 + yx
]
xy: csize * 1x2 / 2 + 1
cells: tail pane
repeat y max-y [
    char: #"A"
    repeat x max-x [
        v: to-word join char y
        set v none
        char: char + 1
        append pane make cell [offset: xy text: none var: v formula: none]
        xy: csize + 1 * 1x0 + xy
    ]
    xy: csize * 1x2 / 2 + 1 + (xy * 0x1)
]
enter: func [face /local data] [
    if empty? face/text [exit]
    set face/var face/text
    data: either face/text/1 = #"=" [next face/text][face/text]
    if error? try [data: load data] [exit]
    if find [
        integer! decimal! money! time! date! tuple! pair!
    ] type?/word :data [set face/var data exit]
    if face/text/1 = #"=" [face/formula: :data]
]
compute: has [blk] [
    unfocus
    foreach cell cells [
        if cell/formula [
            either cell/text = "formula" [
                cell/text: join "=" form cell/formula
                show cell return
            ][
                if error? cell/text: try [do cell/formula] [
                    cell/text: "ERROR!"
                ]
            ]
            set cell/var cell/text
            show cell
        ]
    ]
]
lo: layout [
    bx: box second span? pane
    text "Example: type '7' into A1, '19' into B1, '=a1 + b1' into C1" 
    text "Type 'formula' into any cell to edit an existing formula (C1)."
]
bx/pane: pane
view center-face lo

2.5 Databases, Flash Applets, Network Apps, Web Apps, Native DLL Apps and MORE!

Reading and writing data to/from database systems is simple in REBOL. This example downloads a MySQL database driver and prints all the items in the "John" table of the "contacts" database on a locally hosted MySQL server. Can you figure out how to adjust the code to get all the items from the "Joe" table?:

REBOL [title: "MySQL"]
do http://re-bol.com/mysql-protocol.r
print read/custom mysql://root@localhost/contacts ["SELECT * FROM John"]

Here's a full example that creates an SQLite database, adds data, manipulates entries, and displays the results. Try adjusting the code to add information for another person, and delete entries that contain the phone number 555-1234:

REBOL [title: "SQLITE Example"]
unless exists? %sqlite3.dll [
    write/binary %sqlite3.dll read/binary http://re-bol.com/sqlite3.dll
]
unless exists? %sqlite.r [
    write %sqlite.r read http://re-bol.com/sqlite.r
]
do %sqlite.r
db: connect/create %contacts.db
SQL "create table contacts (name, address, phone, birthday)"
SQL {insert into contacts values 
    ('"John Doe"', '"1 Street Lane"', '"555-9876"', '"1967-10-10"')
}
data: [
    "John Smith" "123 Toleen Lane" "555-1234" "1972-02-01"
    "Paul Thompson" "234 Georgetown Pl." "555-2345" "1972-02-01"
    "Jim Persee" "345 Portman Pike" "555-3456" "1929-07-02"
    "George Jones" "456 Topforge Court" "" "1989-12-23"
    "Tim Paulson" "" "555-5678" "2001-05-16"
]
SQL "begin"
foreach [name address phone bd] data [
    SQL reduce [
        "insert into contacts values (?, ?, ?, ?)" name address phone bd
    ]
]
SQL "commit"
SQL ["DELETE from Contacts WHERE birthday = ?" "1967-10-10"]
results: SQL "select * from contacts"
probe results
disconnect db
halt

REBOL can be used to create and compile Flash applets that are useful in web based graphics and animation apps:

REBOL [title: "Flash"]
cd %/c/4/
do http://re-bol.com/rswf.r
make-swf/save/html http://re-bol.com/swf5-starfield1.rswf
browse %starfield1.html

REBOL enables powerful and easy to use network capabilities. This program displays the WAN and LAN network IP addresses of the user's computer. The extremely powerful "parse" function replaces the need for "regular expressions" found in most other languages, with a much simpler and easier to read alternative:

REBOL [title: "IP Addresses"]
parse read http://guitarz.org/ip.cgi [thru <title> copy w to </title>]
wan: last parse w none
alert rejoin ["WAN: " wan " -- LAN: " read join dns:// read dns://]

Here's a text message app that can be used to send private notes to other users on a network:

REBOL [title: "Network Text Message"]
view layout [ across
    q: btn "Serve"[focus g p: first wait open/lines tcp://:8 z: 1]text"OR"
    k: btn "Connect"[focus g p: open/lines rejoin[tcp:// i/text ":8"]z: 1]
    i: field form read join dns:// read dns://  return
    r: area rate 4 feel [engage: func [f a e][if a = 'time and value? 'z [
        if error? try [x: first wait p] [quit]
        r/text: rejoin [x "^/" r/text] show r
    ]]]  return
    g: field "Type message here [ENTER]" [insert p value  focus face]
]

Here's a full featured network VOIP (voice over IP) intercom/walkie-talkie app, with hands-free operation enabled. In other languages, this would likely take a few (or actually many many many) pages of code to achieve the same results:

REBOL [title: "VOIP"] do [write %ireceive.r {REBOL []
if error? try [port: first wait open/binary/no-wait tcp://:8] [quit]
wait 0  speakers: open sound://
forever [
    if error? try [mark: find wav: copy wait port #""] [quit]
    i: to-integer to-string copy/part wav mark
    while [i > length? remove/part wav next mark] [append wav port]
    insert speakers load to-binary decompress wav
]} launch %ireceive.r
lib: load/library %winmm.dll
mci: make routine! [c [string!] return: [logic!]] lib "mciExecute"
if (ip: ask "Connect to IP (none = localhost):  ") = "" [ip: "localhost"]
if error? try [port: open/binary/no-wait rejoin [tcp:// ip ":8"]] [quit]
mci "open new type waveaudio alias wav"
forever [
    mci "record wav"  wait 2  mci "save wav r"  mci "delete wav from 0"
    insert wav: compress to-string read/binary %r join l: length? wav #""
    if l > 4000 [insert port wav]  ; squelch (don't send) if too quiet
]]

Here's a text chat application that can be used by groups of people to create their own rooms and share private conversations online (using any available FTP server - and absolutely nothing needs to be set up on the server beforehand). This is a console application that can be used on virtually any operating system for which REBOL has been compiled (over 40 and counting), even those which don't have graphics capabilities. Try adjusting it to add the current time and date to each message entry:

REBOL [title: "Group Chat (Console)"]
url: ftp://user:pass@site.com/public_html/chat
write/append url ""
name: copy ask "^LName:  "
forever [
    notes: copy read url
    message: ask rejoin [newpage notes "Message:  "]
    if message = "erase" [write url ""]
    if message <> "" [
        write/append url rejoin [
            now " (" name "):  " message "^/^/"
        ]
    ]
]

Here's a GUI version of the above program, with a nice windowed graphic user interface:

REBOL [title: "Group Chat (GUI)"]
url: ftp://user:pass@site.com/public_html/chat
write/append url ""
name: request-text/title "Name:"
view gui: layout [
    a: area 600x300
    text "New Message:"
    message: field 600 [
        if message/text = "erase" [write url ""]
        if message/text <> "" [
            write/append url rejoin [
                now " (" name "):  " message/text "^/^/"
            ]
        ]
        a/text: copy read url  focus message  show gui 
    ]
]

One of the greatest things about REBOL is that it can be used as a fully capable web site development language (for the same purposes as PHP, ASP, Perl, Python, Ruby, and other popular server programming languages). It can do everything that those languages can do, only with far less code. Because REBOL is tiny and has been ported to nearly every server OS available, it's easy to copy REBOL to your web site and use it to output web pages. Here's a web version of the above script that can be installed on a web server, so that people can connect to the chat app, using only a browser, on any Internet connected computer, phone, tablet, or other device:

#!rebol276 -cs
REBOL [title: "Group Chat (Web App)"]
print {content-type: text/html^/}
url: ftp://user:pass@site.com/public_html/chat
write/append url ""
submitted: decode-cgi read-cgi
if submitted/2 = "erase" [write url ""]
if submitted/2 <> none [
    write/append url rejoin [
        now " (" submitted/2 "):  " submitted/4 "^/^/"
    ]
]
notes: copy read url
print rejoin [
    "<pre>" notes "</pre>"
    {<FORM ACTION="http://site.com/tinychat.cgi">
        Name:<br>
        <input type=text size="65" name="username"><br>
        Message:<br>
        <textarea name=message rows=5 cols=50></textarea><br>
        <input type="submit" name="submit" value="Submit">
    </FORM>}
]

The three programs above are totally interoperable. Take a look at the similar flow of code between the three versions. A person can use any of these three tiny apps to send and immediately view messages transferred by users operating any of the other versions.

Here's a web version of the calendar app you saw earlier. The lengthy code in this program has nothing to do with REBOL. To create any web app, it's necessary to print "HTML" code, which is the language used to format all web pages for display in browsers. HTML actually has a syntax that's simpler than many of the other GUI programming languages used to create windowed applications. Even though this interface is much more plain looking than the REBOL GUI version, take note of how much more complex and verbose the code is! This is simple compared to the code you'll find in other programming languages, to create even little windowed apps like the REBOL calendar program you saw earlier:

#!rebol276 -cs
REBOL [title: "Calendar"]
print {content-type: text/html^/}
submitted: decode-cgi read-cgi
if submitted/2 <> none [
    date: to-date rejoin [submitted/4 "-" submitted/2 "-" submitted/6]
    appointments: form select to-block (
        find/last to-block read %schedule date
    ) date 
    write/append %schedule current: rejoin [
        date mold rejoin [appointments "<br><br>" submitted/8]
    ]
    print rejoin ["<pre>" current "</pre>"]
]
years: ["2011" "2012" "2013"]
print {
    <FORM ACTION="http://site.com/cal.cgi">
        Date: <br>
        <select NAME="month">}
            foreach o system/locale/months [prin rejoin [{<option>} o]]
        print {</option> </select>
        <select NAME="day">}
            for o 1 31 1 [prin rejoin [{<option>} o]]
        print {</option> </select>
        <select NAME="year">}
            foreach o years [prin rejoin [{<option>} o]]
        print {</option> </select>
        <br><br>
        Add Event:<br>
        <input type=text size="65" name="event"><br>
        <INPUT TYPE="SUBMIT" NAME="Submit" VALUE="Submit">
    </FORM>
}

When you program in REBOL, most of the time you'll use REBOL's compact and potent language syntax and built in API functions to create apps. Sometimes you need to interface with other specialized components created by foreign development tools and languages - such as functions imported from .DLL files, .SO files, etc. The following short script demonstrates how to use the "Intelligent Mail Encoder" DLL from the US postal service. Try and find examples of this DLL in use by other other languages. You'll see that the code required to do the exact same thing in other languages, is much more complicated than the script below:

REBOL [title: "USPS Intelligent Mail Encoder"]
write/binary %usps4cb.dll read/binary http://re-bol.com/usps4cb.dll
GEN-CODESTRING: make routine! [
    t [string!]  r[string!]  c [string!]  return: [integer!]
]  load/library %usps4cb.dll "USPS4CB"
t: request-text/title/default "Tracking #:" "00700901032403000000"
r: request-text/title/default "Routing #:" "55431308099"
GEN-CODESTRING t r (make string! 65)
alert first second first :GEN-CODESTRING

Here's a program that allows you to view and save photos from your computer's camera, using the messy native Windows "avicap32" DLL. This code demonstrates a bit more what it's like to program in other languages, even though the entire program is made simpler by REBOL. Paste this code into the REBOL editor and press [F5] to see it run:

REBOL [title: "Camera"]
avicap32.dll: load/library %avicap32.dll
user32.dll: load/library %user32.dll
get-focus: make routine! [return: [int]] user32.dll "GetFocus"
set-caption: make routine! [
    hwnd [int] a [string!]  return: [int]
] user32.dll "SetWindowTextA"
find-window-by-class: make routine! [
    ClassName [string!] WindowName [integer!] return: [integer!]
] user32.dll "FindWindowA"
sendmessage: make routine! [
    hWnd [integer!] val1 [integer!] val2 [integer!] val3 [integer!]
    return: [integer!]
] user32.dll "SendMessageA"
sendmessage-file: make routine! [
    hWnd [integer!] val1 [integer!] val2 [integer!] val3 [string!]
    return: [integer!]
] user32.dll  "SendMessageA"
cap: make routine! [
    cap [string!] child-val1 [integer!] val2 [integer!] val3 [integer!]
    width [integer!] height [integer!] handle [integer!] 
    val4 [integer!] return: [integer!]
] avicap32.dll "capCreateCaptureWindowA"
view/new center-face layout/tight [
    image 320x240
    across
    btn "Take Snapshot" [
        sendmessage cap-result 1085 0 0
        sendmessage-file cap-result 1049 0 "scrshot.bmp"
        save-path: first split-path system/options/script
        view/new center-face layout [
            image load join save-path %scrshot.bmp
            btn "save" [
                (write/binary 
                    to-file pp: request-file/save/file %photo1.bmp
                    read/binary join save-path %scrshot.bmp
                )
                alert join "Saved " pp
                unview
            ]
        ]
    ]
    btn "Exit" [
        sendmessage cap-result 1205 0 0
        sendmessage cap-result 1035 0 0
        free user32.dll
        quit
    ]
]
hwnd-set-title: get-focus
set-caption hwnd-set-title "Web Camera"  ; title bar
hwnd: find-window-by-class "REBOLWind" 0
cap-result: cap "cap" 1342177280 0 0 320 240 hwnd 0
sendmessage cap-result 1034 0 0
sendmessage cap-result 1077 1 0
sendmessage cap-result 1075 1 0
sendmessage cap-result 1074 1 0
sendmessage cap-result 1076 1 0
do-events

You can see that the farther you get from REBOL, the more you're going to discover code that's hard to read, even after years of study and practice.

2.6 There's So Much More to See

Notice that almost all the of the pure REBOL application examples you've seen so far are tiny. Most are just a few lines long. You can copy and paste them, and with just a little basic understanding about how the REBOL language works, you'll be able to understand each line of code very quickly, make changes, and adjust the code for your own use and variation in programs that you imagine. You can learn how to create powerful data management applications that store large volumes of data, without having to learning anything else about database (DBMS) systems, imported libraries, object oriented programming (although REBOL does support objects, when desired), or other concepts that slow you down.

It becomes very exciting to think that small applications presented so far could be altered and combined to provide truly unique software features. The spreadsheet and full screen presentation scripts, for example, could be combined and used to read live data from a web site, email, account, or database, to create a unique sort of "live" presentation displaying updated real-time data figures and computations. The ability to perform totally customizable operations and interactions that are simply impossible using off-the-shelf boxed software and non-programming tools, are endless, and limited only to your own needs and creative motivations.

Because REBOL code snippets and syntax are so simple to learn, so short, and so concise, such great power comes with a much quicker learning curve than even that required to learn, for example, Excel + basic VBA scripting, or even the most fundamental web site scripting. REBOL's powerful ability to parse, sort, search, organize, manipulate, save, retrieve, and perform computations intuitively and concisely, on all types of data coming from all sorts of sources; it's ability to create graphic user interface windows (GUIs) more simply than any other language; it's ability to operate in desktop, web, and mobile environments; it's small size and extraordinary portability between operating systems; and more; gives users of all levels and backgrounds the ability to code powerful solutions to a huge variety of computing goals, quickly and easily.

Since REBOL is a tiny (about 1/2 a meg) multi-platform interpreter, it can be downloaded and used immediately, without installation, on all platforms, as a lightweight file manager, text editor, calculator, database manager, email client, ftp client, news reader, image viewer/editor, OS shell, and more. You can employ it as a simple utility program with a familiar interface to common computing activities, on just about any computer, even if you're unfamiliar with the operating system. All REBOL applications, and the entire development system itself, are instantly transportable. You can even send complex REBOL scripts along with all the REBOL interpreters for Windows, Mac, and Linux as a tiny email attachment smaller that a single photograph. Complex scripts will operate and appear exactly the same visually to every user, using every type of computer, without any other required software installation dependencies, operating system or version updates, data conversion or reformatting work, etc. REBOL's size, portability, and free cost remove all limitations to transferring, computing, and presenting data in any environment, using any standard equipment.

And REBOL is powerful. Businesses around the globe have been relying on it to manage critical processes and large operations, for more than 15 years.

2.7 A Telling Comparison

To provide a quick idea of how much easier REBOL is than other languages, here's a short example. The following code to create a basic program window with REBOL was presented earlier:

view layout [size 400x300]

It works on every type of computer, in exactly the same way.

Code for the same simple example is presented below in the C++ language. It does the exact same thing as the REBOL one-liner above, except it only works on Microsoft Windows machines. If you want to do the same thing with a Macintosh computer, you need to memorize a completely different page of C++ code. The same is true for Linux or any other operating system. You have to learn enormous chunks of code to do very simple things, and those chunks of code are different for every type of computer. Furthermore, you typically need to spend a semester's worth of time learning very basic things about code syntax and fundamentals about how a computer 'thinks' before you even begin to tackle useful basics like the code below:

#include <windows.h>

/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

/*  Make the class name into a global variable  */
char szClassName[ ] = "C_Example";

int WINAPI
WinMain (HINSTANCE hThisInstance,
         HINSTANCE hPrevInstance,
         LPSTR lpszArgument,
         int nFunsterStil)

{
    HWND hwnd;               
    /* This is the handle for our window */
    MSG messages;            
    /* Here messages to the application are saved */
    WNDCLASSEX wincl;        
    /* Data structure for the windowclass */

    /* The Window structure */
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      
    /* This function is called by windows */
    wincl.style = CS_DBLCLKS;                 
    /* Catch double-clicks */
    wincl.cbSize = sizeof (WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                 
    /* No menu */
    wincl.cbClsExtra = 0;                      
    /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                      
    /* structure or the window instance */
    /* Use Windows's default color as window background */
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    /* Register window class. If it fails quit the program */
    if (!RegisterClassEx (&wincl))
        return 0;

    /* The class is registered, let's create the program*/
    hwnd = CreateWindowEx (
           0,                   
            /* Extended possibilites for variation */
           szClassName,         
            /* Classname */
           "C_Example",       
            /* Title Text */
           WS_OVERLAPPEDWINDOW, 
            /* default window */
           CW_USEDEFAULT,       
            /* Windows decides the position */
           CW_USEDEFAULT,       
            /* where the window ends up on the screen */
           400,                 
            /* The programs width */
           300,                 
            /* and height in pixels */
           HWND_DESKTOP,        
            /* The window is a child-window to desktop */
           NULL,                
            /* No menu */
           hThisInstance,       
            /* Program Instance handler */
           NULL                
            /* No Window Creation data */
           );

    /* Make the window visible on the screen */
    ShowWindow (hwnd, nFunsterStil);

    /* Run the message loop. 
        It will run until GetMessage() returns 0 */
    while (GetMessage (&messages, NULL, 0, 0))
    {
        /* Translate virtual-key messages 
            into character messages */
        TranslateMessage(&messages);
        /* Send message to WindowProcedure */
        DispatchMessage(&messages);
    }

    /* The program return-value is 0 - 
        The value that PostQuitMessage() gave */
    return messages.wParam;
}

/*  This function is called by the Windows 
        function DispatchMessage()  */

LRESULT CALLBACK
WindowProcedure (HWND hwnd, UINT message, 
    WPARAM wParam, LPARAM lParam)
{
    switch (message)                  
    /* handle the messages */
    {
        case WM_DESTROY:
            PostQuitMessage (0);       
                /* send a WM_QUIT to the message queue */
            break;
        default:                      
            /* for messages that we don't deal with */
            return DefWindowProc (hwnd, message, 
                wParam, lParam);
    }

    return 0;
}

Yuck. Back to REBOL...

3. Learning How Everything Works

If you do any significant study about other languages, you'll very quickly discover that trying to accomplish any of the sorts of things you've seen here, requires far more effort, understanding, frustration, and written lines of code, using any tool but REBOL.

At the tutorial links below, every one of the examples shown on this page have been fully documented, with line-by-line explanations of every function, variable, and language construct, in a way that is totally understandable, from the ground up, with absolutely no programming background required, and with absolutely no other study materials required:

http://business-programming.com

http://re-bol.com/rebol.html

The first text above, alone, contains more than 100 working applications of every type. Business apps for managing schedule, payroll, communications, financial data crunching, visual presentation, and every conceivable routine in normal business operations. Web site apps such as forum, page building, group coordination, data collection/processing/backup, and more. Classic game models, graphics, sound, utility scripts, and much more are all also covered in depth. Those texts teach everything you need to know, in detail, from the ground up. You'd have to read tens of thousands of instructional pages and take several years to really learn how to do all the same things in any other language.

A series of 68 YouTube video tutorials about REBOL (10 hours of video) is also available, if you prefer sitting back and watching. Don't expect to learn, however, without reading, then copying and pasting, then altering and editing, then looking up syntax, then writing from scratch, lots and lots of code. You'll need to repeat that process many times until you can apply design concepts and coding syntax fluently and intuitively.

A simple executable tutorial application is also available. It's worth downloading and running this Windows program just to see the really nice introductory demonstration programs.

A quick REBOL game programming tutorial is available here.

A tutorial about using REBOL with the Etsy API is available here.

An additional CGI web programming tutorial is available here (not recommended for absolute beginners).

A slideshow presentation covering the introduction of the business programming text is available here. This presentation is important to see, if you're trying to decide whether or not learning to program (or learning to program with REBOL), is "worth it" (it is!).

See http://re-bol.com/examples.txt for a complete REBOL code reference.

Go to http://rebolforum.com to ask questions.

4. Get a FREE Private REBOL Programming Lesson With Nick Antonaccio

The easiest way to start actually learning to write useful code, is to get some personal help.

Hi, my name is Nick Antonaccio. I teach private REBOL programming lessons online using state of the art video conferencing and screen sharing techniques. I'm a well known developer and instructor in the REBOL community (REBOLer of the year in 2010). You can read more about me here, and see some of the significant businesses I own and operate (entirely with REBOL software) here and here. I've been a pioneer in teaching online for nearly a decade, and was featured in an article on the front page of the New York Times in 2012. I have a Masters degree from IU and have created accredited courses and a required text book for that university. I've helped 100s of clients build critical business computing systems, and my own REBOL commercial software directly operates many millions of dollars of critical business transactions each year.

I can help you learn basic or advanced REBOL programming topics, or build from scratch any sort of custom application you imagine, quickly and easily with REBOL.

To introduce myself to new students and clients, I offer an absolutely free, private, no strings attached, one-one-one lesson and/or consultation, live online. If you'd like to take a free personal interactive lesson, if you'd like me to build you an application, or if you have any questions, you can get in touch with me 3 ways:

  1. Go to http://rebolforum.com to ask questions in the forum.
  2. Send an email to com2@com-pute.com, with the word "lessons" in the subject.
  3. Leave me a phone message at 267-352-3625.

Setting up a free lesson/consultation appointment is easy. Just let me know your preferred times, a little about your skill level and what you'd like to learn. Students must be 18 years or older, or have parents' permission. If you want me to create an application for you, let me know a little about your imagined program's specifications. You can read my article at http://www.wherecanifindaprogrammer.com/wherecanifindaprogrammer.html#section-2 to learn how to organize and communicate ideas about creating new apps.

Like REBOL, I keep my lessons easy, fun, and productive. There's really absolutely no catch to the free offer - it's simply the best way for me to introduce myself to new potential students and clients. If you're not interested in taking any more lessons or talking after the first free session, you'll never hear from me again. If you do want to take more lessons or if you do want help writing software, my rate is $25 per 1/2 hour. I am used to writing code on the spot, while clients watch, to create applications, and I can do it quickly. Please don't be afraid to call or write if you have any questions. I'm friendly, and I truly enjoy teaching REBOL to new students, and creating software. You will NOT get advertising messages from me unless you specifically ask to be contacted personally.

5. More Programs to Look Through

There are more than 1000 REBOL program donated by community members at rebol.org (more than 100 by yours truly). Here are a few more examples by this author which may inspire you to look at REBOL:

REBOL [title: "Blogger"]
page: "blog.html"
ftp-url: ftp://user:pass@site.com/public_html/folder/
html-url: join http://site.com/folder/ page
save/png %dot.png to-image layout/tight [box white 1x1]  ; blank image
view center-face gui: layout [
    h2 (form html-url)
    text "Title:"       t: field 400
    text "Link:"        l: field 400
    text "Image:"       i: btn 400 [i/text: request-file show i]
    text "Text:"        x: area  400x100
    across
    btn "Upload" [
        if error? try [existing-text: read html-url] [
            make-dir ftp-url
            write (join ftp-url page) ""
            existing-text: copy ""
        ]
        picture: last split-path to-file i/text
        write/binary (join ftp-url picture) (read/binary to-file i/text)
        write (join ftp-url page) rejoin [
            {<h1>} t/text {</h1>}
            {<img src="} picture {"><br><br>}
            now/date { } now/time { &nbsp; &nbsp; }
            {<a href="} l/text {">} l/text {</a><br><br>}
            {<center><table width=80%><tr><td><pre><strong>}
                x/text 
            {</strong></pre></td></tr></table></center><br><hr>}
            existing-text
        ]
        browse html-url
    ]
    btn "View" [browse html-url]
    btn "Edit" [editor (join ftp-url page)]
]

Here's a little graphic demo that shows how to draw and control the motion of a circle on the screen:

REBOL [title: "Controlling Drawn Graphics"]
pos: 200x200
view layout [
    scrn: box 400x400 black rate 0:0:0.1 feel [
        engage: func [face action event] [
            if action = 'time [
                scrn/effect/draw: copy []
                append scrn/effect/draw [circle pos 20]
                show scrn
            ]    
        ] 
    ] effect [ draw [] ]
    across
    btn "Up" [pos/y: pos/y - 10]
    btn "Down" [pos/y: pos/y + 10]
    btn "Left" [pos/x: pos/x - 10]
    btn "Right" [pos/x: pos/x + 10]
]

Here's a cool animation program based on the "image contort" idea you saw earlier:

REBOL [title: "Image Contort Animation"]
pos: 300x300
view layout [
    scrn: box pos black effect [
        draw [image logo.gif 0x0 300x0 300x300 0x300]
    ]
    btn "Animate" [
        for point 1 140 1 [
            scrn/effect/draw: copy reduce [
                'image logo.gif 
                (pos - 300x300)
                (1x1 + (as-pair 300 point))
                (pos - (as-pair 1 point))
                (pos - 300x0)
            ]
            show scrn
        ]
        for point 1 300 1 [
            scrn/effect/draw: copy reduce [
                'image logo.gif 
                (1x1 + (as-pair 1 point))
                (pos - 0x300)
                (pos - 0x0)
                (pos - (as-pair point 1))
            ]
            show scrn
        ]
        ; no "reduce" is required below, because no calculations
        ; occur in the draw block - they're just static coords: 
        scrn/effect/draw: copy [
            image logo.gif 0x0 300x0 300x300 0x300
        ]
        show scrn
    ]
]

This program was created to save sheets of guitar chord diagrams, so they can be viewed on a computer or displayed on a web site:

REBOL [Title: "Guitar Chord Diagram Maker"]
fretboard: load 64#{
iVBORw0KGgoAAAANSUhEUgAAAFUAAABkCAIAAAB4sesFAAAACXBIWXMAAAsTAAAL
EwEAmpwYAAAA2UlEQVR4nO3YQQqDQBAF0XTIwXtuNjfrLITs0rowGqbqbRWxEEL+
RFU9wJ53v8DN7Gezn81+NvvZXv3liLjmPX6n/4NL//72s9l/QGbWd5m53dbc8/kR
uv5RJ/QvzH42+9nsZ7OfzX62nfOPzZzzyNUxxh8+qhfVHo94/rM49y+b/Wz2s9nP
Zj+b/WzuX/cvmfuXzX42+9nsZ7OfzX4296/7l8z9y2Y/m/1s9rPZz2Y/m/vX/Uvm
/mWzn81+NvvZ7Gezn8396/4l2/n+y6N/f/vZ7Gezn81+tjenRWXD3TC8nAAAAABJ
RU5ErkJggg==
}
barimage: load 64#{
iVBORw0KGgoAAAANSUhEUgAAAEoAAAAFCAIAAABtvO2fAAAACXBIWXMAAAsTAAAL
EwEAmpwYAAAAHElEQVR4nGNsaGhgGL6AaaAdQFsw6r2hDIa59wCf/AGKgzU3RwAA
AABJRU5ErkJggg==
}
dot: load 64#{
iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAIAAAACUFjqAAAACXBIWXMAAAsTAAAL
EwEAmpwYAAAAFElEQVR4nGNsaGhgwA2Y8MiNYGkA22EBlPG3fjQAAAAASUVORK5C
YII=
}
movestyle: [
    engage: func [f a e] [
        if a = 'down [
            initial-position: e/offset
            remove find f/parent-face/pane f
            append f/parent-face/pane f
        ]
        if find [over away] a [
            f/offset: f/offset + (e/offset - initial-position)
        ]
        show f
    ]
]
gui: [
    backdrop white
    currentfretboard: image fretboard 255x300
    currentbar: image barimage 240x15 feel movestyle
    text "INSTRUCTIONS:" underline
    text "Drag dots and other widgets onto the fretboard."
    across    
    text "Resize the fretboard:"
    tab 
    rotary "255x300" "170x200" "85x100" [
        currentfretboard/size: to-pair value show currentfretboard
        switch value [
            "255x300" [currentbar/size: 240x15 show currentbar]
            "170x200" [currentbar/size: 160x10 show currentbar]
            "85x100" [currentbar/size: 80x5 show currentbar]
        ]
    ]
    return
    button "Save Diagram" [
        filename: to-file request-file/save/file "1.png"
        save/png filename to-image currentfretboard
    ]
    tab
    button "Print" [
        filelist: sort request-file/title "Select image(s) to print:"
        html: copy "<html><body>"
        foreach file filelist [
            append html rejoin [
                {<img src="file:///} to-local-file file {">}
            ]
        ]
        append html [</body></html>]
        write %chords.html trim/auto html
        browse %chords.html 
    ]
]
loop 50 [append gui [at 275x50 image dot 30x30 feel movestyle]]
loop 50 [append gui [at 275x100 image dot 20x20 feel movestyle]]
loop 50 [append gui [at 275x140 image dot 10x10 feel movestyle]]
loop 6 [append gui [at 273x165 text "X" bold feel movestyle]]
loop 6 [append gui [at 273x185 text "O" bold feel movestyle]]
view layout gui

This guitar chord program is a bit more complex. It uses REBOL's draw dialect to create professional looking fretboard diagrams for any type of chord possible:

REBOL [title: "Jazz Guitar Chords"]
root6-shapes: [
    "." "major triad, no symbol (just a root note)" [1 3 5 11 55 111]
    "m" "minor triad, min, mi, m, -" [1 b3 5 11 55 111]
    "aug" "augmented triad, aug, #5, +5" [1 3 b6 11 111]
    "dim" "diminished triad, dim, b5, -5" [1 b3 b5 11]
    "5" "power chord, 5" [1 55]
    "sus4" "sus4, sus" [1 4 5 11 55 111]
    "sus2" "sus2, 2" [1 99 5 11]
    "6" "major 6, maj6, ma6, 6" [1 3 5 6 11]
    "m6" "minor 6, min6, mi6, m6" [1 b3 5 6 11]
    "69" "major 6/9, 6/9, add6/9" [1 111 3 13 9]
    "maj7" "major 7, maj7, ma7, M7, (triangle) 7" [1 3 5 7 11 55]
    "7" "dominant 7, 7" [1 3 5 b7 11 55]
    "m7" "minor 7, min7, mi7, m7, -7" [1 b3 5 b7 11 55]
    "m7(b5)" "half diminished, min7(b5), (circle w/ line), m7(-5), -7(b5)"
        [1 b3 b5 b7 11]
    "dim7" "diminished 7, dim7, (circle) 7" [1 b3 b5 6 11]
    "7sus4" "dominant 7 sus4 (7sus4)" [1 4 5 b7 55 11]
    "7sus2" "dominant 7 sus2 (7sus2)" [1 b7 99 5 11]
    "7(b5)" "dominant 7 flat 5, 7(b5), 7(-5)" [1 3 b5 b7 11]
    "7(+5)" "augmented 7, 7(#5), 7(+5)" [1 3 b6 b7 11]
    "7(b9)" "dominant 7 flat 9, 7(b9), 7(-9)" [1 3 5 b7 b9]
    "7(+9)" "dominant 7 sharp 9, 7(#9), 7(+9)" [1 111 3 b77 b33]
    "7(b5b9)" "dominant 7 b5 b9, 7(b5b9), 7(-5-9)" [1 3 b5 b7 b9]
    "7(b5+9)" "dominant 7 b5 #9, 7(b5#9), 7(-5+9)" [1 3 b5 b7 b33]
    "7(+5b9)" "augmented 7 flat 9, aug7(b9), 7(#5b9)" [1 3 b6 b7 b9]
    "7(+5+9)" "augmented 7 sharp 9, aug7(#9), 7(#5#9)" [1 3 b6 b7 b33]
    "add9" "add9, add2" [1 3 5 999 55 11]
    "madd9" "minor add9, min add9, m add9, m add2" [1 b3 5 999 55 11]
    "maj9" "major 9, maj9, ma9, M9, (triangle) 9" [1 3 5 7 9]
    "maj9(+11)" "major 9 sharp 11, maj9(#11), M9(+11)" [1 3 7 9 b5]
    "9" "dominant 9, 9" [1 3 5 b7 9 55]
    "9sus" "dominant 9 sus4, 9sus4, 9sus" [1 4 5 b7 9 55]
    "9(+11)" "dominant 9 sharp 11, 9(#11), 9(+11)" [1 3 b7 9 b5]
    "m9" "minor 9, min9, mi9, m9, -9" [1 b3 5 b7 9 55]
    "11" "dominant 11, 11" [1 b7 99 44 11]
    "maj13" "major 13, maj13, ma13, M13, (triangle) 13" [1 3 55 7 11 13]
    "13" "dominant 13, 13" [1 3 55 b7 11 13]
    "m13" "minor 13, min13, mi13, m13, -13" [1 b3 55 b7 11 13]
]
root6-map:  [
    1 20x70 11 120x70 111 60x110 3 80x90 33 40x50 b3 80x70 5 100x70
    55 40x110 b5 100x50 7 60x90 b7 60x70 9 120x110 99 80x50 6 60x50
    13 100x110 4 80x110 44 100x30 999 60x150 b77 100x130 b33 120x130
    b9 120x90 b6 100x90 b55 40x90
]
root5-shapes: [
    "." "major triad, no symbol (just a root note)" [1 3 5 11 55]
    "m" "minor triad, min, mi, m, -" [1 b3 5 11 55]
    "aug" "augmented triad, aug, #5, +5" [1 3 b6 11 b66]
    "dim" "diminished triad, dim, b5, -5" [1 b3 b5 11]
    "5" "power chord, 5" [1 55]
    "sus4" "sus4, sus" [1 4 5 11 55]
    "sus2" "sus2, 2" [1 9 5 11 55]
    "6" "major 6, maj6, ma6, 6" [1 3 55 13 11]
    "m6" "minor 6, min6, mi6, m6" [1 b3 55 13 11]
    "69" "major 6/9, 6/9, add6/9" [1 33 6 9 5]
    "maj7" "major 7, maj7, ma7, M7, (triangle) 7" [1 3 5 7 55]
    "7" "dominant 7, 7" [1 3 5 b7 55]
    "m7" "minor 7, min7, mi7, m7, -7" [1 b3 5 b7 55]
    "m7(b5)" "half diminished, min7(b5), (circle w/ line), m7(-5), -7(b5)"
        [1 b3 b5 b7 b55]
    "dim7" "diminished 7, dim7, (circle) 7" [1 b33 b5 6 111]
    "7sus4" "dominant 7 sus4, 7sus4" [1 4 5 b7 55]
    "7sus2" "dominant 7 sus2, 7sus2" [1 9 5 b7 55]
    "7(b5)" "dominant 7 flat 5, 7(b5), 7(-5)" [1 33 b5 b7 111]
    "7(+5)" "augmented 7, 7(#5), 7(+5)" [1 33 b6 b7 111]
    "7(b9)" "dominant 7 flat 9, 7(b9), 7(-9)" [1 33 5 b7 b9]
    "7(+9)" "dominant 7 sharp 9, 7(#9), 7(+9)" [1 33 b7 b3]
    "7(b5b9)" "dominant 7 b5 b9, 7(b5b9), 7(-5-9)" [1 33 b5 b7 b9]
    "7(b5+9)" "dominant 7 b5 #9, 7(b5#9), 7(-5+9)" [1 33 b5 b7 b3]
    "7(+5b9)" "augmented 7 flat 9, aug7(b9), 7(#5b9)" [1 33 b6 b7 b9]
    "7(+5+9)" "augmented 7 sharp 9, aug7(#9), 7(#5#9)" [1 33 b7 b3 b6]
    "add9" "major add9, add9, add2" [1 3 5 99 55]
    "madd9" "minor add9, min add9, m add9, m add2" [1 b3 5 99 55]
    "maj9" "major 7, maj9, ma9, M9, (triangle) 9" [1 33 5 7 9]
    "maj9(+11)" "major 9 sharp 11, maj9(#11), M9(+11)" [1 33 b5 7 9]
    "9" "dominant 9, 9" [1 33 5 b7 9]
    "9sus" "dominant 9 sus4, 9sus4, 9sus" [1 44 5 b7 9]
    "9(+11)" "dominant 9 sharp 11, 9(#11), 9(+11)" [1 33 b5 b7 9]
    "m9" "minor 9, min9, mi9, m9, -9" [1 b33 5 b7 9]
    "11" "dominant 11, 11" [1 b7 9 44 444]
    "maj13" "major 13, maj13, ma13, M13, (triangle) 13" [1 3 55 7 13]
    "13" "dominant 13, 13" [1 3 55 b7 13]
    "m13" "minor 13, min13, mi13, m13, -13" [1 b3 55 b7 13]
]
root5-map:  [
    1 40x70 11 80x110 111 100x30 3 100x110 33 60x50 b33 60x30 5 120x70
    55 60x110 b5 120x50 7 80x90 b7 80x70 9 100x70 6 80x50 13 120x110
    4 100x130 44 60x70 444 120x30 99 80x150 b3 100x90 b9 100x50 b6 120x90
    b66 60x130 b55 60x90
]
root6-notes:  [
    "e" {12} "f" {1} "f#" {2} "gb" {2} "g" {3} "g#" {4} "ab" {4}
    "a" {5} "a#" {6} "bb" {6} "b" {7} "c" {8} "c#" {9} "db" {9} "d" {10}
    "d#" {11} "eb" {11}
]
root5-notes: [
    "a" {12} "a#" {1} "bb" {1} "b" {2} "c" {3} "c#" {4} "db" {4}
    "d" {5} "d#" {6} "eb" {6} "e" {7} "f" {8} "f#" {9} "gb" {9} "g" {10}
    "g#" {11} "ab" {11}
]
f: copy []
for n 20 160 20 [append f reduce ['line (as-pair 20 n) (as-pair 120 n)]]
for n 20 120 20 [append f reduce ['line (as-pair n 20) (as-pair n 160)]]
fretboard: to-image layout/tight [box white 150x180 effect [draw f]]
view center-face layout [
    across
    t1: text-list 60x270 data [
        "E" "F" "F#" "Gb" "G" "G#" "Ab" "A" "A#" "Bb" "B" "C" "C#" "Db"
        "D" "D#" "Eb"
    ]
    t2: text-list 330x270 data extract/index root6-shapes 3 2 [
        either empty? a/text [
            a/text: rejoin [
                copy t1/picked " "
                pick root6-shapes ((index? find root6-shapes value) - 1)
            ]
        ] [
            a/text: rejoin [
                a/text newline copy t1/picked " " 
                pick root6-shapes ((index? find root6-shapes value) - 1)
            ]
        ]
        show a
    ]
    return
    a: area
    return
    btn "Create Chart" [if error? try [
        make-dir %chords
        delete/any %chords/*.*
        html: copy "<html><body bgcolor=#ffffffff>"
        foreach [root spacer1 spacer2 type] (parse/all form a/text " ") [
            diagram: copy [image fretboard]
            diagram2: copy [image fretboard]
            root1: copy root
            foreach itvl (third find root6-shapes type) [
                either find [1 55] itvl [
                    append diagram reduce [
                        'fill-pen white 'circle (select root6-map itvl) 5
                    ]
                ] [
                    append diagram reduce [
                        'fill-pen black 'circle (select root6-map itvl) 5
                    ]
                ]
            ]
            append diagram reduce ['text (trim/all join root1 type) 20x0]
            append diagram reduce [
                'text 
                trim/all to-string (
                    select root6-notes trim/all to-string root1
                )
                130x65
            ]
            save/png
                to-file trim/all rejoin [
                    %./chords/ (replace/all root1 {#} {sharp}) type ".png"
                ]
                to-image layout/tight [
                box white 150x180 effect [draw diagram]
            ]
            append html rejoin [
                {<img src="./} 
                trim/all rejoin [
                    replace/all copy root1 {#} {sharp} type ".png"
                ]
                {">}
            ]
            foreach itvl (third find root5-shapes type) [
                either find [1] itvl [
                    append diagram2 reduce [
                        'fill-pen white 'circle (select root5-map itvl) 5
                    ]
                ] [
                    append diagram2 reduce [
                        'fill-pen black 'circle (select root5-map itvl) 5
                    ]
                ]
            ]
            append diagram2 reduce ['text (trim/all join root type) 20x0]
            append diagram2 reduce [
                'text 
                trim/all to-string (
                    select root5-notes trim/all to-string root
                )
                130x65
            ]
            save/png 
                to-file trim/all rejoin [
                    %./chords/ (replace/all root {#} {sharp}) 
                    type "5th.png"
                ]
                to-image layout/tight [
                box white 150x180 effect [draw diagram2]
            ]
            append html rejoin [
                {<img src="./} (trim/all rejoin [
                    replace/all root {#} {sharp} type "5th.png"
                ]) {">}
                ; {<img src="./spacer.bmp">}
            ]
        ]
        append html [</body></html>]
        write %./chords/chords.html trim/auto html
        browse %./chords/chords.html 
    ] [alert "Error - please remove improper chord labels."]]
    btn "Save" [
        savefile: to-file request-file/file/save %/c/mysong.txt
        if exists? savefile [
            alert "Please choose a file name that does not already exist."
            return
        ]
        if error? try [save savefile a/text] [alert "File not saved"]
    ]
    btn "Load" [
        if error? try [
            a/text: load to-file request-file/file %/c/mysong.txt
            show a
        ] []
    ]
]

Here's a little app that allows the users to select any number of images, and create a thumbnail mosaic, with chosen image size, spacing, coloring, and other layout attributes:

REBOL [Title: "Thumbnail Maker"]
view center-face layout [
    text "Resize input images to this height:"
    height: field "200"
    text "Create output mosaic of this width:"
    width: field "600"
    text "Space between thumbnails:"
    padding-size: field "30"
    text "Color between thumbnails:"
    btn "Select color" [background-color: request-color/color white]
    text "Thumbnails will be displayed in this order:"
    the-images: area
    across
    btn "Select images" [
        some-images: request-file/title trim/lines {Hold
            down the [CTRL] key to select multiple images:} ""
        if some-images = none [return] 
        foreach single-image some-images [
           append the-images/text single-image
           append the-images/text "^/"
        ]
        show the-images
    ]
    btn "Create Thumbnail Mosaic" [
        y-size: to-integer height/text
        mosaic-size: to-integer width/text
        padding: to-integer padding-size/text
        if error? try [background-color: to-tuple background-color][
            background-color: white
        ]
        images: copy parse/all the-images/text "^/"   ; see "PARSE" below
        if empty? images [alert "No images selected." break]
        mosaic: compose [
            backcolor (background-color) space (padding) across
        ]
        foreach picture images [
             flash rejoin ["Resizing " picture "..."]
             original: load to-file picture
             unview
             either original/size/2 > y-size [
                 new-x-factor: y-size / original/size/2
                 new-x-size: round original/size/1 * new-x-factor
                 new-image: to-image layout/tight [
                     image original as-pair new-x-size y-size
                 ]
                 append mosaic compose [image (new-image)]
             ][
                 append mosaic compose [image (original)]
             ]
             current-layout: layout/tight mosaic
             if current-layout/size/1 > mosaic-size [
                 insert back back tail mosaic 'return
             ]
        ]
        filename: to-file request-file/file/save "mosaic.png"
        save/png filename (to-image layout mosaic)
        view/new layout [image load filename]
    ]
]

Here's an addictive game. Pick any image on your computer, chop it up into a few (or many) pieces, then try to put the jigsaw puzzle back together:

REBOL [title: "Jigsaw Puzzle"]
random/seed now
pic: load request-file/only/filter ["*.png" "*.gif" "*.jpg" "*.bmp"]
siz: pic/size
while [any [
    siz/1 > system/view/screen-face/size/1 
    siz/2 > system/view/screen-face/size/2
]] [
    siz: siz * .8   pic: to-image layout/tight [image pic siz]
]
divs: request-list "How many pieces?" [4 16 36 64 100 144 256 400]
sqr: square-root divs
x-size: round (siz/x / sqr)
y-size: round (siz/y / sqr)
p-size: as-pair x-size y-size
end: false
movestyle: [
    engage: func [f a e] [if end = false [
        if a = 'down [
            f/data: e/offset
            remove find f/parent-face/pane f
            append f/parent-face/pane f
        ]
        if find [over away] a [
            unrounded-pos: (f/offset + e/offset - f/data)
            snap-x: (round/to first unrounded-pos x-size)
            snap-y: (round/to second unrounded-pos y-size)
            either any [
                snap-x >= siz/1  snap-x < 0  snap-y >= siz/2  snap-y < 0
            ] [f/offset: unrounded-pos] [f/offset: as-pair snap-x snap-y]
        ]
        show f
        if all [a = 'up  pic = to-image system/view/screen-face/pane/1] [
            end: true  alert "Congratulations - you finished!"
        ]
    ]]
]
gui: compose [size (siz) key #" " [view/new layout [image (pic)]]]
repeat i (to-integer sqr) [
    repeat ii (to-integer sqr) [
        pos: as-pair (x-size * (ii - 1)) (y-size * (i - 1))
        append gui compose/deep [
            at random (siz - p-size) image pic (p-size) effect compose [
                crop (pos) (p-size)
            ] feel movestyle
        ]
    ]
]
alert {Press the space bar at any time to view the original image.}
view center-face layout/tight gui

Here's a fully functional Bingo game, with a built in board designer:

REBOL [title: "Bingo"]
write/append %bingo_history.txt rejoin [
    newline newline "NEW GAME:  " now newline newline
]
write %bingo_designer.r {rebol []
    view center-face board-gui: layout/tight [
        size 200x240 across space 0x0
        style b button red 40x40 font-size 28 [
            alert {
                Click the squares, then press the 'S' 
                key to save the image.
            }
        ]
        style n button blue 40x40 effect [] [
            either face/color = blue [
                face/color: white show face
            ] [
                face/color: blue show face
            ]
        ]
        b "B" b "I" b "N" b "G" b "O" return
        n n n n n return
        n n n n n return
        n n n n n return
        n n n n n return
        n n n n n return
        key keycode #"s" [
            save/png file-name: to-file request-file/only/save/file
                %bingo-board_1.png to-image board-gui
            view/new layout [image load file-name]
        ]
    ]
}
insert-event-func [
    either event/type = 'close [
        really: request "Really close the program?"
        if really = true [quit]
    ] [event]
]
cur-let: copy ""
view center-face layout/tight [
    size 1024x768 across space 0x0
    style bb button 64x72 red bold font [size: 48] [
        if ((request/confirm "End game?") = true) [quit]
    ]
    style nn button 64x72 black bold font [size: 14 color: 23.23.23] [
        either face/font/size = 14 [
            set-font face size 46 
            set-font face color white
            show face
            cur-num: to-integer face/text
            case [
                (cur-num <= 15) [cur-let: "B"]
                ((cur-num > 15) and (cur-num <= 30))  [cur-let: "I"]
                ((cur-num > 30) and (cur-num <= 45))  [cur-let: "N"]
                ((cur-num > 45) and (cur-num <= 60))  [cur-let: "G"]
                ((cur-num > 60) and (cur-num <= 75))  [cur-let: "O"]
            ]
            write/append %bingo_history.txt rejoin [
                now "   " cur-let " " face/text newline
            ]
            box1/text: cur-let show box1
            loop 3 [
                box2/text: "" show box2 wait .4
                box2/text: face/text show box2 wait .85
            ]
        ] [
            set-font face size 14 
            set-font face color white
            show face
        ]
    ]
    bb "B" nn "1" nn "2" nn "3" nn "4" nn "5" 
        nn "6" nn "7" nn "8" nn "9" nn "10" 
        nn "11" nn "12" nn "13" nn "14" nn "15" return
    bb "I" nn "16" nn "17" nn "18" nn "19" nn "20" 
        nn "21" nn "22" nn "23" nn "24" nn "25" 
        nn "26" nn "27" nn "28" nn "29" nn "30" return
    bb "N" nn "31" nn "32" nn "33" nn "34" nn "35" 
        nn "36" nn "37" nn "38" nn "39" nn "40" 
        nn "41" nn "42" nn "43" nn "44" nn "45" return
    bb "G" nn "46" nn "47" nn "48" nn "49" nn "50" 
        nn "51" nn "52" nn "53" nn "54" nn "55" 
        nn "56" nn "57" nn "58" nn "59" nn "60" return
    bb "O" nn "61" nn "62" nn "63" nn "64" nn "65" 
        nn "66" nn "67" nn "68" nn "69" nn "70" 
        nn "71" nn "72" nn "73" nn "74" nn "75" return
    box white 512x60 
    box 200.200.255 512x60 font-color blue font-size 52 "Prize: $" [
        face/text: request-text/title/default 
            "Enter Prize Text:" face/text
    ]
    return
    box1: box white 512x80 "" font [size: 50 color: (blue / 2)] 
    box 200.200.255 512x80 font-size 38 font-color black "Current Game:"
    return
    box2: box white 512x240 "" font [size: 200 color: blue] 
    box 200.200.255 136x240
    image1: image 235.235.255 240x240   [
        either true = request/confirm "Create new image?" [
            launch %bingo_designer.r
        ] [
            if error? try [
                image1/image: load request-file/only show image1
            ] [alert "Error loading image."]
        ]
    ] 
    box 200.200.255 136x240
    return
    box white 512x30 
    box 200.200.255 512x30
]

This photo album web app can be copied to any server to display all the photos in a folder, as a web page:

#!./rebol276 -cs
REBOL [title: "Web Site Photo Album"]
print "content-type: text/html^/"
print [<HTML><HEAD><TITLE>"Photos"</TITLE></HEAD><BODY>]
attempt [print read %pageheader.html]
folder: read %.
count: 0
foreach file folder [
    foreach ext [".jpg" ".gif" ".png" ".bmp"] [
        if find file ext [
            print [<BR> <CENTER>]
            print rejoin [{<img src="} file {">}]
            print [</CENTER>]
            count: count + 1
        ]
    ]
]
print [<BR>]
print rejoin ["Total Images: " count]
attempt [print read %pagefooter.html]]

This is a powerful and configurable utility that allows users to search for text within files on a hard drive. It starts in any chosen folder and spiders it's way down through all sub-folders, seaching every single file and displaying a list of found results:

REBOL [title: "Simple Search"]
phrase: request-text/title/default "Text to Find:" "the"
start-folder: request-dir/title "Folder to Start In:"
change-dir start-folder
found-list: ""
recurse: func [current-folder] [ 
    foreach item (read current-folder) [ 
        if not dir? item [  if error? try [
            if find (read to-file item) phrase [
                print rejoin [{"} phrase {" found in:  } what-dir item]
                found-list: rejoin [found-list newline what-dir item]
            ]] [print rejoin ["error reading " item]]
        ]
    ]
    foreach item (read current-folder) [ 
        if dir? item [
            change-dir item 
            recurse %.\
            change-dir %..\
        ] 
    ]
]
print rejoin [{SEARCHING for "} phrase {" in } start-folder "...^/"]
recurse %.\
print "^/DONE^/"
editor found-list
halt

Here's CGI version of the above app that can be used to search for files on your web server, using only a browser as the user interface:

#! /home/yourpath/public_html/rebol/rebol -cs
REBOL []
print "content-type: text/html^/"
print [<HTML><HEAD><TITLE>"Search"</TITLE></HEAD><BODY>]
; print read %template_header.html
submitted: decode-cgi system/options/cgi/query-string
if not empty? submitted [
    phrase: submitted/2
    start-folder: to-file submitted/4
    change-dir start-folder
    found-list: ""
    recurse: func [current-folder] [ 
        foreach item (read current-folder) [ 
            if not dir? item [  if error? try [
                if find (read to-file item) phrase [
                    print rejoin [{"} phrase {" found in:  }
                        what-dir item {<BR>}]
                    found-list: rejoin [found-list newline 
                        what-dir item]
                ]] [print rejoin ["error reading " item]]
            ]
        ]
        foreach item (read current-folder) [ 
            if dir? item [
                change-dir item 
                recurse %.\
                change-dir %..\
            ] 
        ] 
    ]
    print rejoin [{SEARCHING for "} phrase {" in } 
        start-folder {<BR><BR>}]
    recurse %.\
    print "<BR>DONE <BR>"
    ; save %found.txt found-list
    ; print read %template_footer.html
    quit
]
print [<CENTER><TABLE><TR><TD>]
print [<FORM ACTION="./search.cgi">]
print ["Text to search for:" <BR> 
    <INPUT TYPE="TEXT" NAME="phrase"><BR><BR>]
print ["Folder to search in:" <BR> 
    <INPUT TYPE="TEXT" NAME="folder" VALUE="../yourfolder/" ><BR><BR>]
print [<INPUT TYPE="SUBMIT" NAME="Submit" VALUE="Submit">]
print [</FORM>]
print [</TD></TR></TABLE></CENTER>]
; print read %template_footer.html

Here's an implementation of the classic "Snake" game. Eat the food and avoid hitting the walls:

REBOL [Title: "Snake Game"]
snake: to-image layout/tight [button red 10x10]
food: to-image layout/tight [button green 10x10]
the-score: 0  direction: 0x10  newsection: false  random/seed now
rand-pair: func [s] [
    to-pair rejoin [(round/to random s 10) "x" (round/to random s 10)]
]
b: reduce [
    'image food ((rand-pair 190) + 50x50) 
    'image snake ((rand-pair 190) + 50x50)
]
view center-face layout/tight gui: [
    scrn: box white 300x300 effect [draw b] rate 15 feel [
        engage: func [f a e] [
            if a = 'key [
                if e/key = 'up [direction: 0x-10] 
                if e/key = 'down [direction: 0x10]
                if e/key = 'left [direction: -10x0]
                if e/key = 'right [direction: 10x0]
            ]
            if a = 'time [
                if any [b/6/1 < 0 b/6/2 < 0 b/6/1 > 290 b/6/2 > 290] [
                    alert "You hit the wall!" quit
                ]
                if find (at b 7) b/6 [alert "You hit yourself!" quit] 
                if within? b/6 b/3 10x10 [
                    append b reduce ['image snake (last b)]
                    newsection: true
                    b/3: (rand-pair 290)
                ]
                newb: copy/part head b 5  append newb (b/6 + direction)
                for item 7 (length? head b) 1 [
                    either (type? (pick b item) = pair!) [
                        append newb pick b (item - 3)
                    ] [
                        append newb pick b item
                    ]
                ]
                if newsection = true [
                    clear (back tail newb)
                    append newb (last b)
                    newsection: false
                ]
                b: copy newb
                show scrn
                the-score: the-score + 1 
                score/text: to-string the-score
            ]
        ]
    ]
    origin across h2 "Score:" 
    score: h2 bold "000000"
    do [focus scrn]
]

Here's another fun game. Ski down the mountain and avoid hitting the trees:

REBOL [title: "Ski Game"]
tree:  load to-binary decompress 64#{
eJzt18sNwjAQBFDTBSVw5EQBnLjQE1XRngmBQEj8Wa/3M4oYOZKBKHkaWwTO1/sh
jDkNx3N6HI7LcOzCfnz/9v5cMnEai7lj4mokT9C7XczUsrhvGSku6RkgDIbHAEP0
2EiIMBdMDuaOWZCSL91bQvCsSY4MHE9umXz7ydVi3xgltYvEKboexzVSlpTa614d
NonpUauIv176dX0ZTRgJlVgzNl25A3gkGwld1bkrNFqqedQfEI02AU9PjDeMpac/
ShKeTXylROqCImlXRFd9zkQoh4tp+GpqlSTnLnum4HTEzK/gjpmTpDxSASlHFqYU
EE/8nddG9n+9LIm8t9OeIEra2JZWDRSG4VEioa0UFCZFqv/aMQh2Rf790EnGgcJU
SVAer0Bhcp7/epVJvkHzBHjPfz+XSe6BwryC5gmQno3mAY3tpba2KAAA
}
skier-left: load to-binary decompress 64#{
eJyN0U8og2EcB/DvNrz+E5fJZSmRf9Ej76h3Ne1AIspyMQflpJDFU/KO1cQmSnGa
A3PYkvInB3kvuyzlgJolh+fCRUq5iBvP8+5lTvKrX33ep+/zp9/b2Tthhl6zvGt5
W3nX8TYhS1//MOGnSjNEa/AUxd0UVQ3raL9IYbBvA2OBI9Q0DqB6fAujl08Yi97D
Hr3F5EQYSss2OrrWEFo5xB+VO5Vx/skvnxmQbDCFvxcjMJ/b0s6LAZXGA3O0ZtTt
pW3WbJmDeMC8a1gE9o3bTBFI9YvGhrOKSueyEQpu9ri60vQFXFqPMx1K+sNWrdOh
73Y/uMr85fKdcIrJ0z6vxSfsYV5KCU2JEPNIlD9dFZ65AfXwD+HsKdAZiiLdqtvt
Hh65E5ZklTGmDvWLgxxKkjAivwt7XxhJEvIsrCY8ikLs0Tj3yGeCKaQtdsX9fv3G
N1jCJdyv84lHJkNriiM7Li29OIDV0jcU8kuIHaiPLEDEsG9DQYxiQTi0A8sBpEvh
OT65GmBYH9Jx5nf8TFFUFf5ZX2hFdG1uAgAA
}
skier-right: load to-binary decompress 64#{
eJxz8s1jYgCDMiDWAGIJINYCYkYGFrD4D0YGOBBAMBn4++Yz6HjVMSgY1oP5gWdu
M/gHTmCwNutlKJ26l6F03VUGp3XnGGo+/mGILVnMoFkwhaHm7GcGz4m7GbABFwST
eQWSNXMQbM+3DAwlULbmEgaWXih75QUGzvkQJstMBwbPRRA2L1D5yS8QNudioNQF
qNYPDExAZRCtDg78c6Fa7wZK3Ycq940O3L1fAcLWigpctUsZzHTSj5Jd+l7NAKS6
3HnXk6jHSiBF7sUmxi7Gl9VAZrqVOxsZuTirg8TTS0qAQs5FIPF0BhYXFkgog/zg
7gJlq5SXpaWVF4O9lZKuXl6eVl4AZLIfKS82LzYuB2nlOFxWXl5ubA6ytm1KWU65
cXExkMl09lNNR3q5eTFQPYfHE7YT6cXlJgcYGI7cPMAOMtKhgcH9wE8FBuPycgOG
BoYKtl8ODL4gjccY2HSAfr4BVMvgAwyazwwsXSA7ORgY2BQYeH+Cw+sAKPo5wEHj
kQAO/GZwIIHDgc0AaxQSBAAFOXD7bgIAAA==
}
random/seed now
the-score: 0
board: reduce ['image 300x20 skier-right black]
for i 1 20 1 [
    pos: random 600x540
    pos: pos + 0x300
    append board reduce ['image pos tree black]
]
view center-face layout/tight [
    scrn: box white 600x440 effect [draw board] rate 0 feel [
        engage: func [f a e] [
            if a = 'key [
                if e/key = 'right [
                    board/2: board/2 + 5x0
                    board/3: skier-right
                ]
                if e/key = 'left [
                    board/2: board/2 - 5x0
                    board/3: skier-left
                ]
                show scrn
            ]
            if a = 'time [
                new-board: copy []
                foreach item board [
                    either all [
                        ((type? item) = pair!) 
                        ((length? new-board) > 4)
                    ] [ 
                        append new-board (item - 0x5) 
                    ] [
                        append new-board item
                    ]
                    coord: first back back (tail new-board)
                    if ((type? coord) = pair!) [
                        if ((second coord) < -60) [
                            remove back tail new-board
                            remove back tail new-board
                            remove back tail new-board
                            remove back tail new-board
                        ]
                    ]
          ]
                board: copy new-board
                if (length? new-board) < 84 [
                    column: random 600
                    pos: to-pair rejoin [column "x" 440]
                    append board reduce ['image pos tree black]
                ]
                collision-board: remove/part (copy board) 4
                foreach item collision-board [
                    if (type? item) = pair! [
                        if all [
                          ((item/1 - board/2/1) < 15)
                          ((item/1 - board/2/1) > -40)
                          ((board/2/2 - item/2) < 30)
                          ((board/2/2 - item/2) > 5)
                        ] [
                            alert "Ouch - you hit a tree!"
                            alert rejoin ["Final Score: " the-score]
                            quit
                        ]
                    ]
                ]
                the-score: the-score + 1 
                score/text: to-string the-score
                show scrn
            ]
        ]
    ]
    origin across h2 "Score:" 
    score: h2 bold "000000"
    do [focus scrn]
]

Here's an obfuscated an minified version of the snake game. This tiny script is a playable program!

do[p: :append u: :reduce k: :pick r: :random y: :layout q: 'image z: :if
g: :to-image v: :length? x: does[alert join{SCORE: }[v b]quit]s: g y/tight
[btn red 10x10]o: g y/tight[btn tan 10x10]d: 0x10 w: 0 r/seed now b: u[q
o(((r 19x19)* 10)+ 50x50)q s(((r 19x19)* 10)+ 50x50)]view center-face
y/tight[c: area 305x305 effect[draw b]rate 15 feel[engage: func[f a e][z a
= 'key[d: select u['up 0x-10 'down 0x10 'left -10x0 'right 10x0]e/key]z a
= 'time[z any[b/6/1 < 0 b/6/2 < 0 b/6/1 > 290 b/6/2 > 290][x]z find(at b
7)b/6[x]z within? b/6 b/3 10x10[p b u[q s(last b)]w: 1 b/3:((r 29x29)*
10)]n: copy/part b 5 p n(b/6 + d)for i 7(v b)1 [either(type?(k b i)=
pair!)[p n k b(i - 3)][p n k b i]]z w = 1[clear(back tail n)p n(last b)w:
0]b: copy n show c]]]do[focus c]]]

The program below lets you record your voice or other sounds to be played as alarms for any number of multiple events. Save and Load event lists. All alarm sounds repeat until stopped. Record yourself saying 'Remind the boss of his meeting with Jim' or 'Call home and make sure the kids walk the dog', then set alarms to play those voice messages on any given day/time. If you set the alarm as a date/time, the alarm will go off only once, on that date. If you set the alarm as a time, the alarm will go off every day at that time. The .wav recording code is MS Windows only, but the program can play any wave file that is usable in REBOL:

REBOL [title: "Voice Alarms"]
lib: load/library %winmm.dll
mci: make routine! [c [string!] return: [logic!]] lib "mciExecute"
write %play-alarm.r {
    REBOL []
    wait 0
    the-sound: load %tmp.wav
    evnt: load %event.tmp
    if (evnt = []) [evnt: "Test"]
    forever [
        if error? try [
             insert s: open sound:// the-sound wait s close s
        ] [
             alert "Error playing sound!"
        ]
        delay: :00:07
        s: request/timeout [
            join uppercase evnt " alarm - repeats until you click 'stop':"
            "Continue"
            "STOP"
        ] delay
        if s = false [break]
    ]
}
current: rejoin [form now/date newline form now/time]
view center-face layout [
    c: box black 400x200 font-size 50 current rate :00:01 feel [
        engage: func [f a e] [
            if a = 'time [
                c/text: rejoin [form now/date newline form now/time]
                show c
                if error? try [
                    foreach evnt (to-block events/text) [
                        if any [
                             evnt/1 = form rejoin [
                                 now/date {/} now/time
                             ]
                             evnt/1 = form now/time  
                        ] [
                            if error? try [
                                 save %event.tmp form evnt/3
                                 write/binary %tmp.wav 
                                 read/binary to-file evnt/2
                                 launch %play-alarm.r
                            ] [
                                 alert "Error playing sound!"
                            ]
                            ; request/timeout [(form evnt/3) "Ok"] :00:05
                        ]
                    ]
                ] []  ; do nothing if user is manually editing events
            ] 
        ] 
    ]
    h3 "Alarm Events (these CAN be edited manually):"
    events: area  ; {[8:00:00am %alarm1.wav "Test Alarm - DELETE ME"]}
    across
    btn "Record Alarm Sound" [
        mci "open new type waveaudio alias wav"
        mci "record wav"
        request ["*** NOW RECORDING *** Click 'stop' to end:" "STOP"]
        mci "stop wav"
        if error? try [x: first request-file/file/save %alarm1.wav] [
            mci "close wav"
            return
        ]
        mci rejoin ["save wav " to-local-file x]
        mci "close wav"
        request [rejoin ["Here's how " form x " sounds..."] "Listen"]
        if error? try [
            save %event.tmp "test"
            write/binary %tmp.wav 
            read/binary to-file x
            launch %play-alarm.r
        ] [
            alert "Error playing sound!"
        ]
    ]
    btn "Add Event" [
        event-name: request-text/title/default "Event Title:" "Event 1"
        the-time: request-text/title/default "Enter a date/time:" rejoin [
            now/date {/} now/time
        ]
        if error? try [set-time: to-date the-time] [
            if error? try [set-time: to-time the-time] [
                alert "Not a valid time!"
                break
            ]
        ]
        my-sound: request-file/title/file ".WAV file:""" %alarm1.wav
        if my-sound = none [break]
        event-block: copy []
        append event-block form the-time
        append event-block my-sound
        append event-block event-name
        either events/text = "" [spacer: ""][spacer: newline]
        events/text: rejoin [events/text spacer (mold event-block)]
        show events
    ]
    btn "Save Events" [
        write to-file request-file/file/save %alarm_events.txt events/text
    ]
    btn "Load Events" [
        if error? try [
            events/text: read to-file request-file/file %alarm_events.txt
        ] [return]
        show events
    ]
]

This example displays a real time word count of text in the area widget:

REBOL [title: "Word Count"]
view layout [
    i: info rate 0 feel [
        engage: func [f a e] [
            if a = 'time [
                l: length? parse m/text none
                i/text: join "Wordcount: " l
                show i
            ]
        ]
    ]
    m: area 
]

This is a slightly edited version of the 3D Maze program (raycasting engine) by Olivier Auverlot:

REBOL [title: "3D Maze - Ray Casting Example (by Olivier Auverlot)"] 
px: 9 * 1024  py: 11 * 1024 stride: 2 heading: 0 turn: 5
laby: [ 
    [ 8 7 8 7 8 7 8 7 8 7 8 7 ] 
    [ 7 0 0 0 0 0 0 0 13 0 0 8 ] 
    [ 8 0 0 0 12 0 0 0 14 0 9 7 ] 
    [ 7 0 0 0 12 0 4 0 13 0 0 8 ] 
    [ 8 0 4 11 11 0 3 0 0 0 0 7 ] 
    [ 7 0 3 0 12 3 4 3 4 3 0 8 ] 
    [ 8 0 4 0 0 0 3 0 3 0 0 7 ] 
    [ 7 0 3 0 0 0 4 0 4 0 9 8 ] 
    [ 8 0 4 0 0 0 0 0 0 0 0 7 ] 
    [ 7 0 5 6 5 6 0 0 0 0 0 8 ] 
    [ 8 0 0 0 0 0 0 0 0 0 0 7 ] 
    [ 8 7 8 7 8 7 8 7 8 7 8 7 ] 
] 
ctable: [] 
for a 0 (718 + 180) 1 [ 
    append ctable to-integer (((cosine a ) * 1024) / 20) 
] 
palette: [ 
    0.0.128 0.128.0 0.128.128 
    0.0.128 128.0.128 128.128.0 192.192.192 
    128.128.128 0.0.255 0.255.0 255.255.0 
    0.0.255 255.0.255 0.255.255 255.255.255 
] 
get-angle: func [ v ] [ pick ctable (v + 1) ]
retrace: does [ 
    clear display/effect/draw 
    xy1: xy2: 0x0 
    angle: remainder (heading - 66) 720 
    if angle < 0 [ angle: angle + 720 ] 
    for a angle (angle + 89) 1 [ 
        xx: px 
        yy: py 
        stepx: get-angle a + 90
        stepy: get-angle a 
        l: 0 
        until [ 
            xx: xx - stepx 
            yy: yy - stepy 
            l: l + 1 
            column: make integer! (xx / 1024) 
            line: make integer! (yy / 1024) 
            laby/:line/:column <> 0
        ] 
        h: make integer! (1800 / l) 
        xy1/y: 200 - h 
        xy2/y: 200 + h 
        xy2/x: xy1/x + 6 
        color: pick palette laby/:line/:column 
        append display/effect/draw reduce [ 
            'pen color 
            'fill-pen color 
            'box xy1 xy2 
        ] 
        xy1/x: xy2/x + 2  ; set to 1 for smooth walls 
    ] 
] 
player-move: function [ /backwards ] [ mul ] [ 
    either backwards [ mul: -1 ] [ mul: 1 ] 
    newpx: px - ((get-angle (heading + 90)) * stride * mul) 
    newpy: py - ((get-angle heading) * stride * mul) 
    c: make integer! (newpx / 1024) 
    l: make integer! (newpy / 1024) 
    if laby/:l/:c = 0 [ 
        px: newpx 
        py: newpy 
        refresh-display 
    ] 
] 
evt-key: function [ f event ] [] [ 
    if (event/type = 'key) [ 
        switch event/key [ 
            up [ player-move ] 
            down [ player-move/backwards ] 
            left [ 
                heading: remainder (heading + (720 - turn)) 720 
                refresh-display 
            ] 
            right [ 
                heading: remainder (heading + turn) 720
                refresh-display 
            ] 
        ] 
    ] 
    event 
] 
insert-event-func :evt-key 
refresh-display: does [ 
    retrace 
    show display 
] 
screen: layout [ 
    display: box 720x400 effect [ 
        gradient 0x1 0.0.0 128.128.128 
        draw [] 
    ] 
    edge [ 
        size: 1x1 
        color: 255.255.255 
    ] 
] 
refresh-display 
view screen

I use this next security script to make sure that there are no files chmod'd to 777 on my web servers. Built in is a routine that writes the name of every folder and every file on my server, to a text file. I run this one in a CGI console - it has saved me lots of trouble with hackers:

REBOL [title: "CHMOD 777 to 755"]
start-dir: what-dir
all-files: to-file join start-dir %find777all.txt
write all-files ""
recurse: func [current-folder] [
    out-data: copy ""
    write/append all-files rejoin["CURRENT_DIRECTORY:  " what-dir newline]
    call/output {ls -al} out-data
    write/append all-files join out-data newline
    foreach item (read current-folder) [ 
        if dir? item [
            change-dir item 
            recurse %.\
            change-dir %..\
        ] 
    ]
]
recurse %.\
file-list: to-file join start-dir %found777.txt
write file-list ""
current-directory: ""
foreach line (read/lines all-files) [
    if find line "CURRENT_DIRECTORY:  " [
        current-directory: line
    ]
    if find line "rwxrwxrwx" [
        write/append file-list rejoin [
            (find/match current-directory "CURRENT_DIRECTORY:  ")
            (last parse/all line " ")
        ]
        write/append file-list newline
    ]
]
foreach file (read/lines file-list) [
    call rejoin [{chmod 755 } (to-local-file file)]
]

I've used variations of the following script to rename all the files with a given extension in folders on my computer, to a different extension. This particular version of the script copies all the files to the same name, without any extension at all:

foreach file read %. [
    if (suffix? file) = %.src [
        write (to-file first parse file ".")(read to-file file)
    ]
]

Here's a 92 character version of the classic "FizzBuzz" program. Try pasting it right into the REBOL interpreter console:

repeat i 100 [
    j: "" if i // 3 = 0 [j:"fizz"]
    if i // 5 = 0 [j: join j "buzz"]
    if j = "" [j: i]
    print j
]

The following example demonstrates how to use the Captcha library from Softinov:

REBOL [title: "Captcha"]
write/binary %Caliban.caf read/binary http://re-bol.com/Caliban.caf
do http://re-bol.com/captcha.r
captcha/set-fonts-path %./
captcha/level: 4
write/binary %captcha.png captcha/generate
write %captcha.txt captcha/text
view center-face layout [
    image (load %captcha.png)
    text "Enter the captcha text:"
    f1: field [
        either f1/text = (read %captcha.txt) [
            alert "Correct"
        ] [
            alert "Incorrect"
        ]
    ] 
]

Here's a calendar program that displays events on a calendar. It's a CGI application that runs on a web site:

#!../rebol276 -cs
REBOL []
print "content-type: text/html^/"
print {<HTML><HEAD><TITLE>Event Calendar</TITLE></HEAD><BODY>}
write/append %events.db ""
bbs: load %events.db
date: now/date
html: copy rejoin [
    {<CENTER><TABLE border=1 valign=middle width=99% height=99%>
        <TR><TD colspan=7 align=center height=8%><FONT size=5>}
    pick system/locale/months date/month {  } date/year
    {</FONT></TD></TR><TR>}
]
days: ["Sun" "Mon" "Tue" "Wed" "Thu" "Fri" "Sat"]
foreach day days [
    append html rejoin [
        {<TD bgcolor="#206080" align=center width=10% height=5%>
        <FONT face="courier new,courier" color="FFFFFF" size="+1">}
        day 
        {</FONT></TD>}
    ]
]
append html {</TR><TR>}
sdate: date  sdate/day: 0  
loop sdate/weekday // 7 + 1 [append html {<TD bgcolor=gray></TD>}]
while [sdate/day: sdate/day + 1 sdate/month = date/month][
    event-labels: {}
    foreach entry bbs [
        date-in-entry: 1-Jan-1001
        attempt [date-in-entry: (to-date entry/3)]
        if (date-in-entry = sdate) [
            event-labels: rejoin [
                {<font size=1>}
                event-labels 
                "<strong><br><br>"
                {<a href="http://website.com/path/calendar">}
                entry/1 
                {</a>}
                "</strong>"
                {</font>}
            ]
        ]
    ]
    append html rejoin [
        {<TD bgcolor="#}
        either date/day = sdate/day ["AA9060"]["FFFFFF"]
        ; HERE, THE EVENTS ARE PRINTED IN THE APPROPRIATE DAY:
        {" height=14% valign=top>} sdate/day event-labels
        {</TD>}
    ]
    if sdate/weekday = 6 [append html {</TR><TR>}]
]
loop 7 - sdate/weekday [append html rejoin [{<TD bgcolor=gray></TD>}]]
append html {</TR></TABLE></CENTER></BODY></HTML>}
print html

Here's a math test program that can be used and modified by teachers:

REBOL [title: "Math Test - Simple"]
random/seed now
ceil: counter: total: score: 0
calculate: does [
    if error? try [
        either (to-integer f3/text) = do rejoin [
            (to-integer f1/text) " " oprtr/text " " (to-integer f2/text)
        ] [
            alert "Correct!"
            score: score + 1
        ] [
            alert "Wrong!!!!"
        ]
        total: total + 1
        counter: counter + 1
        if (counter > 10) [
            ceil: ceil + 10
            counter: 0
        ]
        f3/text: copy ""
        f1/text: copy form (random 9 + ceil)
        f2/text: copy form (random 9 + ceil)
        show gui
        focus f3
    ] [alert "** ERROR: Please type a number" focus f3]
]
show-score: does [
    alert rejoin [
        {You answered } score { CORRECT and } (total - score) { WRONG.}
    ]
]
view center-face gui: layout [
   f1: field copy form (random 9 + ceil)
   f2: field copy form (random 9 + ceil)
   f3: field 
   key #"^M" [calculate]
   across
   oprtr: rotary 40 "+" "-" "*" "/"
   btn "Score" [show-score]
   do [focus f3]
]

Here's a version of the math test program that makes use of a sprite sheet to display smiley and frowney faces based on correct and incorrect responses:

REBOL [title: "Math Test"] code: [
random/seed now
ceil: counter: total: score: 0
calculate: does [
    if error? try [
        either (to-integer f3/text) = do rejoin [
            (to-integer f1/text) " " oprtr/text " " (to-integer f2/text)
        ] [
            alert "Correct!"
            score: score + 1
            update-pic true
        ] [
            alert "Wrong!!!!"
            update-pic false
        ]
        total: total + 1
        counter: counter + 1
        if (counter > 10) [ceil: ceil + 10  counter: 0]
        f3/text: copy ""
        f1/text: copy form (random 9 + ceil)
        f2/text: copy form (random 9 + ceil)
        show gui
        focus f3
    ] [alert "** ERROR: Please type a number" focus f3]
]
show-score: does [
    alert rejoin [
        {You answered } score { CORRECT and } (total - score) { WRONG.}
    ]
]
update-pic: func [correct] [
    z: either correct [
        first random [0x0 64x0]
    ] [
        first random [0x64 64x64]
    ]
    img/image: to-image layout/tight [
        image 64x64 pic effect [crop z]
    ]
    show img
]
view center-face gui: layout [
   backdrop white
   f1: field copy form (random 9 + ceil)
   f2: field copy form (random 9 + ceil)
   f3: field 
   key #"^M" [calculate]
   across
   oprtr: rotary 40 "+" "-" "*" "/"
   btn "Score" [show-score]
   text ""
   img: image 64x64
   do [focus f3  update-pic true]
]]
pic: load to-binary decompress 64#{
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
2pzXAcrGJkNV9WaBnJzc/Rfn8/8D1e5Xw6EgAAA=
}
do code

Here's another simple game example which illustrates several useful GUI techniques:

REBOL [Title: "Collect the Boxes"]
random/seed now
start-time: now/time
level: to-integer request-text/title/default "Number of Boxes?" "10"
gui: [
    size 600x440  backdrop white
    at -99x0 key keycode [up]    [p/offset: p/offset + 0x-10 show p]
    at -99x0 key keycode [down]  [p/offset: p/offset + 0x10  show p]
    at -99x0 key keycode [left]  [p/offset: p/offset + -10x0 show p]
    at -99x0 key keycode [right] [p/offset: p/offset + 10x0  show p]
    at -99x0 box rate 0 feel [engage: func [f a e][if a = 'time [
        foreach f system/view/screen-face/pane/1/pane [
            if  f <> p [
                if within? (f/offset + 10x10) p/offset 30x30 [
                    remove find system/view/screen-face/pane/1/pane f
                    show system/view/screen-face/pane/1/pane
                ]
            ]
            if (length? system/view/screen-face/pane/1/pane) < 8 [
                alert rejoin ["Your time: " now/time - start-time]
                quit
            ]
        ]
    ]]]
]
for counter 1 level 1 [
    append gui [at random 590x420 box 10x10 random 255.255.255]
]
append gui [p: btn red 20x20]
view center-face layout gui

This email app allows you to save your email account information, and the correct user settings will automatically be loaded every time you run the program:

REBOL [title: "Email"]
m: system/schemes/default q: system/schemes/pop
x: read/lines %mlst m/user: x/1 m/pass: x/2 m/host: x/3 q/host: x/4
view layout [ style f field
    u: f "username" p: f "password" s: f "smtp.address" o: f "pop.address"
    btn bold "Save Server Settings" [
        foreach s reduce [
            m/user: u/text m/pass: p/text m/host: s/text q/host: o/text
        ] [write/append %mlst join s newline]
    ]
    e: f "user@website.com" j: f "Subject" t: area 
    btn bold "SEND" [
        send/subject to-email e/text t/text j/text alert "Sent"
    ]
    y: f "your.email@somesite.com"               
    btn bold "READ"[foreach i read to-url join "pop://" y/text [ask i]]
]

Here's a tricked out version of the data grid app you saw earlier. It demonstrates a number of nice features available in the data grid code:

REBOL [title: "Table/Grid/Listview Example With Expanded Features"]
headers: ["Numbers" "TEXT (Note Sort)" "Dates"]
x: [
    [1 "1" 1-1-2012]
    [11"11"1-2-2012]
    [2"2"1-3-2012]
]
colors: [blue black red]
empty-space: 235
svv/vid-face/color: white
gui-block: {
    h3 "RIGHT-CLICK/DRAG HEADERS TO RESIZE COLUMNS.  RESIZE WINDOW..."
    text "Click headers to sort (note that sort is DATA-TYPE SPECIFIC)."
    text "Notice Arrow Keys, PgUp/PgDn Keys, Scroll Bar, and highliting"
    text "Click any cell to edit data. Buttons load and save data to HD."
}
insert-event-func [either event/type = 'resize [resize-fit none] [event]]
do http://re-bol.com/gridcore.r
append gui-block [
    text "" return
    btn "Insert (Ins)" keycode [insert] [add-line] 
    btn "Remove (Del)" #"^~" [remove-line]  
    btn "Move (CTRL+M)" #"^M" [move-line]
    btn "Grow (+)" #"+" [resize-grid 1.333]
    btn "Shrink (-)" #"-" [resize-grid .75]
    btn "Fit (CTRL+R)" #"^R" [resize-fit]
    return
    btn "Load Blocked (CTRL+O)" #"^O" [load-blocked/request %blocked.txt]
    btn "Save Blocked (CTRL+S)" #"^S" [save-blocked/request %blocked.txt]
    btn "Load Flat (CTRL+U)" #"^U" [load-flat/request %flat.txt]
    btn "Save Flat (CTRL+F)" #"^F" [save-flat/request %flat.txt]
    ;  do [load-blocked %blocked.txt] 
]
view/options center-face gui: layout gui-block [resize]

6. One Last Note About Choosing Programming Languages to Learn

None of the mainstream language choices are as pleasant to learn or as productive to use as REBOL, and most have few, if any, benefits or capabilities that aren't easily accomplished with REBOL. REBOL can be used on its own to complete more total types of commercial software projects than almost any other tool. It also really does tend to make developers 2x-20x more productive, when it can be used. If you want to create software and still have hours of the day left to do other things besides write code, there are no other development tools that give you more time. Short and concise REBOL code also tends to be easier to debug and maintain than complex code created using other development tools.

Unfortunately, programming language popularity has much more to do with marketing power (financial influence) than with capability; and for reasons typically related to job security, project managers rarely choose to use anything but the best known and accepted language tools to build products. REBOL is not one of the popular programming languages. For most of its existence, REBOL was a closed source product, and developers chose to stay way from such products made by small companies. REBOL was just recently released as an open source product, so it can now be used and adopted in ways that were never possible before. But it will take many years before you can even hope to get a job writing REBOL code, unless you do it yourself. If your goal is to work as a professional programmer, learning REBOL can be helpful because it's so productive, but you will be required to learn mainstream development languages: Java, C, C#, PHP, and others that are popular.

In a commercial development environment, language choice is dictated by employers. No one ever gets fired for choosing to use Java on a project, even if the project takes 10 times as long to finish using Java tools. That's especially true from the point of view of commercial developers who charge for the time and work required to deliver a product! Keep that perspective in mind when the question arises "Why isn't REBOL popular?" and/or "Can I really use it to create software?".

This author has written hundreds of applications that have been in commercial use for years, and the productivity gains of programming in REBOL are second to none. REBOL has been used reliably in commercial settings around the world for more than 15 years. If for no other reason, it's exciting to study and learn about REBOL, just to understand it's sheerly unique qualities, and to recognize the extraordinary technical achievement that's packed into such a well engineered, minuscule tool. Beyond being a stable and capable professional software development platform, and a fantastic computing "pocket knife", you'll find yourself constantly using REBOL to complete automation and utility tasks, quick computations, and one-off scripts with speed and simplicity that are not available using any other tool. Becoming proficient with REBOL eliminates the need for many other computing tools, and increases productivity in ways that are just not otherwise possible.

Be sure to read my tutorials if you want to learn more. If you have questions, don't be afraid to write or post them on the forum!

Keywords:

easiest programming language, simplest programming language, easiest software development, easiest way to program a computer, easiest way to create apps, how to write software, computer programming, how to create programs, write code, learn about programming, coding, get started programming

Copyright Nick Antonaccio 2013, All Rights Reserved