translating working lua code (for hammerspoon) to fennel; expected userdata type

482 Views Asked by At

Caveat: I don't really know lua or fennel, though I do have a lot of experience in lua-like languages (python etc.) and fennel-like languages (clojure, elisp, etc.).

But: I was using hammerspoon to manage external monitor configuration on my mac. I had the following, correctly-working, code in my init.lua file for hammerspoon to go get my external monitor and switch it to vertical:

function rotate90()
   hs.screen.find('Dell'):rotate(90)
end

But then I realized that I wanted to use the pre-built modal menu toolkit spacehammer, which is basically like spacemacs for hammerspoon---but which is written in Fennel. Ok, I like lisps, I can handle a config file in a lisp, right?

So first I get spacehammer working, and verify that the default configuration works fine and doesn't throw any errors. Check.

Then I go to port over my simple preexisting functions: I translate my lua function into a Fennel function with a slightly different name:

(fn rotate-vertical []
  (let [monitor (hs.screen.find "Dell")]
    (monitor.rotate 90)))

Right? It's your basic lisp translation, it should work perfectly fine. But when I try to run it, all of a sudden I get errors coming from c-land:

2021-02-19 17:24:59: 17:24:59 ERROR: LuaSkin: hs.timer callback error: /Users/myhomedir/.spacehammer/config.fnl:24: ERROR: incorrect type 'number' for argument 1 (expected userdata) stack traceback: [C]: in field 'rotate' /Users/myhomedir/.spacehammer/config.fnl:24: in function </Users/myhomedir/.spacehammer/config.fnl:22>

the line numbers, interestingly, in the traceback are not correct at all: in config.fnl those lines are comments. But I assume that it has to be the new function, because that's all I changed, and the error was triggered on attempting to run it. But the hammerspoon rotate method that I'm attempting to call definitely takes a number, not whatever "userdata" is...

1

There are 1 best solutions below

0
Paul Gowder On

Oooof. Ok, this is actually my misreading of Fennel docs on method calls. I'll leave the question up just because it seems like an easy gotcha for Google purposes. But apparently method access with periods required you to pass the name of the table in which the method lives a second time, whereas this is not required with method access via colons. So I got it working by changing the last expression to (monitor:rotate 90) --- and I guess (monitor.rotate monitor 90) would have worked as well, judging by the third example in the above-linked section of the docs?