Swift "Array" memory allocation, plus toggle display mirroring - arrays

NOTE: See amended post below re: Hardware mirroring
I have written two Swift functions that toggle the display mirroring in OSX. Both work; the difference between them is just syntax when dealing with pointers. For the convenience of those interested in learning how to toggle mirroring in Swift, I have included the text of the playground file below.
My question is about memory allocation. Here is the section of interest:
toggleMirroringUgly
// allocate space for array
let displayListPtr = displayIDListPtr.alloc(Int(displayCount)) //see typealias above
// fill the list
postError(CGGetActiveDisplayList(displayCount, displayListPtr, &activeCount))
toggleMirroring
// allocate space for list of displays
var displayIDList = Array<CGDirectDisplayID>(count: Int(displayCount), repeatedValue: kCGNullDirectDisplay)
// fill the list
postError(CGGetActiveDisplayList(displayCount, &displayIDList, &activeCount))
CGGetActiveDisplayList is a low-level function call that relies on data being arranged in consecutive memory locations. I am reasonably confident that “alloc” from the ugly version is contiguous. Empirically, it seems that the “Array(…)” call is also contiguous, but can I rely on that always being true (e.g., if the number of displays grows)? Is this assumption about the Swift array initializer poor form?
Here’s all the code; apologies for formatting issues. Note that only one of the two functions should be called; otherwise, you’ll end up where you started.
//: Playground - noun: a place where people can play
import Cocoa
// apparently not defined in Swift version of SDK 10.11 (XCode 7.3.1), so add manually
let kCGNullDirectDisplay = CGDirectDisplayID(0)
let kCGDirectMainDisplay = CGMainDisplayID() // not used here, just for the record
let maxDisplays:UInt32 = 20 // not used
var onlineCount:UInt32 = 0 // not used
func postError(error : CGError){
if error != CGError.Success {
print("got an error")
}
}
// this toggles all active displays, online or not
func toggleMirroring(){
var displayCount:UInt32 = 0
var activeCount:UInt32 = 0
//var onlineCount:UInt32 = 0 //not used
//get count of active displays (by passing nil to CGGetActiveDisplayList
postError(CGGetActiveDisplayList(0, nil, &displayCount))
if displayCount < 2 { return } // no point in any mirroring functions
//***
// allocate space for list of displays
var displayIDList = Array<CGDirectDisplayID>(count: Int(displayCount), repeatedValue: kCGNullDirectDisplay)
// fill the list
postError(CGGetActiveDisplayList(displayCount, &displayIDList, &activeCount))
//***
// determine if mirroring is active
// hack to convert from boolean_t (aka UInt32) to swift's bool
let displaysMirrored = CGDisplayIsInMirrorSet(CGMainDisplayID()) != 0
// set master based on current mirroring state
// if mirroring, master = null, if not, master = main display
let master = (true == displaysMirrored) ? kCGNullDirectDisplay : CGMainDisplayID()
// start the configuration
var configRef:CGDisplayConfigRef = nil //swift 3 syntax
postError(CGBeginDisplayConfiguration(&configRef));
for i in 0..<Int(displayCount) {
let currentDisplay = CGDirectDisplayID(displayIDList[i])
if CGMainDisplayID() != currentDisplay {
CGConfigureDisplayMirrorOfDisplay(configRef, currentDisplay, master);
}
}
if (false){ // change to true in order to execute the toggle
postError(CGCompleteDisplayConfiguration (configRef,CGConfigureOption.Permanently))
}
// The first entry in the list of active displays is the main display. In case of mirroring, the first entry is the largest drawable display or, if all are the same size, the display with the greatest pixel depth.
// The "Permanently" option might not survive reboot when run from playground, but does when run in an application
}
func toggleMirroringUgly(){
// just to decrease eye strain
typealias displayIDListPtr = UnsafeMutablePointer<CGDirectDisplayID>
typealias configurationRefPtr = UnsafeMutablePointer<CGDisplayConfigRef>
//get count of active displays (by passing nil to CGGetActiveDisplayList
postError(CGGetActiveDisplayList(0, nil, &displayCount))
if displayCount < 2 { return } // no point in any mirroring functions
// ***
// allocate space for array
let displayListPtr = displayIDListPtr.alloc(Int(displayCount)) //see typealias above
// fill the list
postError(CGGetActiveDisplayList(displayCount, displayListPtr, &activeCount))
// ***
// determine if mirroring is active
// hack to convert from boolean_t (aka UInt32) to swift's bool
let displaysMirrored = CGDisplayIsInMirrorSet(CGMainDisplayID()) != 0
// set master based on current mirroring state
// if mirroring master = null, if not, master = main display
let master = (true == displaysMirrored) ? kCGNullDirectDisplay : CGMainDisplayID()
// make room for the configuration reference
let configRefPtr = configurationRefPtr.alloc(1) //see typealias above
// start the configuration
postError(CGBeginDisplayConfiguration (configRefPtr));
for i in 0..<displayCount {
let currentDisplay = CGDirectDisplayID(displayListPtr[Int(i)])
if CGMainDisplayID() != currentDisplay {
CGConfigureDisplayMirrorOfDisplay(configRefPtr[0], currentDisplay, master);
}
}
if (false){ //change to true in order to flip the mirroring
// make it happen
postError(CGCompleteDisplayConfiguration (configRefPtr[0],CGConfigureOption.Permanently));
}
// The first entry in the list of active displays is the main display. In case of mirroring, the first entry is the largest drawable display or, if all are the same size, the display with the greatest pixel depth.
// The "Permanently" option might not survive reboot when run from playground, but does when run in an application
}
toggleMirroring()

Arrays don't necessarily use contiguous storage. There is a ContiguousArray type which you can use if you are so inclined, but you'll still need to deal with the possible difference between your maximum size and the actual size returned after the final call to CGGetActiveDisplayList.
One way of cleaning this up might be to make a custom convenience initializer for Array:
extension Array {
init<Size: IntegerType>(
fillingBufferOfSize maxSize: Size,
#noescape fillBuffer: (buffer: UnsafeMutablePointer<Element>, count: inout Size) throws -> ()) rethrows
{
let maxSizeAsInt = Int(maxSize.toIntMax())
let buf = UnsafeMutablePointer<Element>.alloc(maxSizeAsInt)
defer { buf.dealloc(maxSizeAsInt) }
var actualCount: Size = 0
try fillBuffer(buffer: buf, count: &actualCount)
self.init(UnsafeBufferPointer(start: buf, count: Int(actualCount.toIntMax())))
}
}
Then you can use Array(fillingBufferOfSize: ...):
var maxActive: UInt32 = 0
CGGetActiveDisplayList(0, nil, &maxActive)
let displays = Array(fillingBufferOfSize: maxActive) { (buffer, count) in
CGGetActiveDisplayList(maxActive, buffer, &count)
}

I upgraded my computer with a new video card and NVIDIA drivers and discovered my code above no longer works fully - turns mirroring on but not off. Apparently, there's an option for drivers to use hardware or software mirroring, and that changes the coding. I post below a revised version.
It has only been tested on my system (10.12.2) and card (GTX 980Ti), but I think the logic should accommodate software mirroring and fairly recent OS versions as well. If you have more than 2 displays, you can probably modify it, with heroic effort, to mirror arbitrary combinations. My code will just mirror whatever is considered the main display (or the lowest rez one, in software mirroring) on all the others.
Although jbandes' note re: ContiguousArray was informative, it does not work in this case - see the comments in the code. This code assumes that the allocated array of UInt32s will be contiguous. (Too much work to get fancy with malloc and casting, but this is not production ready.)
Good luck to the 2 people who might be interested!
//: Playground - noun: a place where people can play
import Cocoa
import Foundation
func postError(_ error : CGError){
if error != CGError.success {
print("got an error")
}
}
func disableHardwareMirroring(){
// designed for hardware mirroring with > 1 display
// should be no penalty for running with only 1 display, using either hardware or software mirroring drivers
// but not tested
// start the configuration
var configRef:CGDisplayConfigRef? = nil
postError(CGBeginDisplayConfiguration(&configRef))
// only interested in the main display
// kCGNullDirectDisplay parameter disables hardware mirroring
CGConfigureDisplayMirrorOfDisplay(configRef, CGMainDisplayID(), kCGNullDirectDisplay)
// may not be permanent between boots using Playgroud, but is in an application
postError(CGCompleteDisplayConfiguration (configRef,CGConfigureOption.permanently))
}
func toggleMirroring(){
var displayCount:UInt32 = 0
var activeCount:UInt32 = 0 //used as a parameter, but value is ignored
//var onlineCount:UInt32 = 0 //not used
//get count of active displays (by passing nil to CGGetActiveDisplayList
postError(CGGetActiveDisplayList(0, nil, &displayCount))
if displayCount == 1 {
// either it's hardware mirroring or who cares?
disableHardwareMirroring()
return
}
// allocate space for list of displays
// tried to use ContiguousArray, but CGGetActiveDisplayList requires Array<CGDirectDisplayID> parameter
// ContiguousArrays cannot be typecast to Arrays (at least not easily)
var displayIDList = Array<CGDirectDisplayID>(repeating: kCGNullDirectDisplay, count: Int(displayCount))
// fill the list
postError(CGGetActiveDisplayList(displayCount, &(displayIDList), &activeCount))
// determine if mirroring is active (only relevant for software mirroring)
// hack to convert from boolean_t (aka UInt32) to swift's bool
let displaysMirrored = CGDisplayIsInMirrorSet(CGMainDisplayID()) != 0
// set master based on current mirroring state
// if mirroring, master = null, if not, master = main display
let master = (true == displaysMirrored) ? kCGNullDirectDisplay : CGMainDisplayID()
// start the configuration
var configRef:CGDisplayConfigRef? = nil
postError(CGBeginDisplayConfiguration(&configRef))
for i in 0..<Int(displayCount) {
let currentDisplay = CGDirectDisplayID(displayIDList[i])
if CGMainDisplayID() != currentDisplay {
CGConfigureDisplayMirrorOfDisplay(configRef, currentDisplay, master)
}
}
postError(CGCompleteDisplayConfiguration (configRef,CGConfigureOption.permanently))
// The first entry in the list of active displays is the main display. In case of mirroring, the first entry is the largest drawable display or, if all are the same size, the display with the greatest pixel depth.
// The "Permanently" option might not survive reboot when run from playground, but does when run in an application
}
if (false) { // change to true to run the code, false to edit
toggleMirroring()
}

Related

QS5026 - The variable cannot be reassigned here

I'm following tutorial from the official Microsoft learning page (https://learn.microsoft.com/en-us/azure/quantum/tutorial-qdk-explore-entanglement?pivots=ide-azure-portal) about quantum entanglement.
Basically, I copied an example posted there and I am getting error:
QS5026 The variable "numOnesQ1" cannot be reassigned here. In conditional blocks that depend on a measurement result, the target QuantinuumProcessor only supports reassigning variables that were declared within the block.
I understand what it says but it's just a copy from the official Microsoft tutorial. Am I missing something simple like imports, wrong settings? If not, how can I in other way set variables declared outside conditional blocks that depend on a measurement result?
Here is my code:
namespace Quantum.QuantumDream {
open Microsoft.Quantum.Canon;
open Microsoft.Quantum.Intrinsic;
operation GetRandomResult() : Result {
use q = Qubit();
H(q);
return M(q);
}
#EntryPoint()
operation TestBellState(count : Int, initial : Result) : (Int, Int, Int, Int) {
mutable numOnesQ1 = 0;
mutable numOnesQ2 = 0;
// allocate the qubits
use (q1, q2) = (Qubit(), Qubit());
for test in 1..count {
SetQubitState(initial, q1);
SetQubitState(Zero, q2);
// measure each qubit
let resultQ1 = M(q1);
let resultQ2 = M(q2);
// Count the number of 'Ones':
if resultQ1 == One {
set numOnesQ1 += 1;
}
if resultQ2 == One {
set numOnesQ2 += 1;
}
}
// reset the qubits
SetQubitState(Zero, q1);
SetQubitState(Zero, q2);
// Return number of |0> states, number of |1> states
Message("q1:Zero, One q2:Zero, One");
return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
}
operation SetQubitState(desired : Result, target : Qubit) : Unit {
if desired != M(target) {
X(target);
}
}
}
This tutorial code is only supposed to run on a local simulator (using %simulate magic commands in a Jupyter Notebook). From the error message, it looks like you've tried to run it on one of Quantinuum targets, which have some limitations on the kinds of things you can do in the code. To run equivalent code on Quantinuum, you'd need to define an operation for just the body of the loop (preparing a state and measuring it) and run it as a job - the cloud targets will take care of the loop themselves, running your code multiple times and returning to you a histogram of the results. For an example, you can see the QRNG sample in the samples gallery in Azure Portal.

Map modify array of objects in Swift 2.2 (3.0)

I want to be able to modify my array of objects using map in Swift of the fly, without looping through each element.
Before here were able to do something like this (Described in more details here:
gnomes = gnomes.map { (var gnome: Gnome) -> Gnome in
gnome.age = 140
return gnome
}
Thanks for Erica Sadun and others, new proposals have gone through and we're now getting rid of C-style loops and using var inside the loop.
In my case I'm first getting a warning to remove the var in then an error my gnome is a constant (naturally)
My question is : How do we alter arrays inside a map or the new styled loops for that matter to be fully prepared for Swift 3.0?
If you want to keep that syntax, just use a (mutable) temporary variable
gnomes = gnomes.map { (gnome: Gnome) -> Gnome in
var mutableGnome = gnome
mutableGnome.age = 140
return mutableGnome
}
(Below follows the case where Gnome is a reference type; a class -- since you haven't showed us how you've defined Gnome. For the case where Gnome as value type (a struct), see #vadian:s answer)
The removal of var will not effect using .map to mutate mutable members of an array of reference type objects. I.e., you could simply use your old approach (omitting however, the var in the .map closure signature).
class Gnome {
var age = 42
}
var gnomes = [Gnome(), Gnome(), Gnome()]
gnomes = gnomes.map {
$0.age = 150
return $0
}
/* result */
gnomes.forEach { print($0.age) } // 3x 150
However, in case you just want to modify your original array rather than assigning the result of .map to a new array, .forEach might be a more appropriate choice than .map.
gnomes.forEach { $0.age = 140 }
/* result */
gnomes.forEach { print($0.age) } // 3x 140
Given:
struct Gnome {
var age: Int = 0
}
var gnomes = Array(count: 5, repeatedValue: Gnome())
... there are two decent options. The first is as #vadian put it:
gnomes = gnomes.map{
var gnome = $0
gnome.age = 70
return gnome
}
Whilst the second keeps control over "ageing" private and simplifies mapping at the point of call:
struct Gnome {
private(set) var age: Int = 0
func aged(age: Int) -> Gnome {
var gnome = self
gnome.age = age
// any other ageing related changes
return gnome
}
}
gnomes = gnomes.map{ $0.aged(140) }
Of course, reference types still have their place in programming, which may well be a better fit in this case. The friction we are experiencing here suggests that we are trying to treat these structures as if they were objects. If that is the behaviour you need, then you should consider implementing Gnome as a class.

Swift, Generating Array Variables of a Numbered List

I'm making a simple game in swift and xcode and I ran into this problem that I can't figure out. Because I have so many levels, the code locks up indexing and slows down the whole program. I get a color wheel spinning for a few minutes but it never crashes. Just takes several minutes everytime I type in a few characters. Strange, but xcode has always had it's bugs right?
Each Button ("button1, button2..." below) gets a single number from "level1:Array". It's like a code that fills in the button's value for the game. There are only 4 buttons, but the numbers should be able to change as they each have their own variables.
I want to generate this for every level. I should be able to generate something like "button1 = level#[0]" where # is replaced by "userLevel". Changing to a string and doing something like "button1 = ("level(userLevel)") as! Array... doesn't seem to work. Look below and use my terminology when giving examples if you can. Thanks!
Here's the example:
let level1:Array = [9,7,4,1] // current puzzle, to go directly into button vars below (button1,button2,ect)
var userLevel = 1 // current user's level
if userLevel == 1 {
print("making Level 1, setting buttons to value from array")
button1 = level1[0]
button2 = level1[1]
button3 = level1[2]
button4 = level1[3]
}
Now, since level# is repeated so often (for each level as the number progresses) I would rather just make it something like this:
//this doesn't work in swift, but what else can I do?
if userLevel > 0 {
button1 = level\(userLevel)[0]
button2 = level\(userLevel)[1]
button3 = level\(userLevel)[2]
button4 = level\(userLevel)[3]
}
Is there an easy way to do this? Thanks!
-GG
Try using a for-in loop. Create an array of the buttons, and then
var index = 0
for button in buttons {
button = level1[index]
index++
}
EDIT since you want both the user level and the level number to increase, I suggest you define the levels like this. (Make sure that the number of buttons is equal to the number of userLevels, otherwise you will have problems)
var array = [1,2,3]
let levels = [1:[1,3,8],2:[3,6,4],3:[4,2,5]]
var index = 0
if array.count == levels.count {
for number in array {
array[index] = levels[index+1]![index]//The second index can be 0 if you want
index++
}
}
//array = [1,6,5]
// You could create a second index to match the number of levels within the main user level.
In this case, assume array to be your array of buttons
EDIT 2 :)
I've made a function that will allow you to assign all the levels to your array for a specific userLevel, since I see that is what you want
let levels = [1:[1,3,8],2:[3,6,4],3:[4,2,5]]
func assignValuesToArray(levelNo:Int) -> [Int] {
var array: [Int] = []
if (levelNo > 0) && (levelNo <= levels.count) {
for (level,levelArray) in levels {
if level == levelNo {
for value in levelArray {
array.append(value)
}
}
}
return array
} else {
print("This Level number does not exist")
return []
}
}
var finalArray = assignValuesToArray(2)
print(finalArray) // Returns [3,6,4]
As you can see from this example, you will return your array of buttons from the function, and you can assign the returned array values to whatever you like.

Having array problems in Swift

I am learning how to build apps and working with Swift for this project.
I had a buddy help me pull data in from a website and it looks like he created classes with variables and mapped them to certain extensions (IE "Username") so when I call the variable data such as profile I would call it. The below uses luck_30 able to store "Stats.luck_30"
luck_30.text = profile.luck_30
So inside one of my variables that is in this "Profile" class is setup into an array. I can pull the array out of the class, but I can't seem to do for while statement replacing the [#] with a variable from the for command.
func aliveWorkers(profile: Profile) -> NSNumber{
var myworkers : Array = profile.workers!
//this test works and returns the proper value
var testworker: NSNumber = myworkers[0].alive!
println("The satus of the test worker is " + testworker.description)
/* This code is giving error "Could not find member alive" it does not ifor var
for ifor in myworkers{
var thisworker: NSNumber = myworkers[ifor].alive! as NSNumber
}
*/
return 42
}
Your variable ifor is not a counter, it is an actual object. You could do something like this:
for worker in myWorkers {
let workerIsAlive = worker.alive!
}
Alternatively, if you need the index,
for i in 0 ..< myWorkers.count {
let worker = myWorkers[i]
let workerIsAlive = worker.alive!
}
If you need both:
for (i, worker) in enumerate(myWorkers) {
let workerIsAlive = worker.alive!
}
And as a matter of style, I would stay away from NSNumber and use Int or Bool or whatever the data actually is. Also, it looks like the alive variable should not be optional, as you're unwrapping it everywhere. To avoid "mysterious" crashes later, you may want to think about making it a non-optional type.
when using a for in loop, your loop variable isn't an index, its the objects you're looping through. so..
func aliveWorkers() {
var myworkers = [1, 2, 3]
//this test works and returns the proper value
let testworker = myworkers[0]
print("The satus of the test worker is \(testworker)")
for ifor in myworkers {
print(ifor)
}
}
Notice a few things... you don't need to use + to concatenate those strings. you can just use string interpolation. \(variable) inserts the value of variable in the string.
Try to use let instead of var when you don't change the variable. You don't need to explicitly define type on variables either.

Instantiation attempted on a non-constructor

I'm trying to make a bomb catching game (I'm actually using the code from the AS3 Classroom in a Book on arrays). As soon as I changed the word fruit to bomb in the code I got error 1007. With the exception of changing basket_mc to eod_mc and fruit to bomb (I used command-F and replaced with case sensitive on) I haven't changed much. It worked with eod_mc, but doesn't with bomb.
var bombArray:Array = new Array(bomb);
var bombsOnstage:Array = new Array();
var bombsCollected:int = 0;
var bombsLost:int = 0;
for (var i:int = 0; i<20; i++) {
var pickBomb = bombArray[int(Math.random() * bombArray.length)];
var bomb:MovieClip = new pickBomb();
addChild(bomb);
bomb.x = Math.random() * stage.stageWidth-bomb.width;// bomb.width is subtracted from the random x position to elimate the slight possibility that a clip will be placed offstage on the right.
bomb.y = Math.random() * -500;
bomb.speed = Math.random() * 15 + 5;
bombsOnstage.push(bomb);
}
eod_mc.addEventListener(MouseEvent.MOUSE_DOWN, dragEod);
stage.addEventListener(MouseEvent.MOUSE_UP, dragStop);
function dragEod(e:Event):void {
eod_mc.startDrag();
}
function dragStop(e:Event):void {
eod_mc.stopDrag();
}
stage.addEventListener(Event.ENTER_FRAME, catchBomb);
function catchBomb(e:Event):void {
for (var i:int = bombsOnstage.length-1; i > -1; i--) {
var currentBomb:MovieClip = bombsOnstage[i];
currentBomb.y += currentBomb.speed;
if (currentBomb.y > stage.stageHeight - currentBomb.height) {
currentBomb.y = 0 - currentBomb.height;
bombsLost++;
field2_txt.text = "Total Bombs Detonated: " + bombsLost;
}
if (currentBomb.hitTestObject(eod_mc)) {
bombsCollected++;
removeChild(currentBomb);
bombsOnstage.splice(i,1);
field1_txt.text = "Total Bombs Caught: " + bombsCollected;
if (bombsCollected >= 20) {
eod_mc.gotoAndStop(20);
} else if (bombsCollected > 15) {
eod_mc.gotoAndStop(15);
} else if (bombsCollected>10) {
eod_mc.gotoAndStop(10);
} else if (bombsCollected>5) {
eod_mc.gotoAndStop(5);
}
}
}
if (bombsOnstage.length <= 0) {
field1_txt.text = "You Win! You have defused the bombs.";
field2_txt.text = "";
stage.removeEventListener(Event.ENTER_FRAME, catchBomb);
}
if (bombsLost >= 20) {
field1_txt.text = "Sorry you lose. You have lost your foot!";
field2_txt.text = "";
stage.removeEventListener(Event.ENTER_FRAME, catchBomb);
for (var j:int = bombsOnstage.length-1; j > -1; j--) {
currentBomb = bombsOnstage[j];
removeChild(currentBomb);
bombsOnstage.splice(j,1);
}
}
}
Maybe to avoid making your programming life more twisted than it is now...
There are objects and classes in programming, a class is a description of a set of objects, say "table" (or, as it's better to differ in names for classes and variables, "Table", first letter capitalized) is a name of a class. An instance or an object is a structure that belongs to one or more classes, with Object being the topmost, as everything in programming is either an object or a "simple variable", that is, a number, a true/false, a string of characters (these are object types in AS3 too, though, Number, Boolean, String, but these generally not need to be instantiated via new) or probably some other simple type I don't remember right now.
Classes have properties and methods. A property is something that can be requested off any object of the class, say "height" for tables. Properties can be of any type, including nested objects, depending on what your base class is. Say stage in AS3 is a property of any DisplayObject which is used to get the only Stage object there is at runtime[1]. Methods are what any object of a class can be told to do. Say, bombs fall, explode, MovieClips can be told to stop(), etc. You write class code keeping in mind that all of the objects of this class will have to behave exactly like you've written, but since they can differ in properties, you can give them conditional behavior. For example, if a bomb has already exploded, it cannot blow up once more.
A variable, whether a property or a standalone var (if you declare one in a function) is a reference to an object of a given type. Say var i:int refers to some kind of an integer. Simple type vars are containers instead, that is, i=2; will place a 2 in the referred integer, and i=j; will copy the value from j into i, while var theStage:Stage=this.stage will instead create a reference to an existing object, and if that object will change, the reference will give you the changed object instead of its previous state. An array is a collection of variables, reachable by indexes, in AS3 they don't have to be of one type, and a Vector is a typed array.
Next, the lifetime of objects. An object only lives while there's an active reference to it, whether in a property of another alive object, or in a visible variable, or in an event listener (AS3 specific). An object is created via new ClassName(<parameters>), lives while you can reach it somehow, and is destroyed once you have no active links to it and Flash player decides to run garbage collector. Prior to this programmers had to deallocate objects themselves, a rudiment can be seen at BitmapData.dispose(). So, in order to avoid Flash player to run out of free memory, take full control over creation and destruction of links. You don't need to care for simple vars, they are being cared for by Flash player.
A lot of basic functions for interactions has already been implemented in AS3, look for them and examples of how they work in Adobe's manual, navigate through packages in the lower left, most of the interactive stuff is in flash.display package, refer to other packages as necessary.
Hope this will bring you some insight into programming basics.
[1]: There is one stage unless you're doing a load of an SWF, then there could be more, one Stage per one SWF.

Resources