[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: assignment, reference, += and parameter passing



In SmallScript/Smalltalk this would be written as:

    Function [
    assign(a,b)
        a := b.
    ]

    Eval [
        |a| := 0.
        assign(a,1).
        stdout << a.
    ].

The lexical scope of <a> in the eval expression is unrelated to the
lexical scope of <a> in the assign() function. Meaning that while they
may both have the same name "a", they are two completely different
variables.

By default, variables are not passed in messages, only the objects the
variables refer to. So when the assign fn is invoked within the eval
expression, the contents of the <a> variable are what is passed; not a
reference to the variable itself. To pass the variable itself (as in
multiple return args), you must explicitly annotate the call/arg-sig as
a var-ref using "&" or "<in>, <out>, <byref>, etc" annotation.

        assign(&a,1)

And the receiver method should be declared as expecting a var-ref:

    Function [
    assign(&a,b)
        a := b.
    ]

If declared as var-refs then the assign fn would update the <a> variable
in the declared in the eval's lexical scope. Mismatches in declared
forms will generate runtime exceptions (i.e., calling a method with a
value, when it expects a var-ref, will generate an exception. Similarly,
if the var-ref is declared as both an <in> and an <out> type, then the
type of the object referred to by the arg-ref must also match the
binding constraint [multi-methods]. 

The type of the value being assigned is irrelevant and has no bearing on
the semantics of assignment and lexical scoping. If we had declared a
type constraint on the arguments to assign then it would have been
applied in the filtering of the method binding as in: Fn
[assign(<Integer>a,b) a:=b]. Or if we have declared a constraint on the
eval locals it might have generated static or runtime exceptions when an
type-constraint was violated by an assignment operation.

SmallScript/Smalltalk expressions/methods/statements (pick your
terminology) always return a value, even if it is the <void> object. In
our declaration of the "assign()" method/function we did not declare an
explicit return value so it will default to <self>, which for a function
is the class in which the function was declared, which would default to
the current module, which in an arbitrary script would be anonymous or
the <DefaultModule>.

To return the "assigned value", we would write the method/function as:
 
    Function [
    assign(a,b)
        ^a := b. "NOTE the ^"
    ]

A "Function" declaration is syntactic sugar for writing "class-method".
In Smalltalk/SmallScript, everything is a first class object. So classes
are real objects and Functions are just the methods of a class itself.

I S L
-----
N N N SmallScript/Smalltalk var
Y Y Y SmallScript/Smalltalk var-ref annotation "out, ref, &, ..."

SmallScript/Smalltalk also supports arbitrary assignment forms that
incorporate any binary selector message you can cook up. This is just a
shorthand (syntactic sugar).

    a :+= b.

Is sugar for: a := a + b.

    a :%@*&^%= b.

Is sugar for: a := a %@*&^% b.

Where the binary selector (message-name) "%@*&^%" is just a
binary-message-selector I made up for this example. I.e.,
SmallScript/Smalltalk allows you to define any arbitary combination of
binary-selector-symbols to form binary-message-selectors. A binary
message form, as the name implies, is just a message form that takes two
elements (a receiver, and one argument).
 
Messages such as "+", "-", "*", etc are not special forms
[SmallScript/Smalltalk doesn't really have a notion of special
"operator" forms].

-- Dave S. [SmallScript LLC]

SmallScript for the AOS & .NET Platforms
David.Simmons@SmallScript.com | http://www.smallscript.org


> -----Original Message-----
> From: owner-ll1-discuss@ai.mit.edu
[mailto:owner-ll1-discuss@ai.mit.edu]
> On Behalf Of Pixel
> Sent: Tuesday, December 18, 2001 5:51 PM
> To: ll1-discuss@ai.mit.edu
> Subject: assignment, reference, += and parameter passing
> 
> Goal: try to see how parameter passing mode interacts with "+="
> 
> Interesting difference: python's "+=" handling
> 
> 
> (there may be some errors, see my tests examples at
>  http://merd.net/pixel/language-study/various/assignment/)
>
------------------------------------------------------------------------
--
> ------
> Given:
>   def assign(a,b): a = b
> 
> after calling "assign(a, b)" is "a" modified?
> (where the type of "a" and "b" is one of { Int, String, List })
> 
> 
> simple python example:
>   a = 0
>   assign(a, 1)
>   print a
>   #=> a is still 0, so answer is "N"
> 
> I S L (where I=Int S=String L=List)
> ------------------------
> N N N Ruby
> N N N Python
> N N N Java
> N N N C++
> Y Y Y C++ ref
> Y Y Y merd
> Y Y _ Perl ref
> ------------------------
> (Y => Yes, N => No)
> 
> 
> Given:
>   def add(a,b): a += b
> 
> after calling "add(a, b)" is "a" modified?
> 
> I S L (where I=Int S=String L=List)
> ------------------------
> N N N Ruby (+=)
> _ Y Y Ruby (<<)
> N N Y Python (+=)
> N N Y Java (+= += addAll)
> N N N C++
> Y Y Y C++ ref
> Y Y Y merd
> Y Y _ Perl ref
> ------------------------
> 
> 
> Ruby
>   pass-by-ref except for numbers
>   "a = b"  "a" is a new object
>   "a += b" "a" is a new object
>   "a << b" modify the existing object "a" (!not for numbers)
> 
> Python
>   pass-by-ref except for numbers and strings
>   "a = b"  "a" is a new object
>   "a += b" modify the existing object "a" (implies a+=b different from
> a=a+b)
> 
> Java
>   pass-by-ref except for numbers
>   "a = b"  "a" is a new object
>   "a += b" "a" is a new object (only works numbers and strings)
> 
> C++
>   pass-by-value (depth 1), with pass-by-ref possible (using "&")
>   "a = b"  modify the existing object "a"
>   "a += b" modify the existing object "a" (was not available on
vector's)
> 
> merd
>   pass-by-value (deep) unless as a modified parameter where
pass-by-ref is
> used
>   "a = b"  modify the existing object "a"
>   "a += b" modify the existing object "a"
> 
> 
> Perl
>   pass-by-value (depth 1), with pass-by-ref vaguely possible
>   "a = b"  modify the existing object "a" (but "a" can't be shared
(?))
>   "a += b" modify the existing object "a" (but "a" can't be shared
(?))
>   => no implicit reference so this is not a good test