Arc Forumnew | comments | leaders | submitlogin
Hook
3 points by hjek 16 days ago | 6 comments
Does anyone know what the deal with the `hook` function in Arc is? What does it do and why?

Take for example news.arc. It looks like `hook` is called several times without `defhook` ever being called, so it would seem like it does ... nothing?





2 points by shader 16 days ago | link

The idea behind a 'hook' is that it is a place where code can be inserted without having to modify the original code. They're pretty common in emacs, for instance, where lots of packages provide hooks for easy extension in your .emacs file.

Arc hooks are apparently pretty lightweight:

  (= hooks* (table))

  (def hook (name . args)
    (aif (hooks* name) (apply it args)))

  (mac defhook (name . rest)
    `(= (hooks* ',name) (fn ,@rest)))
(from https://github.com/arclanguage/anarki/blob/7a1fba03b6faaa06f...)

So, if there's a function bound to that name in the hooks table, it is run with the arguments. You only call 'defhook when you want to bind to that point in the code.

This is a rather interesting implementation to me, because I'm used to the emacs-lisp concept, where a hook is actually a list of functions that all get called on the arguments, so it can be added to multiple times. The corresponding names in elisp are 'run-hooks and 'add-hook. https://www.gnu.org/software/emacs/manual/html_node/elisp/Ho...

reply

2 points by hjek 16 days ago | link

Ok, makes sense. Thanks for the explanation!

So I guess it's on purpose that `(hook 'somewhere)` doesn't do anything until you define a hook for that place yourself, e.g.:

    (defhook somewhere () (pr "Hello from somewhere"))

reply

2 points by krapp 15 days ago | link

I'm hoping to have some functionality for this wired into an update of prompt.arc and pushed soon.

It might be useful to be able to write app scripts and attach them or detach them from hooks. That seems like it would be a decent basis for a plugin system.

Or not, I don't know. We'll see I guess.

reply

3 points by krapp 13 days ago | link

OK, I have a stupid question. How do I remove an item from a table?

Apparently it's (rem test table) but everything I've tried fails with "Can't take car of #hash(("foo" . (app-run "foo")))" I also thought I might have to assign nil to it but that returns an error as well. Here is my current code if it helps... it's just minor edits of prompt.arc, assignment and running an app in a hook all work:

    (def app-unhook (user app)
      (do ((rem !app hooks*) 
          (editor-page user "Hook removed from " app))))

    (def app-hook (user app) 
      (if (file-exists (app-filepath app))
        (do ((= (hooks* app) `(app-run ,app))
            (editor-page user "Hook applied to " app)))
        (editor-page user "Error: No application " app)))
I feel like I'm probably missing something obvious.

reply

3 points by i4cu 13 days ago | link

rem only works on seqs, you need to set the value to nil:

  (= (mytable 'key) nil)
and tables don't hold nil valued entries so it works.

reply

2 points by krapp 13 days ago | link

thanks!

reply