# Detecting keypress

**URL:** https://discourse.julialang.org/t/detecting-keypress/60612
**Category:** New to Julia
**Tags:** scope, gtk
**Created:** [May 6, 2021, 1:14am UTC](https://discourse.julialang.org/t/detecting-keypress/60612 "2021-05-06T01:14:24Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![rverdier](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rverdier/32/9104_2.png) [@rverdier](https://discourse.julialang.org/u/rverdier)
#### Post date: [May 6, 2021, 1:14am UTC](https://discourse.julialang.org/t/detecting-keypress/60612/1 "2021-05-06T01:14:24Z")

</div>

For a Julia+Gtk course I’m writing, I need to process keys when pressed. This stripped-down example shows that this only works if the callback function, keycall, is defined inside, not outside, the keypresswindow function. Can anybody explain how to make this work when keycall is defined outside? Thanks for any help.  
MacOS 10.14.4, Julia 1.5

```julia
# keytest.jl: Detect typed keys
using Gtk
win = GtkWindow("Keypress Test")
# Does not work if keycall is defined only here
    function keycall(w, event)
        ch = Char(event.keyval)
        tcount += 1
        println("$tcount: $ch")
    end
    signal_connect(keycall, win, "key-press-event")
#
function keypresswindow()
    tcount = 0
    println("Click on window, then press any keys")
# Works only if keycall is defined here; change true to false to demonstrate
  if true
    function keycall(w, event)
        ch = Char(event.keyval)
        tcount += 1
        println("$tcount: $ch")
    end
    signal_connect(keycall, win, "key-press-event")
  end
end
keypresswindow()
return

```

---

<div class="post-metadata">

### Author: ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)
#### Post date: [May 6, 2021, 7:40am UTC](https://discourse.julialang.org/t/detecting-keypress/60612/2 "2021-05-06T07:40:33Z")

</div>

In your version where `keycall` is defined “outside” (i.e. in the global, module scope) you have an issue regarding (write) access to a (non-existent) global variable `tcount`.

This issue is solved in your other version, because `tcount` now refers to a well-defined local variable in `keypresswindow`, and `keycall` is a closure that closes over that variable.

A way to make it work with a global function `keycall` would be to explicitly declare `tcount` as a global, mutable variable (which you’d rather make constant). In the example below, I made `tcount` a [reference](https://docs.julialang.org/en/v1/base/c/#Core.Ref); note in particular how its value is always accessed as `tcount[]`:

```julia
using Gtk
win = GtkWindow("Keypress Test")

# tcount is a global variable, of type Ref{Int}
# the value it refers to is accessed as tcount[]
const tcount = Ref(0)

# keycall is a regular (global) function
function keycall(w, event)
    @info "Key press event"
    ch = Char(event.keyval)
    tcount[] += 1
    println("$(tcount[]): $ch")
end

signal_connect(keycall, win, "key-press-event")

```

Or you could stick with the current solution of having `keycall` close over a local variable (which makes it possible to access to `tcount` more naturally). One way to do that would look like:

```julia
using Gtk
win = GtkWindow("Keypress Test")

const keycall = let
    # tcount is a regular local variable (defined in the scope of the `let` block
    tcount = 0

    # keycall is now a closure over tcount
    function (w, event)
        @info "Key press event"
        ch = Char(event.keyval)
        tcount += 1
        println("$tcount: $ch")
    end
end

signal_connect(keycall, win, "key-press-event")

```

---

<div class="post-metadata">

### Author: ![jdad](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jdad/32/4739_2.png) [@jdad](https://discourse.julialang.org/u/jdad)
#### Post date: [May 6, 2021, 7:59am UTC](https://discourse.julialang.org/t/detecting-keypress/60612/3 "2021-05-06T07:59:00Z")

</div>

Probably stupid question, but, in OP case (function keypresswindow), both tcount and key all are local to keypresswindow, so, how come they are not discarded after returning? How the compiler knows it has to capture them?

---

<div class="post-metadata">

### Author: ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)
#### Post date: [May 6, 2021, 8:30am UTC](https://discourse.julialang.org/t/detecting-keypress/60612/4 "2021-05-06T08:30:22Z")

</div>

Names already existing in the containing scope are assigned into there. Python uses the `nonlocal` keyword for this behavior but doing it automatically is traditional in Lisp which Julia inherits from.

Detailed thread about this:

> [@Referencing local variable before assignment results in unexpected behavior](https://discourse.julialang.org/t/referencing-local-variable-before-assignment-results-in-unexpected-behavior/58088):
>
> Julia version: 1.6.0 I recently had a bug in my code, after isolating the bug, it came down to a piece of code that looks like this: function outer(n) function inner() n = n + 1 end inner() return n end println(outer(3)) 4 My impression was that outer(3) should return 3, but it actually returns 4. Somehow the code in the inner() block assigns value 4 to the variable n outside of its scope. To me this is very counter-intuitive. Is this a bug or intended beh…

---

<div class="post-metadata">

### Author: ![jdad](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jdad/32/4739_2.png) [@jdad](https://discourse.julialang.org/u/jdad)
#### Post date: [May 6, 2021, 8:43am UTC](https://discourse.julialang.org/t/detecting-keypress/60612/5 "2021-05-06T08:43:14Z")

</div>

Thank you for the enlightening reference!

---

<div class="post-metadata">

### Author: ![rverdier](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rverdier/32/9104_2.png) [@rverdier](https://discourse.julialang.org/u/rverdier)
#### Post date: [May 6, 2021, 9:16pm UTC](https://discourse.julialang.org/t/detecting-keypress/60612/6 "2021-05-06T21:16:47Z")

</div>

Thanks for catching my error. I’m somewhat surprised that neither REPL nor the compiler flagged the error inside the function, since the bare statement a+=1 is immediately flagged by the REPL… but then, I didn’t catch it either. I’m grateful to those who responded.
