# Is there any way I can call an instance of a function repeatedly with the function retaining internally the last state of the GPIO pin

**URL:** <https://discourse.julialang.org/t/is-there-any-way-i-can-call-an-instance-of-a-function-repeatedly-with-the-function-retaining-internally-the-last-state-of-the-gpio-pin/58748>\
**Category:** Internals & Design\
**Tags:** gpio, raspberry-pi\
**Created:** [April 7, 2021, 12:09pm UTC](https://discourse.julialang.org/t/is-there-any-way-i-can-call-an-instance-of-a-function-repeatedly-with-the-function-retaining-internally-the-last-state-of-the-gpio-pin/58748 "2021-04-07T12:09:41Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![GregMcC](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gregmcc/32/14827_2.png) [@GregMcC](https://discourse.julialang.org/u/GregMcC)\
**Post date:** [April 7, 2021, 12:09pm UTC](https://discourse.julialang.org/t/is-there-any-way-i-can-call-an-instance-of-a-function-repeatedly-with-the-function-retaining-internally-the-last-state-of-the-gpio-pin/58748/1 "2021-04-07T12:09:41Z")

</div>

I am wanting to monitor some GPIO pins on a Raspberry Pi. Is there any way I can call an instance of a function repeatedly with the function retaining internally the last state of the GPIO pin - so that I can detect Rising and Falling edges. The only way I have found at the moment is to use Global variables, but there must be a more clever way of doing it. I’ve searched - and I can’t find it.  
( I thought defining Structures within functions might help - but I have drawn a blank )

many thanks for any advice …

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [April 7, 2021, 12:15pm UTC](https://discourse.julialang.org/t/is-there-any-way-i-can-call-an-instance-of-a-function-repeatedly-with-the-function-retaining-internally-the-last-state-of-the-gpio-pin/58748/2 "2021-04-07T12:15:47Z")

</div>

This thread has a few suggestions you might find helpfuL: [In Julia, how to create a function that saves its own internal state?](https://discourse.julialang.org/t/in-julia-how-to-create-a-function-that-saves-its-own-internal-state/58457)

---

<div class="post-metadata">

**Author:** ![GregMcC](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gregmcc/32/14827_2.png) [@GregMcC](https://discourse.julialang.org/u/GregMcC)\
**Post date:** [April 7, 2021, 3:51pm UTC](https://discourse.julialang.org/t/is-there-any-way-i-can-call-an-instance-of-a-function-repeatedly-with-the-function-retaining-internally-the-last-state-of-the-gpio-pin/58748/3 "2021-04-07T15:51:30Z")

</div>

Think this is the simpliest …

> GlobalBool = [false, false , false , false, false , false , false]

then the function :-

> function IdentifyEdgeOfPress(PB :: Int , GlobalBoolPtr :: Int ) :: Int  
> bTemp = gpio\_read(PB)
> 
> if (( bTemp == true ) && ( GlobalBool[GlobalBoolPtr] == false )) ; println("Pressed Edge ") ; end  
> if (( bTemp == false ) && ( GlobalBool[GlobalBoolPtr] == true )) ; println(“Released Edge”) ; end
> 
> global GlobalBool[GlobalBoolPtr] = bTemp  
> end

then just call the function with a different index ( the indices must be not be repeated otherwise there’ll be cross contamination )

```
	IdentifyEdgeOfPress(TestPB,1)
	IdentifyEdgeOfPress(TunePB,2)

```

Bingo - you have a subroutine retaining it’s own state.  
( Thought there might be a more elegant ‘Julia’ way of doing this )

Thanks for your response **rdeits**

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [April 7, 2021, 4:24pm UTC](https://discourse.julialang.org/t/is-there-any-way-i-can-call-an-instance-of-a-function-repeatedly-with-the-function-retaining-internally-the-last-state-of-the-gpio-pin/58748/4 "2021-04-07T16:24:39Z")

</div>

You should at the very least make `GlobalBool` a `const` otherwise you’ll run into the very first [performance tip](https://docs.julialang.org/en/v1/manual/performance-tips/#Avoid-global-variables).

---

<div class="post-metadata">

**Author:** ![GregMcC](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gregmcc/32/14827_2.png) [@GregMcC](https://discourse.julialang.org/u/GregMcC)\
**Post date:** [April 7, 2021, 5:59pm UTC](https://discourse.julialang.org/t/is-there-any-way-i-can-call-an-instance-of-a-function-repeatedly-with-the-function-retaining-internally-the-last-state-of-the-gpio-pin/58748/5 "2021-04-07T17:59:11Z")

</div>

Think I am mis-understanding ‘const’ as in the definition it says :-

> In some cases changing the value of a `const` variable gives a warning instead of an error. However, this can produce unpredictable behavior or corrupt the state of your program, and so should be avoided.

The code is writing to this array to retain the status between polls of the routine - so I don’t see ‘const’ being appropriate.

---

<div class="post-metadata">

**Author:** ![aramirezreyes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aramirezreyes/32/42573_2.png) [@aramirezreyes](https://discourse.julialang.org/u/aramirezreyes)\
**Post date:** [April 7, 2021, 6:02pm UTC](https://discourse.julialang.org/t/is-there-any-way-i-can-call-an-instance-of-a-function-repeatedly-with-the-function-retaining-internally-the-last-state-of-the-gpio-pin/58748/6 "2021-04-07T18:02:58Z")

</div>

The adjacent paragraph says also:

> Note that “constant-ness” does not extend into mutable containers; only the association between a variable and its value is  
> constant. If x is an array or dictionary (for example) you can still modify, add, or remove elements.

So you can actually modify the contents of an array:

```julia

julia> const global a = [1,2,3]
3-element Vector{Int64}:
 1
 2
 3

julia> a[1] = 3
3

julia> a
3-element Vector{Int64}:
 3
 2
 3

```

In your case, making the array a const will let your function know that GlobalBool is always an array of type bool, allowing it to produce optimal code. If you don’t make it a const, the compiler cannot know that your array will not change its type at a later time, so it cannot create efficient code. This will affect your performance.

You can see this in the example above. If I try to put something that cannot be converted into an Int into my array, Julia will complain because the variable a must always have a type Array{Int}

```julia

julia> a[1] = "toto"
ERROR: MethodError: Cannot `convert` an object of type String to an object of type Int64
Closest candidates are:
  convert(::Type{T}, ::T) where T<:Number at number.jl:6
  convert(::Type{T}, ::Number) where T<:Number at number.jl:7
  convert(::Type{T}, ::Base.TwicePrecision) where T<:Number at twiceprecision.jl:250
  ...
Stacktrace:
 [1] setindex!(A::Vector{Int64}, x::String, i1::Int64)
   @ Base ./array.jl:839
 [2] top-level scope
   @ REPL[18]:1

```

---

<div class="post-metadata">

**Author:** ![GregMcC](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gregmcc/32/14827_2.png) [@GregMcC](https://discourse.julialang.org/u/GregMcC)\
**Post date:** [April 8, 2021, 6:19pm UTC](https://discourse.julialang.org/t/is-there-any-way-i-can-call-an-instance-of-a-function-repeatedly-with-the-function-retaining-internally-the-last-state-of-the-gpio-pin/58748/7 "2021-04-08T18:19:55Z")

</div>

Thanks Argel ,

That is a very good explanation. I’m coming from Old School and would expect a crash situation putting a variable of a different type into a previousy defined variable.

thank you

---

<div class="post-metadata">

**Author:** ![FPGro](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fpgro/32/20822_2.png) [@FPGro](https://discourse.julialang.org/u/FPGro)\
**Post date:** [April 8, 2021, 11:54pm UTC](https://discourse.julialang.org/t/is-there-any-way-i-can-call-an-instance-of-a-function-repeatedly-with-the-function-retaining-internally-the-last-state-of-the-gpio-pin/58748/8 "2021-04-08T23:54:46Z")

</div>

> [@GregMcC](#):
>
> then just call the function with a different index ( the indices must be not be repeated otherwise there’ll be cross contamination )

Since handling these indices by hand for every call seems really unsafe to me, I’d suggest giving the approaches in the topic rdeits linked a try! Like a functor for each pin you want:

```julia
julia> struct Edgedetector
           pinnumber::Int
           state::Ref{Bool}
           Edgedetector(pin, initialstate = false) = new(pin, Ref(initialstate))
       end

julia> function (e::Edgedetector)()
           newstate = getgpio(e.pinnumber)
           if newstate
               if !e.state[] println("Pin $(e.pinnumber): Button pressed!") end
           else
               if e.state[] println("Pin $(e.pinnumber): Button released!") end
           end
           e.state[] = newstate
           return newstate
       end

julia> getgpio(_) = rand(Bool); # mocked up

```

```julia
julia> p1 = Edgedetector(1)
Edgedetector(1, Base.RefValue{Bool}(false))

julia> p1()
false

julia> p1()
Pin 1: Button pressed!
true

julia> p1()
Pin 1: Button released!
false

julia> p1()
Pin 1: Button pressed!
true

```

Or if you don’t feel like carrying around an object per pin:

```julia
julia> let pinstates = Dict{Int,Bool}()
           global detectedge
           function detectedge(pinnumber::Int)
               newstate = getgpio(pinnumber)
               if haskey(pinstates, pinnumber)
                   if newstate
                       if !pinstates[pinnumber] println("Pin $(pinnumber): Button pressed!") end
                   else
                       if pinstates[pinnumber] println("Pin $(pinnumber): Button released!") end
                   end
               end
               pinstates[pinnumber] = newstate
               return newstate
           end
       end
detectedge (generic function with 1 method)

julia> getgpio(_) = rand(Bool)

```

```julia
julia> detectedge(1)
true

julia> detectedge(1)
Pin 1: Button released!
false

julia> detectedge(1)
false

julia> detectedge(1)
false

julia> detectedge(1)
Pin 1: Button pressed!
true

julia> detectedge(2)
false

julia> detectedge(2)
Pin 2: Button pressed!
true

```
