2
Variables
Bartłomiej Przemysław Pluta edited this page 2020-04-01 21:08:50 +02:00

SMNP language's variable mechanism allows you to store some data in memory which could be used in the later stages of code. Even though SMNP language does have a data types, declaring new variables doesn't require you to explicitly put a type before declaration as in the case of most popular languages, like Java etc. Hence, it is not possible to declare variable without initialization. You always have to initialize your variable when you are declaring it. Initialization can be done with assignment operator (=). The right-hand side should be expression (value, function call or even other variable) but the left-hand side can be only variable identifier.

myVar;        # It is not a declaration
myVar = 2;    # It is a declaration. From now you are able to use variable myVar
3 = 2;        # error! 
var2 = foo(); # Correct
var2 = myVar; # Also correct

Variables are nothing but references to objects (values) and they don't have any type. In other words you are able to assign value of different type to already initialized variable.

myVar = 2;
println(myVar);              # 2
myVar = "Hello, world!";
println(myVar);              # Hello, world!

Because assignment is an expression which returns a value being assigned it is possible to perform multiple initialization.

a = b = c = 10;             # It is like a = (b = (c = 10))
println(a == b and b == c); # true

SMNP language doesn't have any equivalent of Python's del instructions, so you aren't able to delete already created variable. The only way is using scopes.

Scopes

Scopes are strongly related to blocks. Block is a set of statements and expressions bounded on both sides with { and respectively }. Even though it is not required and you can write whole code in one line, it is highly recommend to use any kind of indentations for each block, including blocks nested inside.

println("I'm outside any block");

{
   println("I'm in the first-level block");
   {
      println("I'm in second-level block");
   }

   println("Greetings from first-level block again");
}
    

In context of variable mechanism it is important to know that variables declared inside block are available to each instructions following declaration in the same block and for each nested block placed after variable declaration.

var1 = "top-level";
{
    var2 = "first-level";
    println(var1);               # "top-level"
    println(var3);               # error!
    {
        var3 = "second-level";
        println(var1);           # "top-level"
        println(var2);           # "first-level"
        println(var3);           # "second-level"
    }
    println(var2);               # "first-level"
    println(var3);               # error!
}

println(var2);                   # error!
println(var1);                   # "top-level"

Identifiers

It is also important to know what is identifier in context of SMNP language. Identifier is a string that contains only letters (both lowercase and uppercase), numbers and _ character. Identifier must not start with number and must not be any of reserved words (keywords).

List of keywords:

  • and
  • or
  • not
  • function
  • return
  • extend
  • import
  • throw
  • from
  • with
  • if
  • else
  • as
# Valid identifiers
i
var
myVar
my_var
var20
x_YZ
_vArIaBlE
_if
_return
returns

# Invalid identifiers
19i
foo[
bar@
return
!@#%$
if
as

Immutability

It's a good place to say that all values in SMNP code are immutable. That means you are not able to e.g. change pitch of existing note, change arbitrary letter of string, put object to list and so on.

You are able to produce note basing on given one with new pitch or join two or more lists but these operations produces new objects and leave values unmodified.

a = [1, 2];
b = [3, 4];
c = a + b;
println(a == [1, 2]);        # true
println(b == [3, 4]);        # true
println(c == [1, 2, 3, 4]);  # true

a = @c;
b = a.withDuration(2);
println(a == @c);            # true
println(b == @c:2);          # true