Olical / aniseed

Neovim configuration and plugins in Fennel (Lisp compiled to Lua)
https://discord.gg/wXAMr8F
The Unlicense
606 stars 28 forks source link

attempt to call ... (a nil value) #84

Closed monkoose closed 2 years ago

monkoose commented 2 years ago

Hello, Oli!

--Fixed-- so to save your time you can skip to my next comment, i have some question there.

I'm trying to convert simple functions to aniseed/fennel, and got into a problem.

I have let g:aniseed#env = v:true in my config.

I have this file in my ~/.config/nvim/fnl/myfunctions.fnl

(module myfunctions
  {autoload {a aniseed.core
             as aniseed.string}})

(def- vfn vim.fn)
(def- api vim.api)

(defn- reverse [t]
  (let [t-len (length t)]
    (for [i 1 (math.floor (/ t-len 2))]
      (let [j (a.inc (- t-len i))
            temp-i (. t i)]
        (tset t i (. t j))
        (tset t j temp-i)))
    t))

(defn- synnames []
  (let [[line-nr col-nr] (api.nvim_win_get_cursor 0)]
    (->> (vfn.synstack line-nr
                       (a.inc col-nr))
         (a.map #(vfn.synIDattr $1
                                "name"))
         (reverse))))

(defn print-synnames []
  (print (.. " "
              (as.join " " (synnames)))))

It converted to this file in ~/.config/nvim/lua/myfunctions.lua

local _2afile_2a = "fnl/myfunctions.fnl"
local _2amodule_name_2a = "myfunctions"
local _2amodule_2a
do
  package.loaded[_2amodule_name_2a] = {}
  _2amodule_2a = package.loaded[_2amodule_name_2a]
end
local _2amodule_locals_2a
do
  _2amodule_2a["aniseed/locals"] = {}
  _2amodule_locals_2a = (_2amodule_2a)["aniseed/locals"]
end
local autoload = (require("aniseed.autoload")).autoload
local a, as = autoload("aniseed.core"), autoload("aniseed.string")
do end (_2amodule_locals_2a)["a"] = a
_2amodule_locals_2a["as"] = as
local vfn = vim.fn
_2amodule_locals_2a["vfn"] = vfn
local api = vim.api
_2amodule_locals_2a["api"] = api
local function reverse(t)
  local t_len = #t
  for i = 1, math.floor((t_len / 2)) do
    local j = a.inc((t_len - i))
    local temp_i = t[i]
    t[i] = t[j]
    t[j] = temp_i
  end
  return t
end
_2amodule_locals_2a["reverse"] = reverse
local function synnames()
  local _let_1_ = api.nvim_win_get_cursor(0)
  local line_nr = _let_1_[1]
  local col_nr = _let_1_[2]
  local function _2_(_241)
    return vfn.synIDattr(_241, "name")
  end
  return reverse(a.map(_2_, vfn.synstack(line_nr, a.inc(col_nr))))
end
_2amodule_locals_2a["synnames"] = synnames
local function print_synnames()
  return print((" " .. as.join(" ", synnames())))
end
_2amodule_2a["print-synnames"] = print_synnames

But when I'm trying to call print_synnames() function with :lua require("myfunctions").print_synnames() the error apperas

E5108: Error executing lua [string ":lua"]:1: attempt to call field 'print_synnames' (a nil value)

If i add (print-synnames) into myfunctions.fnl and eval file with conjure - it works and i can see the output in the echo area.

If i add (global Synnames print-synnames) into myfunctions.fnl and then require it in init.fnl then i can call that function without a problem with :lua Synnames()

Inside fnl dir i have another module and i can call some function from it with the :lua require... without a problem. Do i miss something?

monkoose commented 2 years ago

Ok found my mistake.

If I rename print-synnames into something that doesn't have - like printsynnames, then i can require it with :lua require("myfunctions").printsynnames() or i can require it with :lua require("myfunctions")["print-synnames"](). For some reason i thought that fennel transforms dashes into underscore for exposed functions. But it isn't and this line

_2amodule_2a["print-synnames"] = print_synnames

confirms that.

So i guess it is fixed.

Anyway have you any suggestions about this in particular? Should i name all public functions without the dashes (name conventions in lisp) and just use underscores or simple one word names?

I will close it after some time.

Olical commented 2 years ago

Yep you have to be careful with Fnl->Lua naming since Fennel is farrr more permissive (which is great!). My general approach if I'm calling a Fennel compiled Lua function is to just guess what it mangled the name to (:lua require("myfunctions").print_synnames()) or check the .lua to see what it did. For instance, _2a is *, which I know from seeing it mangle that character so much.

I think you could export Lua friendly names if you know your module will be called from Lua a lot (so ensure you stick to a-zA-Z0-9_ or whatever it supports) but I think it's still okay to just use Fennel naming then document / think about how that'll be accessed from vanilla Lua.

Just a quirk of Fennel really! One that you can work around fairly easily but you need to be aware of whenever you're crossing the language boundary.

monkoose commented 2 years ago

Thank you again.

Olical commented 2 years ago

You're welcome, just glad you worked it out!