A bind example

author: pat665
date: 3-nov-2002
contributions: Ladislav and Gabriele

Contents

1. Introduction
1.1. The starting point
1.2. Code is data
1.3. Now with a function
2. The problem
3. Solutions
3.1. A solution with 'bind
3.2. Explanations
3.3. Another solution with Gabriele's functional approach
3.4. Explanations

1. Introduction

Here is an example of bind usage I think valuable for newbies. I fall into this while transforming a "pascal-like" program to produce a more rebolistic code.

It is a bit long and fairly simplistic but each step can be tested. Hope some of you will learn a bit from it.

Note: 'bind is not the only answer to this kind of problem. As Ladislav pointed to me on the Rebol List, Gabriele's functional approach can also be used. This alternative approach is also provided in the following.

1.1. The starting point

That's what I call a "pascal-like" program.

Rebol [title: "Exemple 10.1"]

nb1: to-decimal ask "Enter number 1 :"
nb2: to-decimal ask "Enter number 2 :"
nb3: to-decimal ask "Enter number 3 :"

print "Your choice"
print "Sum      - 1 "
print "Product  - 2 "
print "Average  - 3 "

choice: ask "1|2|3 ? "

switch choice [
    "1"     [print ["Sum is "  nb1 + nb2 + nb3] ] 
    "2"     [print ["Product is " nb1 * nb2 * nb3]]
    "3"     [print ["Average is " (nb1 + nb2 + nb3) / 3]]
]

1.2. Code is data

In Rebol, code is data, data is code. So this version uses block of data to store the computation code.

Rebol [title: "Exemple 10.2"]

; prepared block
b-sum:  [nb1 + nb2 + nb3] 
b-prod: [nb1 * nb2 * nb3]
b-aver: [(nb1 + nb2 + nb3) / 3]


nb1: to-decimal ask "Enter number 1 :"
nb2: to-decimal ask "Enter number 2 :"
nb3: to-decimal ask "Enter number 3 :"

print "Your choice"
print "Sum      - 1 "
print "Product  - 2 "
print "Average  - 3 "

choice: ask "1|2|3 ? "

switch choice [
    "1"     [print ["Sum is "  do b-sum]] 
    "2"     [print ["Product is " do b-prod]]
    "3"     [print ["Average is " do b-aver]]
]

1.3. Now with a function

Doing the code is now performed in a function: fn-calculate.

Rebol [title: "Exemple 10.3"]

; prepared block
b-sum:  [nb1 + nb2 + nb3] 
b-prod: [nb1 * nb2 * nb3]
b-aver: [(nb1 + nb2 + nb3) / 3]

fn-calculate: func [cb [block!]][
    return do cb
]

nb1: to-decimal ask "Enter number 1 :"
nb2: to-decimal ask "Enter number 2 :"
nb3: to-decimal ask "Enter number 3 :"

print "Your choice"
print "Sum      - 1 "
print "Product  - 2 "
print "Average  - 3 "

choice: ask "1|2|3 ? "

switch choice [
    "1"     [calcul-bloc: b-sum] 
    "2"     [calcul-bloc: b-prod]
    "3"     [calcul-bloc: b-aver]
]

print ["Result: " fn-calculate calcul-bloc]

2. The problem

Beware this version is incorrect ! The goal here was to send to the function the values as parameters and the code block. Note that num1, num2, num3 are used in the main part. This is important because now nb1 do not exist anymore in the global context. So the function gives an error.

Rebol [title: "Exemple 10.4"]

; prepared block
b-sum:  [nb1 + nb2 + nb3] 
b-prod: [nb1 * nb2 * nb3]
b-aver: [(nb1 + nb2 + nb3) / 3]

fn-calculate: func [ 
    nb1 [decimal!]
    nb2 [decimal!]
    nb3 [decimal!]
    cb [block!]
    ][
    return do cb
]

num1: to-decimal ask "Enter number 1 :"
num2: to-decimal ask "Enter number 2 :"
num3: to-decimal ask "Enter number 3 :"

print "Your choice"
print "Sum      - 1 "
print "Product  - 2 "
print "Average  - 3 "

choice: ask "1|2|3 ? "

switch choice [
    "1"     [calcul-bloc: b-sum] 
    "2"     [calcul-bloc: b-prod]
    "3"     [calcul-bloc: b-aver]
]

print ["Result: " fn-calculate num1 num2 num3 calcul-bloc]

3. Solutions

To me, 'bind was the obvious solution ! However another technic is available, so we will discuss these two solutions here.

3.1. A solution with 'bind

A solution is to bind the block with the local word 'nb1.

Rebol [title: "Exemple 10.5"]

; prepared block
b-sum:  [nb1 + nb2 + nb3] 
b-prod: [nb1 * nb2 * nb3]
b-aver: [(nb1 + nb2 + nb3) / 3]

fn-calculate: func [ 
    nb1 [decimal!]
    nb2 [decimal!]
    nb3 [decimal!]
    cb [block!]
    ][
    return do bind cb 'nb1
]

num1: to-decimal ask "Enter number 1 :"
num2: to-decimal ask "Enter number 2 :"
num3: to-decimal ask "Enter number 3 :"

print "Your choice"
print "Sum      - 1 "
print "Product  - 2 "
print "Average  - 3 "

choice: ask "1|2|3 ? "

switch choice [
    "1"     [calcul-bloc: b-sum] 
    "2"     [calcul-bloc: b-prod]
    "3"     [calcul-bloc: b-aver]
]

print ["Result: " fn-calculate num1 num2 num3 calcul-bloc]

3.2. Explanations

Bind is needed to attach values to words. Values of word are stored in a context. Here for example, num1, num2, num3 are in the global context, while nb1, nb2, nb3 lives in the fn-calculate context. Because nb1, nb2, nb3 are on the same context, all the following binding are equivalent:

bind cb 'nb1
bind cb 'nb2
bind cb 'nb3

Each of these lines reads : the values for the words in block cb are to be found in the context of the word (nb1 nb2nb3).

3.3. Another solution with Gabriele's functional approach

Rebol [title: "Exemple 10.6"]

; prepared block
b-sum:  [nb1 + nb2 + nb3] 
b-prod: [nb1 * nb2 * nb3]
b-aver: [(nb1 + nb2 + nb3) / 3]

fn-calculate: function [
    nb1 [decimal!]
    nb2 [decimal!]
    nb3 [decimal!]
    cb [block!]
] [f] [
    f: func [nb1 nb2 nb3] cb
    f nb1 nb2 nb3
]

num1: to-decimal ask "Enter number 1 :"
num2: to-decimal ask "Enter number 2 :"
num3: to-decimal ask "Enter number 3 :"

print "Your choice"
print "Sum      - 1 "
print "Product  - 2 "
print "Average  - 3 "

choice: ask "1|2|3 ? "

switch choice [
    "1"     [calcul-bloc: b-sum] 
    "2"     [calcul-bloc: b-prod]
    "3"     [calcul-bloc: b-aver]
]

print ["Result: " fn-calculate num1 num2 num3 calcul-bloc]

3.4. Explanations

Here a temporary function f is created inside the fn-calculate function. The function code is the block received as a parameter in the fn-calculate function. Here the binding is implicit. The f function is then executed to produce the result.


Documentformater copyright Robert M. Münch. All Rights Reserved.
Formatted with Make-Doc-Pro Version:1.0.0 on 3-Nov-2002 at 20:41:48