Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

PlantUML Macro
object rpncalc2 {
	operands = []
	token = "+"
	operand = ...
}

object "1: hasOperand" as hasOperand1 {
	n = 2
}

rpncalc2 <-left- hasOperand1

Når hasOperand er kalt, så har vi både et rpncalc2-ark for programmet som helhet og et hasOperand-ark for funksjonen. Koden inni funksjon vil kunne referere til variabler i begge arkene. Så når verdien av uttrykket len(operands) >= n beregnes, så finner den verdien av operands i rpncalc2-arket og n i hasOperand-arket.

...

Pila i figuren angir at hasOperand-arket sjekkes først, og deretter rpncalc2-arket. Dersom vi hadde kalt parameteret til hasOperand for operands (uvisst av hvilken grunn ...), så ville vi ikke kunnet referere til operands på rpncalc2-arket, fordi den ville funnet operands i hasOperands-arket først.

Når hasOperand returnerer så fjernes hasOperand-arket og parametrene og de lokale variablene blir borte. Det er derfor det er nyttig å tenke på funksjonsark som Post-It-lapper, fordi de legges på og fjernes hele tiden.

Reglene for hvordan funksjonsark kommer på toppen av eksisterende ark er litt mer komplisert enn dette. Hvorfor er det f.eks. slik at hasOperand-arket refererer til rpncalc2-arket? Regelen er at funksjonsarket refererer til samme ark som funksjonen selv er definert i! rpncalc2-arket inneholder strengt tatt ikke bare variabler, men også funksjoner, evt. kan en se på funksjoner som variabler som har funksjoner som verdi. Figuren under viser i detalj hva som skjer når plus-funksjonen kalles og kaller hasOperands:

PlantUML Macro
object rpncalc2 {
	operands = []
	hasOperands(n)
	plus()
	token = "+"
	operand = ...
}

object "1: plus" as plus1 {
}

rpncalc2 <-left- plus
plus-funksjonen er akkurat kalt fra elif-grenen i while-løkka. plus-arket refererer til rpncalc2-arket, fordi plus-funksjonen selv er definert i rpncalc2-arket. Dermed kan koden i plus-funksjonen referere til variabler (og funksjoner) i rpncalc2-arket.
PlantUML Macro
object rpncalc2 {
	operands = []
	token = "+"
	operand = ...
}

object "1: plus" as plus1 {
}
object "1: hasOperand" as hasOperand1 {
	n = 2
}

rpncalc2 <-left- plus
rpncalc2 <-left- hasOperand1
plus-funksjonen har akkurat kalt hasOperands. Vi har nå to aktive funksjonsark, og merk hvordan begge refererer til rpncalc2-arket, fordi både plus- og hasOperands-funksjonene selv er definert der. Men selv om hasOperands-arket ble aktivert av plus-funksjonen, så refererer det ikke til plus-arket.

For ordens skyld, her nedenfor er hele koden: rpncalc2-koden. Kjør den gjerne og sjekk at den virker! Har vi plantet noen feil denne gangen?

Code Block
languagepython
# rpncalc2.py
operands = []

def isOperand(token):
    return token[0].isdigit()

def hasOperands(n):
    return len(operands) >= n

def plus():
    if hasOperands(2):
        operands.append(operands.pop() + operands.pop())
def minus():
    if hasOperands(2):
        operands.append(- (operands.pop() - operands.pop()))
while (True):
    print(operands)
    token = raw_input(" > ")
    if isOperand(token):
        operand = float(token)
        operands.append(operand)
    elif token == "exit":
        break
    elif token == "+":
        plus()
    elif token == "-":
        minus()
    else:
        print("Unsupported operator: " + token)
print("program exited")