[Chicken-hackers] functors
Hello! For quite a while I thought about how to implement functors, i.e. modules that take modules as parameters. After several failed attempts with macros that expand into modules I now tried a different approach by directly integrating this into the core system. Tests pass and things appear to work fine, but I'm unsure whether the approach is sound or whether it s considered useful. This also adds a few generalizations to the module system, and I present the concepts here in case someone has suggestions or criticisms. Interfaces: It is possible to define /interfaces/ (named groups of exports), for example: (define-interface ARITHMETIC (+ - * /)) (module foo (this that (interface: ARITHMETIC) the-other) ...) The export list of a module may optionally be an interface name so (module bar ((interface: ARITHMETIC)) ...) could also be written as (module bar ARITHMETIC ...) [This implies an interface may not be named *] The syntax is a bit ugly, but I couldn't think of a better way, which doesn't introduce ambiguity into the syntax. For symmetry, there is now also (syntax: SYNTAXIDENTIFIER [IMPLICITEXPORT ...]), equivalent to (SYNTAXIDENTIFIER [IMPLICITEXPORT ...]). This is not enforced in the moment, but may be useful for documentation purposes. Functors: A /functor/ is a module that takes other modules as parameters, binding the argument modules to temporary identifiers inside the body: (functor (linear-search-functor (S FINITE-SET)) (search) (import scheme S) ...) Inside linear-search-functor, S refers to some module that satisfies the interface SEQUENCE, that is, which exports at least the identifiers defined in the interface. The general syntax is: (functor (FUNCTORNAME (ARGUMENT1 EXPORTLIST1) ...) FUNCTOREXPORTS BODY ...) One uses a functor by /instantiating/ it: (module my-search = (linear-search-functor some-key-value-store)) (import my-search) (search ...) This will expand into a module definition containing the body of the functor linear-search-functor, and with imports of S redirected to the module some-key-value-store. This could be simply done by syntax that expands into a module, but functor-instantiation will check that the argument modules satisfy the required exports. Also, the functor itself will be put into a module, so an import-library can be generated and installed for it. I'm not sure if simply substituting the functor body in the instantiation is a problem - exccessive use may result in code bloat, which means functors should be restricted to the part that is truly specialized to the argument modules. Standard ML compilers IMHO generate only a single functor body, but it is very difficult to find much information about functor implementation, apart from a lot of type-theoretic mumbo jumbo. Scheme48 apparently has higher-order modules, but only hints at them in the manual. Another difference is that an import may refer to a procedure in one instantiation and to syntax in another one. Restricting this looks like a loss of expressivity to me, so full functor-body substitution seems to be the only option. On the other hand, this allows the body to compile to heavily specialized code if the imports refer to syntax, low-level intrinsics or those core library procedures that the compiler is able to optimize well (or for which type-information is available in the forthcoming type-driven specialization optimization which is currently in the works). I have seen heavily optimized libraries once or twice, which basically where just a macro parameterized with primitive operations that expands into a set of procedure definitions. I remember a really badass red-black tree implementation by Marc Feeley, but can't recall where I found it. It was written in this style and would be a perfect use case for a functor. Anyway, that's it. cheers, felix ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org http://lists.nongnu.org/mailman/listinfo/chicken-hackers
Re: [Chicken-hackers] functors
One question: right now it is necessary to define an intermediary module and then another one to actually instantiate the functor like. in this example from the documentation: (module nums (multiply) (import scheme) (define (multiply x y) (* x y))) (module number-squarer = (squaring-functor nums)) Maybe I didn't understand it all correctly but is there syntax for folding that into one definition? E.g. something like this: (module number-squarer ((instantiates: squaring-functor)) (import scheme) (define (multiply x y) (* x y))) squaring-functor takes any number of arguments, so your example would probably an abbreviation for the common case of instantiating a functor with a single argument module and providing the body of that argument at the same step. Interesting! I'll ponder this. cheers, felix ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org http://lists.nongnu.org/mailman/listinfo/chicken-hackers
Re: [Chicken-hackers] functors
2011/3/24 Felix fe...@call-with-current-continuation.org: [...] (module foo (this that (interface: ARITHMETIC) the-other) ...) [...] Hello, just a small remark about the syntax: I find this use of keywords rather unintuitive. I would either expect to be able to write something like this: (module foo (bar baz #:interface ARITHMETIC boing) ...) Or something like this: (module foo (bar baz (interface ARITHMETIC) boing) ...) But a keyword in operator position is unusual and looks rather strange to me. Ciao, Thomas -- When C++ is your hammer, every problem looks like your thumb. ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org http://lists.nongnu.org/mailman/listinfo/chicken-hackers
Re: [Chicken-hackers] functors
Hello, Hi! just a small remark about the syntax: I find this use of keywords rather unintuitive. I would either expect to be able to write something like this: (module foo (bar baz #:interface ARITHMETIC boing) ...) Or something like this: (module foo (bar baz (interface ARITHMETIC) boing) ...) But a keyword in operator position is unusual and looks rather strange to me. The problem is that the latter example is ambiguous - it is the same as exporting a macro interface that implicitly exports the binding ARITHMETIC. The former example doesn't also looks confusing to me, but that is more a matter of taste. The use of a keyword is indeed not everybodies taste, but I couldn't come up with a better syntax that is both unambiguous and obvious. cheers, felix ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org http://lists.nongnu.org/mailman/listinfo/chicken-hackers
Re: [Chicken-hackers] functors
From: Moritz Heidkamp mor...@twoticketsplease.de Subject: Re: [Chicken-hackers] functors Date: Thu, 24 Mar 2011 12:12:50 +0100 Maybe I didn't understand it all correctly but is there syntax for folding that into one definition? E.g. something like this: (module number-squarer ((instantiates: squaring-functor)) (import scheme) (define (multiply x y) (* x y))) One possible syntax would be: (module number-squarer = squaring-functor (import scheme) ...) cheers, felix ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org http://lists.nongnu.org/mailman/listinfo/chicken-hackers
[Chicken-hackers] Patch for fastcgi on chicken master
The fastcgi egg doesn't build anymore with error such as: Error: illegal foreign argument type `(pointer c-string)' The attached patch merely replaces pointer with c-pointer; seems to work. Index: trunk/fastcgi.scm === --- trunk/fastcgi.scm (revision 23250) +++ trunk/fastcgi.scm (working copy) @@ -50,7 +50,7 @@ ;;; (define-foreign-type fcgx-stream c-pointer) -(define-foreign-type fcgx-param-array (pointer c-string)) +(define-foreign-type fcgx-param-array (c-pointer c-string)) (define (fcgx-init-if-necessary!) (unless (or *fcgi-has-been-initialised* @@ -199,8 +199,8 @@ ;;; Utility function for incrementing a char**. (define sarray-pointer+1 (foreign-lambda* -(pointer c-string) -(((pointer c-string) p)) +(c-pointer c-string) +(((c-pointer c-string) p)) return(p + 1);)) (define (wrap-env e) @@ -213,7 +213,7 @@ ;; Convert the char ** array into a list of key/value cons pairs. (let loop ((strlist '()) (p e)) (let ((deref - ((foreign-lambda* c-string (((pointer c-string) ps)) return(*ps);) + ((foreign-lambda* c-string (((c-pointer c-string) ps)) return(*ps);) p))) (cond (deref ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org http://lists.nongnu.org/mailman/listinfo/chicken-hackers
Re: [Chicken-hackers] Patch for fastcgi on chicken master
Quoth Peter Danenberg on Pungenday, the 10th of Discord: The attached patch merely replaces pointer with c-pointer; seems to work. While we're at it, we should be able to send binary data over OUT; the signature of FCGX_PutStr is: DLLAPI int FCGX_PutStr(const char *str, int n, FCGX_Stream *stream); so let's change the binding to: (foreign-lambda int FCGX_PutStr blob int fcgx-stream) otherwise, we get: Error: (##sys#make-c-string) cannot represent string with NUL bytes as C string See attached patch. Index: fastcgi.scm === --- fastcgi.scm (revision 23250) +++ fastcgi.scm (working copy) @@ -50,7 +50,7 @@ ;;; (define-foreign-type fcgx-stream c-pointer) -(define-foreign-type fcgx-param-array (pointer c-string)) +(define-foreign-type fcgx-param-array (c-pointer c-string)) (define (fcgx-init-if-necessary!) (unless (or *fcgi-has-been-initialised* @@ -125,7 +125,7 @@ (foreign-lambda c-string FCGX_GetParam c-string fcgx-param-array)) (define fcgx-put-str - (foreign-lambda int FCGX_PutStr c-string int fcgx-stream)) + (foreign-lambda int FCGX_PutStr blob int fcgx-stream)) (define fcgx-has-seen-eof (foreign-lambda bool FCGX_HasSeenEOF fcgx-stream)) @@ -199,8 +199,8 @@ ;;; Utility function for incrementing a char**. (define sarray-pointer+1 (foreign-lambda* -(pointer c-string) -(((pointer c-string) p)) +(c-pointer c-string) +(((c-pointer c-string) p)) return(p + 1);)) (define (wrap-env e) @@ -213,7 +213,7 @@ ;; Convert the char ** array into a list of key/value cons pairs. (let loop ((strlist '()) (p e)) (let ((deref - ((foreign-lambda* c-string (((pointer c-string) ps)) return(*ps);) + ((foreign-lambda* c-string (((c-pointer c-string) ps)) return(*ps);) p))) (cond (deref ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org http://lists.nongnu.org/mailman/listinfo/chicken-hackers
Re: [Chicken-hackers] Patch for fastcgi on chicken master
Hi Peter, On Mar 24, 2011, at 8:53 PM, Peter Danenberg wrote: so let's change the binding to: (foreign-lambda int FCGX_PutStr blob int fcgx-stream) Shouldn't this be scheme-pointer, not blob? I believe calling that with a string would result in a type error, so I am surprised you can get it to work. Jim ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org http://lists.nongnu.org/mailman/listinfo/chicken-hackers
Re: [Chicken-hackers] Patch for fastcgi on chicken master
Quoth Jim Ursetto on Pungenday, the 10th of Discord: On Mar 24, 2011, at 8:53 PM, Peter Danenberg wrote: so let's change the binding to: (foreign-lambda int FCGX_PutStr blob int fcgx-stream) Shouldn't this be scheme-pointer, not blob? I believe calling that with a string would result in a type error, so I am surprised you can get it to work. Maybe you're right, Jim; scheme-pointer seems to work equally well. Attached. Index: fastcgi.scm === --- fastcgi.scm (revision 23250) +++ fastcgi.scm (working copy) @@ -50,7 +50,7 @@ ;;; (define-foreign-type fcgx-stream c-pointer) -(define-foreign-type fcgx-param-array (pointer c-string)) +(define-foreign-type fcgx-param-array (c-pointer c-string)) (define (fcgx-init-if-necessary!) (unless (or *fcgi-has-been-initialised* @@ -125,7 +125,7 @@ (foreign-lambda c-string FCGX_GetParam c-string fcgx-param-array)) (define fcgx-put-str - (foreign-lambda int FCGX_PutStr c-string int fcgx-stream)) + (foreign-lambda int FCGX_PutStr scheme-pointer int fcgx-stream)) (define fcgx-has-seen-eof (foreign-lambda bool FCGX_HasSeenEOF fcgx-stream)) @@ -199,8 +199,8 @@ ;;; Utility function for incrementing a char**. (define sarray-pointer+1 (foreign-lambda* -(pointer c-string) -(((pointer c-string) p)) +(c-pointer c-string) +(((c-pointer c-string) p)) return(p + 1);)) (define (wrap-env e) @@ -213,7 +213,7 @@ ;; Convert the char ** array into a list of key/value cons pairs. (let loop ((strlist '()) (p e)) (let ((deref - ((foreign-lambda* c-string (((pointer c-string) ps)) return(*ps);) + ((foreign-lambda* c-string (((c-pointer c-string) ps)) return(*ps);) p))) (cond (deref ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org http://lists.nongnu.org/mailman/listinfo/chicken-hackers
Re: [Chicken-hackers] Patch for fastcgi on chicken master
OK, it turns out blob and scheme-pointer are equivalent in argument position (contrary to the docs, blob does not check for blobbiness, only blockiness, which is more general). Anyway, applied in fastcgi 1.1.1. Thanks! Jim On Mar 24, 2011, at 10:00 PM, Peter Danenberg wrote: Quoth Jim Ursetto on Pungenday, the 10th of Discord: On Mar 24, 2011, at 8:53 PM, Peter Danenberg wrote: so let's change the binding to: (foreign-lambda int FCGX_PutStr blob int fcgx-stream) Shouldn't this be scheme-pointer, not blob? I believe calling that with a string would result in a type error, so I am surprised you can get it to work. Maybe you're right, Jim; scheme-pointer seems to work equally well. Attached. fastcgi-scheme-pointer.patch ___ Chicken-hackers mailing list Chicken-hackers@nongnu.org http://lists.nongnu.org/mailman/listinfo/chicken-hackers