Skip to content

Viper: problem updating nonlocal variables #8086

@peterhinch

Description

@peterhinch

I am trying to write a Viper function which retains state between calls, preferably using a closure. The following produces an unexpected result (all testing on a Pyboard 1.1 running V1.17):

def foo():
    x : int = 0
    @micropython.viper
    def inner() -> int:
        nonlocal x
        q : int = int(x)
        q += 1
        x = q  # x never increments
        return int(x)
    return inner

bar = foo()
bar()  # 0
bar()  # 0

Oddly similar code using a global works:

x = 0
@micropython.viper
def foo() -> int:
    global x
    q : int = int(x)
    q += 1
    x = q
    return int(x)

foo()  # 1
foo()  # 2
foo()  # 3

Attempting this with a class produces a type error

class Foo:
    def __init__(self):
        self.x : int = 0

    @micropython.viper
    def bar(self) -> int:
        q : int = int(self.x)
        self.x += q  # ViperTypeError: can't do binary op between 'object' and 'int'
        return int(self.x)

foo = Foo()

To date my "best" solution is to use a closure with an integer array to contain state:

from array import array
def foo():
    x = array('i', (0,))
    @micropython.viper
    def inner() -> int:
        i = ptr32(x)
        r = i[0]
        i[0] += 1
        return r
    return inner

bar = foo()
bar()  # 0
bar()  # 1
bar()  # 2

It would be good if nonlocal worked as expected and if there were a solution to the problem of accessing integer bound variables.

Incidentally the speedup using Viper in my actual application is phenomenal :)

Metadata

Metadata

Assignees

No one assigned

    Labels

    py-coreRelates to py/ directory in source

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      pFad - Phonifier reborn

      Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

      Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


      Alternative Proxies:

      Alternative Proxy

      pFad Proxy

      pFad v3 Proxy

      pFad v4 Proxy