3.1 binding
Joseph N. Wilson.
A binding is an association of a name to a value within a module. Both variable and constant bindings can be defined.
fun- principal
In a define
Chris Page
"constant" is probably a bad choice of terms. They're really just
"read-only variables". A module constant can change between runs of a
program, since they can be initialized from arbitrary code. For
example, a constant could contain the IP address of the computer it's
running on.
 
 
 
 
Joseph N. Wilson.
graphic
> But what do you mean above by a binding?


A binding is a name in some namespace, bound to a value. For example,
the name of every generic function, module variable, and local variable
is a "binding".

>>> list is not taken into account for selecting the correct procedure.
>>> Even Langauges like
>>> Ada 95 are able to do this!
>>
>> Again, functions are just bare methods that happen to be named. GFs
>> are a different kind of object, that is callable too, but does method
>> selection.
>
> This is what i mean by a flaw. I can't understand why this distinction
> is made?!

Note that when you define a method, it doesn't get a binding. Instead,
only the generic function has a name associated with it. The methods
are referred to by the generic function.

In Ada or C++ you can use "overloading" to have multiple functions with
different signatures, and the compiler treats each one as a separate
function. Since they are statically-typed languages, the compiler
always knows the exact types of the arguments at every call site, which
means it can always decide which function to call at compile-time based
upon the argument types.

In addition, each of those functions can only handle arguments of one
exact type. A C++ function that accepts int cannot also accept a float
in the same argument position.

In contrast, Dylan supports dynamic programming, where the exact types
of all the arguments at a given call site may not be known. In fact,
the types don't have to be known at all for the program to compile and
run correctly.

At runtime, argument types are used to select which method of a generic
function to call. This provides a similar behavior to "overloading",
except that the types don't have to be known at compile time. In fact,
the set of methods don't have to be known at compile time, either. The
set of methods in a generic function can be changed at runtime.

Since the compiler may not be able to determine which method to call,
the only information it can always rely upon to compile a function call
is the name of the generic function being called.

In Dylan, the name of a generic function identifies a "family" of
methods, and the generic function must have a unique name. In a way,
it's just a variation of "overloading" in C++, but it's more flexible
and powerful. Every generic function is like a set of overloaded,
non-member functions, and every method is like a virtual member
function in that you can have multiple methods handling different
subclasses of arguments.

By the way, if multiple generic functions had the same name, Dylan
would have to have yet another level of dispatching added to determine
which generic to call, and then determine which method to call. This
may or may not be a good idea, but Dylan doesn't have a way to do that,
currently. Instead, each generic is uniquely identified by its name and
function calls using that name can be successfully compiled.
3.1.1 to do
Is dynamic binding a key aspect?
   example is it possible to extend
     data Pet = Cat | Dog 
     data Domestic = Pet | |Cow | Horse

is qouted_var = '{ x  * y + z }
applied quoted_var ( x = 2, y = 4, z = 6 )
3.1.2 Binding and Scoping
Is not allowed to use one name for different bindings
Joseph N. Wilson
Dylan won't let one name have different types of bindings in a single context. That is, a name cannot refer to a generic function *and* some other kind of value.
[ In Dylan a namespace for bindings (the context of a binding) is the module.]
scoping constructs
Johan Ovlinger
I assume that there are scoping constructs so that two different method using the same naming don't interfere with each other?
Scott McKay
Of course, this has all been done in Lisp (CLOS) and Dylan. Generic functions are what you use to extend functionality, packages (or modules) are what you use to prevent clashes. 
In Dylan you can't create bindings at runtime
Jonathan Bachrach
In Dylan you can't create bindings at runtime, so, in the very least you must create a bunch of variables for your accessors up front.
If you don't create these bindings up front, then calls to accessors corresponding to these bindings would give rise to undefined binding errors when compiled.
 
 
3.1.3 module binding
what's the inverse of 'define variable ' and 'define method' ?
Bruce Hoult
what's the inverse of 'define variable ' and 'define method' ?
i.e.
? foo;
error: unbound variable: foo.
** Debugger **

Debug[1]> [interrupt -- returning to top level.]
? define variable foo = 99;
? foo;
==> 99
? WHATGOESHERE??
? foo;
error: unbound variable: foo.
** Debugger **
Seth LaForge
The point of define at the top level is that it creates a global binding. There are two things you can do to get the effect you want:
  • define the variable in it's own module (this prevents it from being visible elsewhere, unless you specifically export it; or
  • create a local binding using let. 
Here's an example of the latter:

? foo;
error: unbound variable: foo.
? begin
>   let foo = 99;
>   foo;
> end;
==> 99
? foo;
error: unbound variable: foo.
?
3.1.4 local binding
every time you see the word 'let' a NEW lexical context created
Brandon Corfman
Although I've gotten a few comments from people pointing out that you won't get a compiler error in C++ from the following:
void main()

    // OK, this a really silly example ...
    // but it illustrates my point ...
    char stuff[] = "Brandon";
    while (1)
    {
        char stuff[] = "Corfman";
    }
}
You will get an error from this:
void main()

    char stuff[] = "Brandon";
    char stuff[] = "Corfman";

at least I do under VC++.
But I won't get a compiler error with Dylan if I do this, but I think it would be certainly nice if I did:
define method main () => ()
  let answer :: <string> = "Brandon";
  let answer :: <string> = "Corfman";
end method main;
So I think my point is still valid.
 
No Becauce the equivalent C++ for the above Dylan code is
    void main ()
    {   
        char  stuff[] = "Brandon";
        { char stuff[] = "Corfman";
         }
    }
Which again will NOT issue any warning at all.
Every time you see the word 'let' a NEW lexical context created. If yo do not want a new lexical context, don't use the word.
To bind variable to a new value you can use a -setter method or the syntactic sugar equivalent, ':=' .
[ Personally, I think the word "assignment" carries too much baggage
  for C/Algol folks. The expectation is the "assignment" makes a
  copy. For the most part, no "copy" is created in Dylan unless you
  explicitly ask for one. ]
If you want to keep this straight then I'd suggest a slightly different coding style.
    define method main () =>  ()
    let answer :: <string> = "Brandon";
       let answer :: <string> = "Corfman";
    end method main;
Namely, indent for each new lexical scope you create.
[ I think some folks avoid this because they keep the "rule" straight
  in their head and want to avoid the code "drifting to the right".
  This has a negative impact on "newbies" though. ]
Jason Trenouth wrote
> I think a Dylan implementation is free to warn you about
> the circumstance you describe, its just the current
> implementations don't. ie you keep saying
There is nothing wrong.  It could be "style" warning is you had some Dylan style checker. ( where the style violations is either indentation or "reuse" depending on your preference) However, semantically if you would "warn" for this you should also "warn" if a function/method parameter is the same name as one in the outer scope. The two have effectively the same signficance. If don't want one it seem "hypocritical" to want the other.
Now this would be more blanantly obvious if there were either a requirement for an explicit 'end' for each 'let' or Dylan still had the prefix syntax.  
     let answer ....
       let answer ...
       end let
     end let
   or
     (let ...
       (let  ...
        )
     )
However, the current system has the benefit of cutting down on the number of "ends" you have to insert into your code.  Very often you would end up with sequence of 'end's. The current systax     manages to "reuse" the 'end' to close multiple "enclosures". This "special reuse" is only "combines" 'let' with others (or itself) so the meaning is straightforward once you know the rule.
why is 'let' allowed to float around?
Marco G. Antoniotti
The 'let' *is* allowed to float around in Dylan programs. As minor as it is, this really bothers me.
The point of having 'let' as syntactic sugar for a functional binding is somewhat lost in Dylan. A syntax like ML
let <bindings>
 in
   <ops>
 end
would have made more sense.
Paul Haahr
Which, in Dylan, would probably be transliterated as something like
let (bindings) body ... end
given the rest of the syntax.)
I have to admit that this bothered me, too, at first.  Until I started using it.  All of a sudden, I discovered the joy of not needing a new level of indentation just to introduce a new local variable.
(C++ programmers probably feel the same way:  C requires that local declarations appear at the beginning of a {} enclosed block, where C++ allows them in any statement position.  Very convenient.)
But, if you really don't like that bit of Dylan syntax after trying it, here's a ``bind'' macro which behaves like a Lisp/Scheme let*. The word ``let'' is one of the eight or so truly reserved words in Dylan that can't be renamed, so I had to use a different name.
  define macro bind
    { bind (?bindings) ?:body end }
    => { ?bindings; ?body }
   bindings:
    { ?binding:*, ... }
    => { let ?binding; ... }
    { }
    => { }
  end macro;
So, for example,
  bind (a = 1, b = 2)
    a + b
  end
  => 3
  bind (a = 1, b = a + 1)
    b
  end
  => 2
  bind (a = 13, a = 42)
    a
  end
  => 42
Marco G. Antoniotti
The problem with the choice made by the Dylan designers is that we'll see a lot of code written like
<statements>*
let newvar = 33;
<statements>*
let anothervar = 44;
<statements>*
Paul Haahr
I expect so, too. I've written lots of code like that myself. I think it's perfectly readable, maintainable code. I like it. What about it do you find problematic
Marco G. Antoniotti
Not Lispish enough :)
Enrico Colombini
> From: Paul Haahr: 
> I expect so, too. I've written lots of code like that
> myself. I think it's perfectly readable, maintainable code.
> I like it.
I like it too, and consider it a major readability improvement from Lisp (no holy wars, please).
Jeff Dalton
Look at it like this: Dylan-style "let" can more naturally replace assignment in more cases. And Dylan is trying to attract people away from languages where they'd be using assignment all over the place.
(I know there are arguments that point the other way. E.g. better attract them to a more functional style so that it's less likely that bad habits will be carried over. But, on balance, I think Dylan's "let" is at least a reasonable idea and probably a good one.)
>  <statements>*
>  let newvar = 33;
>  <statements>*
>  let anothervar = 44;
>  <statements>*
FWIF, I prefer code like that above to code w/ a single "let" at the top but with the other "lets" replaced by assignments.
Dylan's interpretation of let
Jeff Dalton
Dylan's interpretation of "let" solves a problem that can be significant in some other languages (such as Common Lisp, Scheme, and some functional languages), namely that introducing new variables also means increasing the indentation. Dylan also eliminates the problem in Common Lisp that let and multiple-value-bind are two separate forms, so that it's awkward to deal with multiple values together with other cases (though in CL one can, of course, write a macro).
I also think Dylan does a pretty good job of reducing the potential of equality / assignment confusion by using := for assignment and by having a keyword ("let") when = is used when introducing a variable.
There can be a period when learning a new language when certain mistakes seem to be often in the way. I think the right test here is whether programmers continue to be tripped up when they become more experienced. I suspect, though I can't prove it, that most programmers will end up finding Dylan's "let" to be pretty reasonable, or even rather nice.
The use of "let" for assignment in some varieties of Basic is very unusual when we consider the world of programming languages as a whole. "let" almost always has a declarative, variable- introduction, function, rather than being a way to assign to an existing variable. Even some Basics have adopted "set" for assignment, in recognition of this.
Indeed, as someone who has written a fair amount of Basic in a dialect that used "let" for assignment (though this was years ago), I quite like Dylan's "let".
There are some things about Dylan's syntax that I don't like, but "let" isn't one of them.
3.1.5 assignment
cannot assign a new value to an existing binding (variable) with let
Brandon Corfman
I'm was busy developing a console app in Dylan when I mistakenly wrote this piece of code:
 format-out("Do you want to play again? ");
  let answer :: <string> = read-line(*standard-input*);
  while (answer = "")
    format-out("Do you want to play again? ");
    let answer :: <string>
              = read-line(*standard-input*);
  end while;
The strange thing is, Dylan let me redefine answer without throwing an error. Then, when the program runs, the first read-line works correctly, but if I hit Enter so that the program drops into the while loop, it never comes out again.
It seems that the while condition is actually looking at the _original_ answer variable and not the newly redefined answer variable.
I don't understand this behavior, being new to Dylan. Can someone explain it to me?
Gabor Greif
You cannot assign a new value to an existing binding (variable) with let. Let always creates a new binding in the smallest enclosing scope (here the while body). This is the same in C++:
int main()

 string answer;
 cin >> answer;
 while (answer == "")
 {
  string answer;
  cin >> answer;
} // 2nd answer is destructed here...

If you want to assign to an existing binding, use the assignment operator:=
But I guess your problem is nicer solved by using tail recursion, thus not needing assignment at all:
begin
  local method
  play(prompt :: <string>,
         action :: <function>)
    format-out(prompt);
    let answer :: <string>
    = read-line(*standard-input*);
    if (answer = "")
      action();
      play(prompt, action);
    end
  end;
  play("Do you want to play again?\n",
     method()
        format-out("playing...\n");
    end)
end
(code not checked)
Hugh G. Greene
To quote the DRM (Chapter 14, Table 14-2):
 let      Creates and initializes new local bindings
          within the scope of the smallest enclosing
          implicit body.
(and from the description below)
  The bindings are visible for the remainder of the [body].
An "implicit body" includes the inside of "define method" and of "statement macros" like "while", "if", "for" etc.  The macro "let" creates new bindings (between names and values, or "locations for values") which last for the rest of the body.  It's valid to re-bind a name, in the same or a narrower scope, though you might want a warning from a compiler if you did it in the same scope.
In your code, the first binding of "answer" is in scope in the test clause of the while loop and in the body of the while loop, right up until after the second binding of "answer" (which shadows the first) and again after the while loop (because that's outside the implicit body where the second binding occurs).
What you want to do would be written like this:
 format-out("Do you want to play again? ");
  let answer :: <string> = read-line(*standard-input*);
  while (answer = "")
    format-out("Do you want to play again? ");
    answer := read-line(*standard-input*);
  end while;
where ":=" changes the value bound to the name "answer", rather than creating a new binding (with a separate "location").
Or, you could abbreviate it like this:
  local method ask () => (answer :: <string>)
    format-out("Do you want to play again? ");
    read-line(*standard-input*)
  end;
  let answer :: <string> = "";
  while ((answer := ask()) = "")
  end;
Does that help?
reassigning a new value to the variable doesn't affect the old value in any way.
Jason Pellerin
I still haven't made the mental leap Jasonfrom variables-in-c to variables- in- dylan.
I probably shouldn't be thinking in terms of variables at all, but in terms of objects, with a variable just being the name of some object
Mark Craig Chu- Carroll
Variables are even weaker than that in Dylan.
A variable is a *temporary* name for an object. "let a = make(<gobble>)" doesn't establish "a" as the name for the newly created object; it establishes a temporary binding from the name "a" to the newly created object.
Reassigning a new value to the variable doesn't affect the old value in any way.
let creates and initializes new local bindings within the scope of the smallest enclosing implicit body.
 
define method main () => ()
  let answer :: <string> = "Brandon";
  let answer :: <string> = "Corfman";
end method main;

But I won't get a compiler error with Dylan if I do this, but I think it would be certainly nice if I did:
 
No Becauce the equivalent C++ for the above Dylan code is
    void main ()
    {   
        char  stuff[] = "Brandon";
        { char stuff[] = "Corfman";
         }
    }
The following fits into the same category.
    let  index  = 23  ;
    for ( index  from 0  to 10 )
       a[index] := index * 23;
    end for;
    // index equals ??
After the loop, 'index' is 23. The loop's 'index' masks the "outer" let.
Hugh G. Greene
To quote the DRM (Chapter 14, Table 14-2):
 let        Creates and initializes new local bindings
            within the scope of the smallest enclosing
            implicit body.
(and from the description below)
  The bindings are visible for the remainder of the [body].
An "implicit body" includes the inside of "define method" and of "statement macros" like "while", "if", "for" etc.  The macro "let" creates new bindings (between names and values, or "locations for values") which last for the rest of the body.  It's valid to re-bind a name, in the same or a narrower scope, though you might want a warning from a compiler if you did it in the same scope.
In your code, the first binding of "answer" is in scope in the test clause of the while loop and in the body of the while loop, right up until after the second binding of "answer" (which shadows the first) and again after the while loop (because that's outside the implicit body where the second binding occurs).
What you want to do would be written like this:
 format-out("Do you want to play again? ");
  let answer :: <string> = read-line(*standard-input*);
  while (answer = "")
    format-out("Do you want to play again? ");
    answer := read-line(*standard-input*);
  end while;
where ":=" changes the value bound to the name "answer", rather than creating a new binding (with a separate "location").
Or, you could abbreviate it like this:

  local method ask () => (answer :: <string>)
    format-out("Do you want to play again? ");
    read-line(*standard-input*)
  end;
  let answer :: <string> = "";
  while ((answer := ask()) = "")
  end;
Does that help?
3.1.6 variables
Think of variables as labels
Neelakantan Krishnaswami
The easiest way to think about variables in Dylan is to think of them as labels you paste onto objects.
Imagine that you have an instance of <car>, maybe a VW Beetle. When you do
  let car-1 = make(<car>);
what happens is that first, you create a <car>, and then you use the let operation to paste a little sticky note labeled "car-   1" onto it.
Let's suppose that car.odometer == 0, since this is a new <car>. So if you then do:
  let car-2 = car-1;
what this means is "find the object with the sticky-note 'car- 1', and paste another note labelled 'car-2' to it." You haven't copied anything -- you now have a <car> with two sticky labels on it. So if you then
  drive-ten-thousand-miles(car-1);
Naturally the odometer(car-1) and odometer(car-2) will have the same reading, 10000, since they both refer to the same <car>, and it just drove ten thousand miles.
3.1.7 syntax
Talking about let using "=" while assignment uses ":="
Peter Hinely
Some aspects of Dylan's syntax bother me (maybe because I don't know what I am doing. :)
   let x = 1;   // declares a local variable
                // and binds it to an object
   x := 2;      // binds local variable to
                // another object
My question is, why do the two statements use a different operator? 
The assignment operator :=     vs.    equality operator =
Why didn't the designers of Dylan use the syntax:
     let x := 1;
It would seem to be more consistent syntax if they used the same operator.  Both statements are assignments, even though the first statement initializes x.  The only other difference that I can think of is that the scope of x begins right after the end of the "let" declaration statement that declares x.
     let x = x + 1;                 // ERROR
     x := x + 1;                    // VALID
Anyone want to comment on := vs. =  ?
Scott Fahlman
It was felt by the majority of the people involved in the decision that creation and initial binding of a variable is a conceptually different beast from reassignment of a variable. The latter is a non-functional, destructive operation and perhaps needs to be used with a bit more care. So it was felt that these operations shold look different.
I can see their point, but I think I would probably have gone the other way on this, using := for both. For me it's close to a toss- up, however, and some of the people who prefer that the two forms look different feel pretty strongly about it.
Antoun Kanawati
>  let x = 1;  // declares a local variable
>              // and binds it to an object
>
>   x := 2;    // binds local variable to
>              // another object
The first form introduces 'x' into the local environment, and associates it with an initial value. The second form changes the association of the symbol x with an object, but does not introduce any new bindings.
Dylan comes from a LISP heritage, where variables REFER to values, not contain values (like in C, or Pascal).
>  My question is, why do the two statements use a
>  different operator?
>
  The assignment operator :=   vs.   equality operator =
Actually, you're comparing the "let" binding form to assignment, which is not correct. The "=" operator in "let" is pure syntactic sugar, whereas the ":=" operator is the defining characteristic of an assignment expression.
> Why didn't the designers of Dylan use the syntax:
>
     let x := 1;
>
It would seem to be more consistent syntax if they
> used the same operator.  Both statements are
> assignments, even though the first statement initializes x. 
The two expressions are not assignment. The first is a binding form, whereas the second is a destructive assignment. There are significant differences between the two. The first's effect (introducing x into the lexical scope) is a compile time concept, whereas the second is a runtime mutation.
> The only other difference that I can think of
> is that the scope of x begins right after the end
> of the "let" declaration statement that declares x.
Actually, there is a significant difference in meaning. I'll use the Lispish syntax to demonstrate:
  (let ((x 3)) (+ x 1))
means
  ((lambda (x) (+ x 1)) 3)
That is, it is not assignment, whereas the second form explicitely means assignment.
Nick Kramer
C users probably don't see the distinction.  C++ users, though, shouldn't be entirely unfamiliar with the idea.  C++ draws a distinction between initialization and assignment.  I've been bitten at least once by this:
  class FOO {
  FOO();
  FOO(FOO& original); // Called a copy
                      // constructor
  FOO& operator= (FOO& foo1, FOO& foo2) { .... };
}
void main (void)
 {
  FOO foo1;
  foo1.something();
  FOO foo2 = foo1; // Invokes the copy
                   // constructor,
                   // *not* the = operator!
}
Anyhow, my point is merely that Dylan's distinction between binding and assignment is not entirely unheard of, even by C++ programemrs.
 
 
The syntax for global and local definitions
Peter Hinely
Why is the syntax for the declaration of global and local variables so different?  It seems inconsistent.
                                   // Declares and initializes
  define variable x = 1; // a global variable
  let x = 1;             // a local variable
Why didn't they use a syntax like:
  define global variable x = 1;
  define local variable x = 1;
(or some shortened version of something like that.)
The same can be said of methods:
  define method my-method (x)
    x;
  end method
  local method my-method (x)
    x;
  end;
The words to initialize the global vs. local functions do not follow a logical syntax.
Also the statments that end the methods are not the same.
   "end method" vs. "end;"
Also local methods are intialized with the syntax "local method", but local variables are initialized with "let".  It seems very inconsistent to me.
Or is there something more I should consider?  (I know realize that "global"  methods provide for generic functions.)
Scott E. Fahlman
>                                 // Declares and initializes
>  define variable x = 1; // a global variable
>  let x = 1;             // a local variable
Well, maybe this is an inheritance from Common Lisp.
"Define" is a top-level, global sort of thing.
But creating a global variable is a more heavyweight operation, with more consequences.
Paul Haahr
>Also the statments that end the methods are not the same.
>
   "end method" vs. "end;"
The word ``method'' is optional but permitted after ``end'' in both cases. I don't see what the problem is.
Scott E. Fahlman
It is curious that in the DIRM examples the "method" is pretty consitently omitted for local declarations and is kept for global ones.
That can be misleading, but the published grammar seems to be OK on this -- just hard to read.
Kim Barrett
The inconsistency being discussed here doesn't actually exist.
In the BNF from the DIRM, the syntax for both "local" and "define method" eventually reach "method-definition" as a common tail.
"method-definition" ends with "end method(opt) SYMBOL(opt)", so there's no difference between "local" and "define method" in this regard.