[Chicken-hackers] functors

2011-03-24 Thread Felix
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

2011-03-24 Thread Felix
 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-03-24 Thread Thomas Chust
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

2011-03-24 Thread Felix
 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

2011-03-24 Thread Felix
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

2011-03-24 Thread Peter Danenberg
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

2011-03-24 Thread Peter Danenberg
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

2011-03-24 Thread Jim Ursetto
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

2011-03-24 Thread Peter Danenberg
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

2011-03-24 Thread Jim Ursetto
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