...
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 |
---|
|
# 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") |