Variable declaration and assignment as I understand it at the moment


#1

Let me know of anything I got wrong or important things to add to this:

In Skookum                   In C++                              Notes
----------------------------------------------------------------------------------------------------------------------------------------
!a : 8                       auto a = 8;                          The type is figured out implicitly by what's assigned to the variable
a := 8                       a = 8;                               Assigning a value without declaring a variable
!a : Integer!                int a;                               Explicitly set the type. "a" will have an initial value of zero (0)
!a : Integer!copy(8)         int a = 8;                           Normally <Type>!copy is not needed as implicit typing resolves it: !a : 8!
!a:4 !b := a>>Real           int a = 4; float b = (float) a;      Explicit type cast. Real>>Integer rounds, not floors
-----------------------------------------------------------------------------------------------------------------------------------------
!a:4 !b:Real!                int a=4; float b;
b:=a                         b=a; // error in sk                  ":=" copy the value, assert if 'a' and 'b' are different types
b:a                          N/A                                  ":" change the type of b to a, then copy the value
-----------------------------------------------------------------------------------------------------------------------------------------
@myBlueprintVar := 10        N/A (without extra code)             Set a variable declared in the BP associated with this script to 10
-----------------------------------------------------------------------------------------------------------------------------------------
myActor.@Var := 8            myActor->Var = 8;                    When accessing member variable of BP classes (assuming ‘myActor’ came 
                                                                  as a parameter). C++ vars that are not BP exposed are not visible.
-----------------------------------------------------------------------------------------------------------------------------------------
!myVec : Vector2!xy(2,3)     Vector2 myVec(2,3);                  class/struct variable declaration with initialization
myVec.@x := 3                myVec.x = 3.0f;                      Accessing member variable of struct/class. Type is implied as Real here
!myVar : Vector2{}           TArray<Vector2> myVar;               Declare an empty list of type Vector2
!myVar : {1,9}               TArray<int> myVar = {1, 9};          Declare a list using the implicit type of the list values
!myVar : Real{1,9}           TArray<float> myVar = {1.0f, 9.0f};  Declare a list using an explicit type, with 2 initial values

Great curated posts to learn about SkookumScript
#2

That is a good first determination of how things work in SkookumScript. The C++ examples would be more complicated with a heap memory based object rather than a simple Integer of course.

Here are some additional notes.

Notes on !a: 8

!a: 8 with more recent C++ is closer to auto a = 8; which also infers the type.

Notes on !a : Integer!

If you don’t initially bind a variable to a value it is set to nil with class type None. You can always bind a variable to a new class type later - the parser will keep track and know its new type from that point on.

!a           // bound to nil/None
a: Integer!  // rebound to 0/Integer

// It is often easier to just use a literal than a default
// constructor if a class has literals as an option
a: 0  // Simpler than a: Integer!

Notes on !a: Integer!copy(8)

Since Integer!copy(8) is a common pattern, it also has some syntactical sugar shorthand in SkookumScript with what is called an instantiation expression:

  • 8!copy The Integer class is inferred from the type of 8.
  • 8! The !copy() is inferred by default since copy constructors are so common. So ! following an expression will make a copy of the object.

So the example can be more simply written a: 8! though in practice there is no point in making a copy of a literal since evaluating a literal always makes a new object in the first place. a: num! would make a copy of num and bind it to a.

When SkookumScript encounters the pattern obj!name:

  • first it looks to see if there is a constructor ObjClass!name() and if so calls ObjClass!name(obj)
  • if no such constructor exists, it looks for a method name() then it assumes you want to make a copy of the original object and then call the found method on it: ObjClass!copy(obj).name()
!a
!num: 42
// These are all equivalent:
a: Integer!copy(num)
a: num!copy
a: num!

So for example, str.uppercase will convert the original string object to uppercase whereas str!uppercase will first make a copy of the string object and then uppercase that object String!copy(str).uppercase. If there was a constructor with the name String!uppercase() it would be called instead String!uppercase(str). In both cases, it is much more handy to just use str.uppercase.

!a
!str: "hello"
// These are all equivalent:
a: String!copy(str).uppercase()
a: str!copy.uppercase
a: str!uppercase

The general idea behind the exclamation ! symbol in SkookumScript is make something new.

Notes on Type Conversion >>

Type conversion can be inferred if the desired type is known to the SkookumScript parser.

!a: 4
// min() takes a Real so full >>Real is not necessary
// Basically means "do whatever conversion that makes sense".
!b : 2.0.min(a>>)

Here are some more notes on conversions.

Note that this are converting >> an object from one class type to another, not casting <> from one type to another.

// Say you have an object that could be of several possible types
// a is type <Integer|String>
!a: test? [4] else ["hello"]
if a.class = String
  [
  a.uppercase          // Error: could be an Integer or a String
  a<>String.uppercase  // Tell the compiler you know it is a String

  // Cast type can also be inferred if the parser knows the desired type
  "hey" + a<>  // Same as "hey" + a<>String
  ]

Notes on second section

!a: 4 !b: 0.0
b := a   // Type error: Integer is not a Real
b := a>> // Tell parser explicitly to convert `a` and copy to the contents of `b`

// discard original 0.0 object and have memory address of `b` point to same object
// (and memory) as `a`. So now `a` and `b` refer to the exact same Integer 4 object.
b: a 

// The somewhat equivalent C++ would be something like this:
// (not that this would be valid and ignoring some type issues)
a.increment_reference();  // increment reference count
b.decrement_reference();  // decrement reference count
&b = &a;                  // copy address of `a` to `b`

Notes on third section: accessing values

Not sure what you mean by “only” here.
If the BP class script class equivalent has variables defined in SkookumScript, you can also access them in scripts.
Are there other variables that you expect to access in some way and cannot?

Notes on fifth section: initializing classes

Looks all good. Only extra note is that the commas are optional - you can just use whitespace. SkookumScript style convention is to use whitespace though use whatever you find most readable in a given situation.


Thanks for diving in! :madsci:

All of this will eventually be more fully detailed in the online docs which we are expanding right now.

Until then, keep on pestering us on the forum and we will fill in any blanks and try to give additional clarity.