digego / extempore

A cyber-physical programming environment
1.41k stars 127 forks source link

Example code from documentation ('Scheme-xtlang interop') doesn't work? #278

Closed kroll-j closed 8 years ago

kroll-j commented 8 years ago

According to https://digego.github.io/extempore/scheme-xtlang-interop.html#more-caveats , I think this should work:

(bind-func squarer:[double,double]*
  (lambda (x)
    (* x x)))

(bind-func test_apply:[double,[double,double]*,double]*
  (lambda (f:[double,double]* x:double)
    (f x)))

(test_apply (llvm:get-native-closure "squarer") 2.0)

But it doesn't:

Compiled:  squarer >>> [double,double]* 
Compiled:  test_apply >>> [double,[double,double]*,double]* 
test_apply_adhoc_W2RvdWJsZSxbZG91YmxlLGRvdWJsZV0qLGRvdWJsZV0 Scheme wrapper error: check the arg arity and types

(llvm:get-native-closure "squarer") returns NIL. Same for other functions/closures apparently.

benswift commented 8 years ago

Hey, thanks for the issues - if the docs aren't clear on these things then they need to be improved.

The issue here is a scheme-xtlang interop one:

http://digego.github.io/extempore/scheme-xtlang-interop.html

If you wrap the call to test_apply in a $ form (to call it as xtlang, rather than scheme) then it should work.

(bind-func squarer:[double,double]*
  (lambda (x)
    (* x x)))

(bind-func test_apply:[double,[double,double]*,double]*
  (lambda (f:[double,double]* x:double)
    (f x)))

($ (test_apply squarer 2.0))

The source for the docs website is in the top-level docs directory, so if you do come across any stuff which is wrong/could be clearer then pull requests are welcome :)

Cheers Ben

j. kroll notifications@github.com writes:

According to https://digego.github.io/extempore/scheme-xtlang-interop.html#more-caveats , I think this should work:

(bind-func squarer:[double,double]*
  (lambda (x)
    (* x x)))

(bind-func test_apply:[double,[double,double]*,double]*
  (lambda (f:[double,double]* x:double)
    (f x)))

(test_apply (llvm:get-native-closure "squarer") 2.0)

But it doesn't:

Compiled:  squarer >>> [double,double]* 
Compiled:  test_apply >>> [double,[double,double]*,double]* 
test_apply_adhoc_W2RvdWJsZSxbZG91YmxlLGRvdWJsZV0qLGRvdWJsZV0 Scheme wrapper error: check the arg arity and types

(llvm:get-native-closure "squarer") returns NIL. Same for other functions/closures apparently.


You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/digego/extempore/issues/278

kroll-j commented 8 years ago

Hm. I grepped for "llvm:get-native-closure" and apparently it needs a bit of tape like here.

(bind-func squarer:[double,double]*
  (lambda (x)
    (* x x)))

(bind-func test_apply:[double,[double,double]*,double]*
  (lambda (f:[double,double]* x:double)
    (f x)))

(test_apply (llvm:get-native-closure (eval (string->symbol (string-append (symbol->string 'squarer) "_xtlang_name")))) 2.0)

This seems to work, but I can't properly explain what it does, so I'd rather not change the docs...

benswift commented 8 years ago

Fixed in b682a9f

kroll-j commented 8 years ago

But that changes the meaning doesn't it? The docs previously explained how to pass an xtlang closure to an xtlang closure from a scheme context, which was exactly what I was looking for. The new version just calls the fn from an xtlang context, which is different. Also, if I understand correctly, the $ form is JIT-compiled every time, with all its overhead. Each ($ (printf "test\n")) I run takes about half a second on my laptop. That's not usable in audio or drawing callbacks etc. The other method doesn't have such overhead.

I think the native closure thing is handy and should be in the docs. It works, I just don't know enough about Extempore (yet) to understand what the magic (eval (string->symbol (string-append (symbol->string 'squarer) "_xtlang_name")))) does. That's why I didn't want to change your documentation.

Sorry for the fuss. :)

benswift commented 8 years ago

Hey, sorry that the "fixed in blah" message was a bit brief. The actual issue here is Extempore recently gained automatic poly-ing if you define multiple functions with the same name but different type signatures. One implication is that the scheme wrappers are now a bit more complicated and the above doesn't work (the scheme wrapper doesn't/can't know how to use the right version of squarer).

This doesn't mean that you can't use xtlang functions as first-class args, etc. Just that you can only do that from xtlang, not through the scheme wrapper anymore. The compile-every-time overhead of $ is indeed a pain for anything you're going to do repeatedly, so you should probably wrap it in another function e.g.

(bind-func squarer:[double,double]*
  (lambda (x)
    (* x x)))

(bind-func apply_function:[double,[double,double]*,double]*
  (lambda (f:[double,double]* x:double)
    (f x)))

(bind-func test_apply_squarer
  (lambda ()
    (apply_function squarer 2.0)))

(println (test_apply_squarer))

None of this is ideal, and will go away once xtlang is self-hosting, but that's why the situation described in the docs doesn't work anymore. Hope that clears things up.