dev-serveez
[Top][All Lists]
Advanced

[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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]