Why make a variable immutable and create a new entry when redefining a variable? - immutability

In SML,if I am correct, variables are immutable by default. So when we try to redefine a variable
val y = 100;
val y = 0.6;
y
the environment will have two entries for y. The new entry hides the original entry.
Isn't it the same effect as if we modified the value in the original entry from 100 to 0.6?
If the original entry was created outside a function call, and the new entry was created in a function call, then when the function call returns, we can access the original entry.
If both entries were created in the same "scope", like the example above, is the original entry not accessible?
Effectively, isn't it the same in SML as in an imperative language such as C? What is the point of making a variable immutable in SML and creating a new entry when redefining a variable?
Thanks.

Isn't it the same effect as if we modified the value in the original entry from 100 to 0.6
No. Consider code that references the previous environment through use of a closure like
val x = 7
val f = fn () => x
val x = 8
val _ = print (Int.toString (f ())) (* prints 7 *)
If the original entry was created outside a function call, and the new entry was created in a function call, then when the function call returns, we can access the original entry.
Sure, its statically scoped.
If both entries were created in the same "scope", like the example above, is the original entry not accessible?
It is still accessible, just not by that identifier. Consider the example above.
What is the point of making a variable immutable in SML and creating a new entry when redefining a variable?
One use of this is changing the type of a variable while still using the same identifier (which you do in the example you post!). Take for instance (in C):
int i = 7;
i = 7.0;
Here, i will still be of type int. Cf., in SML:
val i : int = 7
val i : real = 7.0
I've added type annotations for illustration, but even without this has the same behaviour. After the second binding, i has type real.

To amend kopecs' answer:
What is the point of making a variable immutable in SML and creating a new entry when redefining a variable?
That is the wrong way to phrase the question. :) Immutability by default has many merits, but that would be off-topic.
The actual question is: Why does SML allow multiple bindings for the same variable in a single scope? Instead of making it an error?
And that's a fair question. There is no deep reason. It merely turns out to be convenient sometimes. For example, to avoid spurious identifier clashes when using open. Or to allow redefining previous definitions in an interactive session.

Related

What is the difference of immutable and mutable variables?

I have read almost every definition of immutable/mutable variables on the internet but as a beginner I just do not grasp it fully so I was wondering if someone could really explain it in layman terms.
Immutable variables (or objects) in any programming language is what I understand when you cannot change the value of that variable after it has been assigned a value. For example, I am using the Haskell programming language, and I write:
let x = 5
Since Haskell has immutable variables, x can never have any other value than 5. So if I after that line of code write:
x = 2
I have in fact not changed the value of x but made a new variable with the same name, which will now be the one that is referenced when I call x, so after both lines of code I can only reach an x with the value of 2.
But what is a mutable variable then, and what programming languages have it? This is where it gets foggy for me. Because when people say mutable variable, they are obviously referring to a variable or object which value you can indeed change after it has been assigned an initial value.
Does this mean that if you have a mutable variable you actually manipulate that place in the computers memory for that variable, and in case of immutable variable you cannot manipulate that place in the computers memory or what?
I don't know how to explain my question any further, as I said, I understand that mutable = can change value of variable after initial value assignment, immutable = cannot. I get the definition. But I don't understand what it actually means in terms of what is going on "behind the scenes". I guess I am looking for easy examples on actual mutable variables.
This has nothing to do with immutability
let x = 5
x = 2
This is reassignment and definitely not allowed in Haskell
First let's look at a regular let assignment
Prelude> let x = 5 in x
5
it :: Num a => a
You can bind x using let, and rebind a new x in a nested let – this effectively shadows the outer x
Prelude> let x = 5 in let x = 2 in x
2
it :: Num a => a
Remember a let is basically a lambda
Prelude> (\x -> x) 5
5
it :: Num a => a
And of course a lambda can return a lambda; illustrates shadowing agian
Prelude> (\x -> (\x -> x)) 5 2
2
it :: Num a => a
I believe a shorthand answer to your question would be that a Mutable variable that holds a value that you would later want to be adjusted.
Depending on the language you're using is its method.
In Kotlin val and var are used to declare variables.
val is a constant while var is adjustable.
Mutable respectively immutable does not concern the variables but the values. Note: one also says the type is (im-)mutable.
For instance if the value is of an immutable type StudentCard, with fields ID and Name, then after creation the fields no longer can be changed. On a name change the student card must be reissued, a new StudentCard must be created.
A more elementary immutable type is String in java. Assigning the same value to two variables is no problem as one variable may not change the shared value. Sharing a mutable value could be dangerous.
A commont mutable type is the array in java and others. Sharing an array, say storing an array parameter in a field, risks that somewhere else the array content is changed inadvertently changing your field.

What does Location means in R6RS of scheme?

At first, I thought that set! assignment in scheme is more like assignment = in python other than in c/c++.
in python:
>>> x = 1
>>> id(x)
15855960
>>> x = 2
>>> id(x)
15855936 # different from above!
the second assignment means rebind variable/name to another value instead of overwrite original value in memory location of x.
But c/c++ is the latter case:
int x = 1;
cout << &x << endl; // 0x7ffe3e6adba4
x = 2;
cout << &x << endl; // 0x7ffe3e6adba4 (the same memory location!)
But in 1.3 section of R6RS:
Scheme allows identifiers to stand for locations containing
values. These identifiers are called variables. In many
cases, specifically when the location’s value is never modified
after its creation, it is useful to think of the variable
as standing for the value directly.
And in 1.8 Assignment section:
Scheme variables bound by definitions or let or lambda
expressions are not actually bound directly to the objects
specified in the respective bindings, but to locations
containing these objects. The contents of these locations
can subsequently be modified destructively via assignment.
So it seems in scheme assignment set! is just like what c/c++ assignment = does?
But then how to explain the following:
=> (define x 10)
=> x
10
=> (set! x "lonnnnnnnnnnnnng")
=> x
"lonnnnnnnnnnnnng"
At first x is a location to store an small integer. But later set! put a LONG string into that SMALL memory location? But the location have no enough memory space to do that I think?
Both the citations from the manual say the same thing: an identifier (e.g. a thing like x or y), is associated (“bound”) to a location (a memory cell, e.g. the cell at address 0x7ffe3e6adba4), that can hold different values (for instance an integer, a string etc.), and that the content of the location can be modified with a new value. That is:
Identifier -> Location -> Value
The value, depending from the combination language/compiler, can be either a direct value (or an “unboxed” values, as sometimes it is called, typically in case of values like integers or float), or a “boxed” value, that is a pointer to some memory area the contains the value (typically for complex values like cons cells, arrays, strings, etc.).
As I said, the key point is that the implementation is free to chose how to store values in location, for instance if use a uniform method of storing values according to their type, if optimize and allocate values with different strategies, etc. The only important thing is to strictly follow the specification of the language that requires the double map above. The crucial point here is that in languages like Lisp pointers are (and should remain) “invisible” to the user (the programmer).

Does an equivalent function in OCaml exist that works the same way as "set!" in Scheme?

I'm trying to make a function that defines a vector that varies based on the function's input, and set! works great for this in Scheme. Is there a functional equivalent for this in OCaml?
I agree with sepp2k that you should expand your question, and give more detailed examples.
Maybe what you need are references.
As a rough approximation, you can see them as variables to which you can assign:
let a = ref 5;;
!a;; (* This evaluates to 5 *)
a := 42;;
!a;; (* This evaluates to 42 *)
Here is a more detailed explanation from http://caml.inria.fr/pub/docs/u3-ocaml/ocaml-core.html:
The language we have described so far is purely functional. That is, several evaluations of the same expression will always produce the same answer. This prevents, for instance, the implementation of a counter whose interface is a single function next : unit -> int that increments the counter and returns its new value. Repeated invocation of this function should return a sequence of consecutive integers — a different answer each time.
Indeed, the counter needs to memorize its state in some particular location, with read/write accesses, but before all, some information must be shared between two calls to next. The solution is to use mutable storage and interact with the store by so-called side effects.
In OCaml, the counter could be defined as follows:
let new_count =
let r = ref 0 in
let next () = r := !r+1; !r in
next;;
Another, maybe more concrete, example of mutable storage is a bank account. In OCaml, record fields can be declared mutable, so that new values can be assigned to them later. Hence, a bank account could be a two-field record, its number, and its balance, where the balance is mutable.
type account = { number : int; mutable balance : float }
let retrieve account requested =
let s = min account.balance requested in
account.balance <- account.balance -. s; s;;
In fact, in OCaml, references are not primitive: they are special cases of mutable records. For instance, one could define:
type 'a ref = { mutable content : 'a }
let ref x = { content = x }
let deref r = r.content
let assign r x = r.content <- x; x
set! in Scheme assigns to a variable. You cannot assign to a variable in OCaml, at all. (So "variables" are not really "variable".) So there is no equivalent.
But OCaml is not a pure functional language. It has mutable data structures. The following things can be assigned to:
Array elements
String elements
Mutable fields of records
Mutable fields of objects
In these situations, the <- syntax is used for assignment.
The ref type mentioned by #jrouquie is a simple, built-in mutable record type that acts as a mutable container of one thing. OCaml also provides ! and := operators for working with refs.

Data structure for storing variables in an interpreted language

I am designing my own experimental scripting language for the purpose of embedding it in my bigger application.
Almost everything I wanted to do was programmed smoothly, but the "simple" act of storing variables in memory appeared to be the hardest part here. I don't know how to store them to allow all type checking, global variables and special flags on them. First look at a sample code:
a = 1
b = 2
someFunction()
print(a) --> This should read the global variable and print `1`
a = 3 --> Now `a` should become a local variable of this function
and the global `a` remain unchanged
x = 4 --> `x` should always be local of this function
end
I call the "locality" of variables their levels so variables in nested blocks have a higher level. In the above code, a and b are level 1 variables. Local variables of someFunction will have level 2. The first line of the function should read the global variable a (level 1) but the second line should create a variable again called a but with level 2 that shadows the global a from that point onwards. The third line should create the variable x with level 2. How to store and keep track of all these in memory?
What I tried so far:
Method 1: Storing maps of variable=>value in array of levels:
variables
{
level=1 //global variables
{
a => 1,
b => 2
},
level=2 //function variables
{
a => 3,
x => 4
}
}
But that will make variable look-up really slow since one has to search all the levels for a given variable.
Method 2: Storing the (variable, level) pairs as keys of a map:
variables
{
(a, 1) => 1, //global
(b, 1) => 2, //global
(a, 2) => 3, //function
(x, 2) => 3 //function
}
This has the same problem as before since we have to try the pair (variable, level) with all possible levels for a given variable.
What method should I use for optimal memory usage and fastest access time?
Additional notes:
I know about how variables are managed on stack and heap on other "real" languages, but I find it tricky to do this on an interpreted language. "This mustn't be how Lua and Python do that," I always think. Correct me if I'm wrong. I'm trying to store the variable in maps and internal C++ structures.
And finally, this is how I represent a variable. Do you think it's big and there can be more memory-efficient representations? (I've also tried to put the "Level" as a member here but it had the same problem as the other too.)
struct Member
{
uchar type; //0=num, 1=str, 2=function, 3=array, etc
uchar flags; //0x80 = read-only, 0x40 = write-only, etc
union {
long double value_num;
char* value_str;
int value_func;
//etc
};
};
An easy thing to do, similar to your array, is to maintain a stack of maps. Each map contains the bindings for that scope. To bind a variable, add it to the top map; to look up a variable, start at the top of the stack and stop when you reach a map that contains a binding for that variable. Search takes a little bit, but starting from the top/end you only have to search until you find it — in most cases, this search will not be very long.
You can also make the stack implicit by encapsulating this logic in an Environment class that has local bindings and an inherited environment used for resolving unknown variables. Need to go into a new scope? Create a new environment with the current environment as its base, use it, then discard it when the scope is finished. The root/global environment can just have a null inherited environment. This is what I would probably do.
Its worth noting that if, inside a function, you don't have access to any variables from the caller function, it lowers the number of levels you need to look at. For example:
variable a;
function one() {
variable b;
// in this function, we can see the global a, local b
two();
}
function two() {
// in this function, we can see the global a, local c
// we cannot see the local b of our caller
variable c;
while (true) {
variable d;
// here we can see local d, local c, global a
}
}
The idea being that function boundaries limit the visibility of variables, with the global scope being "special".
That being said, you can consider removing the specialness of global variables, but allowing the code to specify that they want access to non-local variables
variable a;
function one() {
global a; // or upvar #0 a;
variable b;
// in this function, we can see the global a, local b
two();
}
function two() {
// in this function, we can see the local c
// and the local b of our caller
// (since we specifically say we want access to "b" one level up)
upvar 1 b;
variable c;
}
It looks complicated at first, but it's really easy to understand once you get used to it (upvar is a construct from the Tcl programming language). What it allows you is access to variables in your caller's scope, but it avoids some of the costly lookup involved by requiring that you specify exactly where that variable comes from (with 1 being one level up the call stack, 2 being two levels up, and #0 being "special" in saying "the uppermost call stack, the global)

Modifying module level variables in an anonymous array in Ruby

I am in the midst of learning Ruby and thought I was clever with the following piece of code:
[#start,#end].map!{ |time| time += operation == :add ? amount : -(amount) }
where #start, #end are two module level variables, operation can be one of :add or :sub, and amount is an float amount to adjust both #start and #end by.
Granted it only saves me a line of code, but why doesn't this approach work, and how can I get something similar that does?
(My expected output is for #start/#end to be modified accordingly, however unit tests show that they stay at their original values.)
It's important in Ruby to remember the distinction between variables and the objects they hold. Simply setting a variable will never change the object referenced by that variable. When you do a += b, it's just shorthand for a = a + b. So you're assigning a new value to the variable a, not changing the object that used to be there or changing any other references to that object. So changing the variable time doesn't change #start.
In order to assign to an instance variable, you need to actually assign to that instance variable. Here's a way to do what you were looking for:
operation = :+
amount = 12
#start, #end = [#start, #end].map {|time| time.send(operation, amount)}
You'll notice that we're not faffing around with that :add and :sub business either — we can just pass the actual name of the message we want to send (I used + in this case, but it could be anything).
If you had a big, dynamically generated list of ivars you wanted to set, it's only a little bit more complicated. The only difference there is that need to get and set the ivars by name.
ivars = [:#start, :#end, :#something_else]
operation = :+
amount = 12
ivars.each {|ivar| instance_variable_set(ivar, instance_variable_get(ivar).send(operation, amount))}
The += operator changes the value of time but it returns the old value of time, therefore the right code is:
#start,#end = [#start,#end].map!{ |time| time + (operation == :add ? amount : -amount) }
EDIT
Updated the code to actually change #start and #end.
The addition operation in the block doesn't modify 'time', it returns a new value. So the elements in the array aren't modified, they're replaced.

Resources