unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* exposing C struct contents in Scheme
@ 2003-04-22 12:56 Pascal Haakmat
  2003-04-22 14:22 ` Dale P. Smith
  2003-04-23 15:59 ` Robert Uhl
  0 siblings, 2 replies; 5+ messages in thread
From: Pascal Haakmat @ 2003-04-22 12:56 UTC (permalink / raw)


Hello,

I'm considering the use of guile to script my application. Since I'm
new to guile (and Scheme/LISPish languages in general), I want to take
things slowly and start out using a very limited subset of language
features. I'm still not decided whether I like Scheme and/or whether
it's the best tool for the job, but a lot of that uncertainty stems
from the fact that I have little intuition on how to do things in the
language or what the proper idioms are. So I'm looking for some
advice.

Most importantly, I am unsure how to represent/modify my application's
struct's from guile. The guile documentation on SMOBifying structs
made the initial work quite easy, but it doesn't really address the
question of how to deal with the information inside the structs. As
far as I can see, there are 3 methods to deal with that:

1. Write getter/setter functions for every property in the struct.
2. Write a generic getter/setter function that takes a string argument
   denoting the property to get/set.
3. Use some kind of Scheme type (records? structs? objects? I'm
   confused about these and from what little examples I have seen the
   Scheme syntax to manipulate these types seems rather grotty).
   
The first method has the drawback that it provides no means of 
enumerating all possible properties. The second method might be slow
for large numbers of properties. The third method has the drawback
that it probably requires huge changes in my program, and I guess I'd
also be relinquishing a lot of control, which I'm not quite prepared
to do until I become more familiar with guile/Scheme. 

I'm leaning towards the second method, but would prefer something more
Scheme-native (a la method 3) if only I knew how to get started
(without having to make huge changes). So I'd appreciate some examples
on how I might do that (and enumerate the properties in a
record/struct/object), or pointers to examples.

Sorry for the long mail on what is probably a FAQ, but I couldn't find
a lot of info on the mailing lists, and I barely understood what I did
find. Hopefully some of you can find the time to help me on my way.

Thanks,
Pascal.


_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: exposing C struct contents in Scheme
  2003-04-22 12:56 exposing C struct contents in Scheme Pascal Haakmat
@ 2003-04-22 14:22 ` Dale P. Smith
  2003-04-23 15:59 ` Robert Uhl
  1 sibling, 0 replies; 5+ messages in thread
From: Dale P. Smith @ 2003-04-22 14:22 UTC (permalink / raw)
  Cc: guile-user

On Tue, 22 Apr 2003 14:56:13 +0200
Pascal Haakmat <a.haakmat@chello.nl> wrote:

> Most importantly, I am unsure how to represent/modify my application's
> struct's from guile. The guile documentation on SMOBifying structs
> made the initial work quite easy, but it doesn't really address the
> question of how to deal with the information inside the structs. As
> far as I can see, there are 3 methods to deal with that:
> 
> 1. Write getter/setter functions for every property in the struct.
> 2. Write a generic getter/setter function that takes a string argument
>    denoting the property to get/set.
> 3. Use some kind of Scheme type (records? structs? objects? I'm
>    confused about these and from what little examples I have seen the
>    Scheme syntax to manipulate these types seems rather grotty).
>    
> The first method has the drawback that it provides no means of 
> enumerating all possible properties. The second method might be slow
> for large numbers of properties. The third method has the drawback
> that it probably requires huge changes in my program, and I guess I'd
> also be relinquishing a lot of control, which I'm not quite prepared
> to do until I become more familiar with guile/Scheme. 
> 
> I'm leaning towards the second method, but would prefer something more
> Scheme-native (a la method 3) if only I knew how to get started
> (without having to make huge changes). So I'd appreciate some examples
> on how I might do that (and enumerate the properties in a
> record/struct/object), or pointers to examples.

I had a similar problem with mod-guile.  I ended up writing some C
macros that create all the getter/setter routines I needed.  See
http://savannah.nongnu.org/cgi-bin/viewcvs/*checkout*/mod-guile/mod-guile/mod_guile.c?rev=1.3&content-type=text/plain

-Dale

-- 
Dale P. Smith
Senior Systems Consultant,      | Treasurer,
Altus Technologies Corporation  | Cleveland Linux Users Group
dsmith at altustech dot com     | http://cleveland.lug.net
440-746-9000 x239               |


_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: exposing C struct contents in Scheme
  2003-04-22 12:56 exposing C struct contents in Scheme Pascal Haakmat
  2003-04-22 14:22 ` Dale P. Smith
@ 2003-04-23 15:59 ` Robert Uhl
  2003-04-28 16:14   ` Rob Browning
  1 sibling, 1 reply; 5+ messages in thread
From: Robert Uhl @ 2003-04-23 15:59 UTC (permalink / raw)


Pascal Haakmat <a.haakmat@chello.nl> writes:
> 
> I'm considering the use of guile to script my application.

Cool!  I believe that in the long run you'll find that it's very much
worth it.  Remember that emacs got where it has due to being so
scriptable in a Lisp dialect.

> I'm still not decided whether I like Scheme and/or whether it's the
> best tool for the job, but a lot of that uncertainty stems from the
> fact that I have little intuition on how to do things in the language
> or what the proper idioms are.

Well, the great thing about the Lisp family is that a) they're geared
towards functions, which is what most actual calculation is about and b)
they can do procedural programming and OOP quite easily, too.  In other
words, no matter which idiom fits your problems best, it's quite likely
that you can convince Scheme to handle it well.

> Most importantly, I am unsure how to represent/modify my application's
> struct's from guile.

Are these conceptually OOP objects?  If so, you might wish to
investigate GOOPS or some other framework to use for calculation within
guile, and simply convert to/from when calling your app's functions.

> 1. Write getter/setter functions for every property in the struct.

This is what I've done, partly because I'm writing in gtk+ and already
have to write getters & setters in C; the burden of writing them in
guile was negligible.  Even in C you might find that your library is
more robust if you always use functions (they can really be macros...)
to get/set structure members.

One bit of Scheme tradition is naming.  A value getter will typically
just be that value's name (e.g. trav-mapobject-name returns an object's
name), while the setter is the getter with a ! appended
(e.g. trav-mapobject-name! to set the name); a predicate would be a name
with a ? appended (e.g. trav-mapobject?, which returns true if its
argument is a TravMapobject).  Also, names are typically lower-case
where others might use caps.

Thus this piece of code:

(if (trav-mapobject? obj)
    (if (string=? (trav-mapobject-name obj) "Untitled")
        (trav-mapobject-name! obj
                              (string-append "Untitled "
                                             (number->string
                                                (inc untitled-count))))))

What this does is name an object in the pattern "Untitled 1" if it is
already named "Untitled."  It presupposes a macro in which takes an
argument, increments it and returns the result.  This code is not very
clean; it'd be more readable to define a function untitled-name which
would do the (string-append ...) for one--but you get the idea.

> 2. Write a generic getter/setter function that takes a string argument
>    denoting the property to get/set.

This actually wouldn't work as well as you might think.  In Scheme it's
easy to write a macro which, given a record and a string (or symbol)
representing a field, sets the field.  But at some point you'll have to
have a C interface to do the same thing (consider a function
set_field(struct foo* x, char* name, void* value)...), or you'll have to
enumerate everything anyway.  This is one of the several advantages
Scheme has over C--but it's no help with the underpinnings are C.

> 3. Use some kind of Scheme type (records? structs? objects? I'm
>    confused about these and from what little examples I have seen the
>    Scheme syntax to manipulate these types seems rather grotty).

It's really not so bad.  Generally you create a type, then you create
functions which get and set the fields of that type.  It's actually
quite elegant.  As an example:

(define foo-type (make-record-type "foo" '(name date comment)))

;; Exactly equivalent to:
;;
;; struct foo
;; {
;;   char* name;
;;   time_t date;
;;   char* comment;
;; };
;;
;; Except of course the Scheme members can be of any type (unless you
;; constrain them...)

(define foo-new (record-constructor foo-type '(name date comment)))

;; Equivalent to:
;; 
;; struct foo* foo_new(char* name, time_t date, char* comment)
;; {
;;   struct foo* new;
;; 
;;   new = (struct foo*)malloc(sizeof(struct foo));
;;   new->name = strcpy(name, strlen(name));
;;   new->date = date;
;;   new->comment = strcpy(comment, strlen(comment));
;;   return new;
;; }
;; 
;; Except of course that it's rather more elegant:-)

(define foo-new-blank (record-constructor foo-type))

;; Equivalent to:
;; 
;; struct foo* foo_new_blank(void)
;; {
;;   return (struct foo*)malloc(sizeof(struct foo));
;; }

(define is-foo? (record-predicate foo-type))

;; This would be handled by the compiler in C, due to the fact that C's
;; types are static.

(define foo-name (record-accessor foo-type 'name))

;; Equivalent to:
;; 
;; char* foo_get_name(struct foo* foo)
;; {
;;   return strcpy(foo->name, strlen(foo->name));
;; }
;; 
;; Except in C one has to worry about managing that copied string--and one
;; really ought to make sure that foo->name is not NULL, and one cannot do
;; anything if it's a pointer to never-never land...

(define foo-name! (record-accessor foo-type 'name))

;; Equivalent to:
;; 
;; void foo_set_name(struct foo* foo, char* name)
;; {
;;   free(foo->name);
;;   foo->name = strcpy(name, strlen(name));
;; }
;; 
;; Except one would want to check to ensure that foo->name is not NULL,
;; than name is not NULL, and one would be in trouble if name were a
;; pointer into never-never land.

You might use these functions like this:

(let ((foo (foo-new "A foo" (current-time) "My first foo")))
     (write-line (foo-name foo)) ;; displays A foo\n
     (foo-name! foo "Aristobulus Guthlacii")
     (write-line (foo-name foo)) ;; displays Aristobulus Guthlacii\n
     (write-line (is-foo? foo)) ;; displays #t\n
     (write-line (is-foo? "egg"))) ;; displays #f\n

As you can see, it's actually quite far from grotty:-)

> The third method has the drawback that it probably requires huge
> changes in my program, and I guess I'd also be relinquishing a lot of
> control, which I'm not quite prepared to do until I become more
> familiar with guile/Scheme.

That's the real argument against it.  Also, it means that to access data
members from C you have to go through the slow Scheme layer.  Nt the
best way to do things IMHO.

Anyway, I'd simply write out a full complement of getters & setters.

HTH.

-- 
Robert Uhl <ruhl@4dv.net>
In general, it is best to assume that the network is filled with
malevolent entities that will send in packets designed to have the
worst possible effect.                      --Jon Postel, RFC 1122


_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: exposing C struct contents in Scheme
  2003-04-23 15:59 ` Robert Uhl
@ 2003-04-28 16:14   ` Rob Browning
  2003-04-29  0:41     ` Robert Uhl
  0 siblings, 1 reply; 5+ messages in thread
From: Rob Browning @ 2003-04-28 16:14 UTC (permalink / raw)
  Cc: guile-user

Robert Uhl <ruhl@4dv.net> writes:

> This is what I've done, partly because I'm writing in gtk+ and already
> have to write getters & setters in C; the burden of writing them in
> guile was negligible.  Even in C you might find that your library is
> more robust if you always use functions (they can really be macros...)
> to get/set structure members.

And it makes it easy if you ever need to instrument public access to
the struct, or add locking, or whatever.

-- 
Rob Browning
rlb @defaultvalue.org, @linuxdevel.com, and @debian.org
Previously @cs.utexas.edu
GPG starting 2002-11-03 = 14DD 432F AE39 534D B592  F9A0 25C8 D377 8C7E 73A4


_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: exposing C struct contents in Scheme
  2003-04-28 16:14   ` Rob Browning
@ 2003-04-29  0:41     ` Robert Uhl
  0 siblings, 0 replies; 5+ messages in thread
From: Robert Uhl @ 2003-04-29  0:41 UTC (permalink / raw)


Rob Browning <rlb@defaultvalue.org> writes:
> 
> > This is what I've done, partly because I'm writing in gtk+ and
> > already have to write getters & setters in C; the burden of writing
> > them in guile was negligible.  Even in C you might find that your
> > library is more robust if you always use functions (they can really
> > be macros...)  to get/set structure members.
> 
> And it makes it easy if you ever need to instrument public access to
> the struct, or add locking, or whatever.

Exactly.  It's not the old days when it was worth the savings to twiddle
data directly.  Except, of course, when it is:-)

It can be pretty ugly and verbose, but even that can be worth it in
terms of run-time error checking &c.:

  TravMapobject* planet;
  ...
  trav_mapobject_set_name(planet, "Earth");
  trav_planet_set_diameter(TRAV_PLANET(planet), 4.3);

rather than:

  TravPlanet* planet;
  ...
  if (planet && planet->name)
    free(planet->name); // hope that it was allocated with malloc...
  (void)strcpy(planet->name, "Earth");
  planet->diameter = 4.3;

which also loses because one must retrieve a planet's name differently
than a galaxy's (the offsets may be different), which can be a pain for
some generic functions.

-- 
Robert Uhl <ruhl@4dv.net>
Come receive the light from the unwaning light,
And glorify Christ Who rose from the dead.


_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2003-04-29  0:41 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-04-22 12:56 exposing C struct contents in Scheme Pascal Haakmat
2003-04-22 14:22 ` Dale P. Smith
2003-04-23 15:59 ` Robert Uhl
2003-04-28 16:14   ` Rob Browning
2003-04-29  0:41     ` Robert Uhl

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).