[CM] s7 C functions and environments

chrg chrghrc at protonmail.com
Sat Jan 11 09:09:53 PST 2025


> Here's an idea:
> 
> /* tfunc.c */
> #include <stdlib.h>
> 
> #include <stdio.h>
> 
> #include <string.h>
> 
> #include "s7.h"
> 
> s7_pointer g_f(s7_scheme sc, s7_pointer args) / (f f 12) */
> {
> s7_pointer let = s7_function_let(sc, s7_car(args));
> s7_pointer x = s7_symbol_local_value(sc, s7_make_symbol(sc, "x"),
> let);
> return(s7_make_integer(sc, s7_integer(x) +
> s7_integer(s7_cadr(args))));
> }
> 
> s7_pointer make_f(s7_scheme sc, s7_pointer args) / (make-f 1) */
> {
> s7_pointer let = s7_sublet(sc, s7_curlet(sc), s7_nil(sc));
> s7_pointer old_curlet = s7_set_curlet(sc, let);
> s7_define(sc, let, s7_make_symbol(sc, "x"), s7_car(args));
> s7_pointer f = s7_make_typed_function_with_environment(sc, NULL, g_f,
> 2, 0, false, "f", NULL, let);
> s7_set_curlet(sc, old_curlet);
> return(f);
> }
> 
> int main(int argc, char **argv)
> {
> char buffer[512];
> char response[1024];
> s7_scheme *s7 = s7_init();
> s7_define_function(s7, "make-f", make_f, 1, 0, false, NULL);
> while (1)
> {
> fprintf(stdout, "\n> ");
> 
> fgets(buffer, 512, stdin);
> if ((buffer[0] != '\n') ||
> (strlen(buffer) > 1))
> 
> {
> sprintf(response, "(write %s)", buffer);
> s7_eval_c_string(s7, response);
> }}
> }
> 
> /*
> The "g_f" function called in C has no idea which value returned by
> make-f is calling it.
> So we can get around that by passing it as an argument ("self"?):
> 
> gcc tfunc.c -o tfunc -I. -g3 s7.o -ldl -lm -Wl,-export-dynamic
> 
> tfunc
> 
> > (define f1 (make-f 1))
> 
> #<c-function> ; NULL as name above = anonymous function
> 
> > (define f2 (make-f 2))
> 
> #<c-function>
> 
> > (f1 f1 3)
> 
> 4
> 
> > (f2 f2 3)
> 
> 5
> */

Hi, sorry for not replying back in a long time.

I had tried this idea too before our discussion, and while I like it, unfortunately it does require the user to call the function in that weird way you show at the end. (there are ways around it, but still...)

I am wondering: is there any way in s7 to get the current C function? I've noticed there is a way for normal Scheme functions (*function*), but it doesn't work inside C functions.

Also, as a note: I see you've added s7_function_let, I suppose because of our discussion. But I must warn that I noticed there already were other ways to access a C function's let: for example, back when I tried implementing this idea, I used s7_let_ref: that somehow worked even if I passed a C function instead of a real let. Well, I suppose using s7_function_let could be faster due to no checks...




More information about the Cmdist mailing list