[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [dev-serveez] Guile switch
From: |
Martin Grabmueller |
Subject: |
Re: [dev-serveez] Guile switch |
Date: |
Fri, 09 Mar 2001 08:49:27 +0100 |
> From: "Raimund 'Raimi' Jacob" <address@hidden>
> Date: Thu, 8 Mar 2001 23:19:02 +0100 (CET)
>
> First, we agreed on 3-call schema for creating servers:
> (ignore scheme errors for now, i think you get the idea)
[example snipped, included with corrections below]
> 'define-port!', 'define-server!' and 'bind!' are procedures to be
> implemented in C and exported to guile. As you can see it is easy to bind
> multiple servers to the same port.
Actually, `define-port!' and `define-server!', as used in the above
example, are syntax, not procedures, because the introduce bindings
for the variables `http-port', `http-server' and `ctrl-server'. The
problem is that `http-port' etc. are not defined when Guile evaluates
the `define-port!' call, and will therefore signal an `unbound
variable' error.
The solution is either to
- define new syntax for the `define-*' calls (which is difficult in
Guile and requires modifying the evaluator).
- define Scheme macros which expand the `define-*' calls into calls to
appropriate procedures, for example:
(define-port! port <port-definition>)
=expands to=>
(define port (make-port-definition <port-definition>))
I think the second posiibility is the way to go. The macros could be
defined in a straup file which gets loaded before the user's config
file, or hard-coded into Serveez and evaluated with a
`gh_eval_string()' call (or however it is called).
Please note that the `define-server!' calls should expect three
arguments: The name of the server (to be referenced in `bind!' calls),
the type of the server and the server options.
`bind!', by the way, could be implemented as a simple procedure.
> we are not sure yet whether we want to write the server's name in
> quotes (string vs. symbol). we are also not sure wether the server type
> should be extracted from the [symbol] name (as we do with sizzle) or given
> explicitly. Any opinion ?
Explicitly stating the server type is better, IMHO (see above).
> Now, serveez does not understand strings and ints as values only, there
> are also those:
> ---
> ;; string array
> (define-port! zwei-interfaces (
> (port . 42420)
> (ipaddr . ("127.0.0.1"
> "192.168.2.2"))
> (proto . tcp)))
> ;; int array
> (define-server! bla-server (
> (numbers . (1 2 3 4 5))))
> ;; hash
> (define-server!
> http-server (
> (content-types . (
> ("gif" . "image/gif")
> ("jpg" . "image/jpeg")
> ("wav" . "audio/x-wav")))))
This is no problem. With some aded quotes, the syntax in the example
is fine.
> ok, now the questions:
> Is it at all possible to write something like that in guile? Can you add
> single quotes (or function calls) at appropriete places so that is valid
> scheme?
(define-port! http-port '(
(ipaddr . "127.0.0.1")
(port . 80)
(proto . tcp)
))
(define-server! http-server
'http ;; <-- inserted server type here
'(
( docdir . "/" )
( logfile . "/dev/null")
))
(define-server!
ctrl-server
'control ;; <-- inserted server type here
'(
(password . "secret")
))
(bind! http-port (list http-server ctrl-server))
;; OR
(bind! http-port `(,http-server ,ctrl-server))
;; OR
(bind! http-port http-server ,ctrl-server)
The syntax for `bind!' depend on whether it expects a list of server
definitions (first and second lines), or whther it expects variable
arguments, which are server definitions.
> ( As you remember we already agreed to use those alist thingies
> which are something like ( (key1 . val1 ) . ( (key2 . val2) . ... )..).
> Ela decided (and convinced me) that this is too much parenthesis.
> the gnutella client has 39 config options which would result in more
> than 40 closing parenthesises!. The above syntax uses much less
> parenthesis but we dont know wether that can work somehow )
I don't understand the problem here. Your example above is perfectly
fine, except for some quoting problems.
> Can you show me (or point me to an example) how to acces variable
> argument lists in a C-defined function ?
You should be able to handle variable arguments with something like
the code below (beware, not tested!):
#include <guile/gh.h>
#define FUNC_NAME "mult-args"
static SCM
mult_args (SCM args)
{
SCM l = args;
/* Handle th argument list in `args' here. */
while (SCM_CONS_P (l))
{
/* Do something with SCM_CAR (l) ... */
gh_write (SCM_CAR (l));
gh_newline ();
/* Go to next list element. */
l = SCM_CDR (l);
}
/* Maybe return a useful value instead of the unspecified one. */
return SCM_UNSPECIFIED;
}
#undef FUNC_NAME
static void
init_guile_stuff (void)
{
/* Declare the procedure as one with 0 fixed arguments, 0 optional
arguments and 1 rest argument (the complete argument list). */
gh_new_procedure("mult-args", mult-args, 0, 0, 1);
}
> How are the above constructs represented in scheme? Can you explain the
> terminology (list, vector to name 2 that confuse us)? I hope to be able
> to figure out how to traverse that in C once i understand the structure...
Okay, here comes my Scheme data type quick tutorial:
- a PAIR is an object with to elements (the CAR and the CDR). It is
constructed with the procedure `cons' or entered as literal data:
(cons 1 2)
'(1 . 2)
- A list is nothing more than CDR-chained pairs. The following are
equivalent:
(list 1 2 3)
'(1 2 3)
(cons 1 (cons 2 (cons 3 '())))
`list' is a procedure which produces a list of all arguments.
'() denotes the empty list (some kind of NULL pointer in Scheme,
used to terminate lists).
- A vector is a fixed-length array of Scheme objects. Equivalent are:
'#(1 2 3)
(vector 1 2 3)
(list->vector '(1 2 3))
#(...) is the notation for literal vectors.
`vector' produces a vector from its arguments.
It is important that a literal list which should be inserted into a
source file must be quoted, because unquoted lists are function
applications. In an application, all element of the list get
evaluated, and then the first element is taken as a procedure and
applied to the remaining elements.
Raimi: the list stuff is pretty much like sequences in Opal, just
another syntax, and cooler, of course.
Hope that helps. Please ask more specific questions if any remain.
Regards,
'martin