11 |
that flow from being able to extend the application in a high level |
that flow from being able to extend the application in a high level |
12 |
extension language rather than in plain old C. |
extension language rather than in plain old C. |
13 |
|
|
14 |
Underlying this argument is the assumption that programming in a high |
In abstract terms, it's difficult to explain what this really means and |
15 |
level language, specifically Guile's implementation of Scheme, is |
what the integration process involves, so instead let's begin by jumping |
16 |
necessarily better in some way than programming in C. What do we mean |
straight into an example of how you might integrate Guile into an |
17 |
by this claim, and how can we be so sure? |
existing program, and what you could expect to gain by so doing. With |
18 |
|
that example under our belts, we'll then return to a more general |
19 |
|
analysis of the arguments involved and the range of programming options |
20 |
|
available. |
21 |
|
|
22 |
|
@menu |
23 |
|
* Extending Dia:: How one might extend Dia using Guile. |
24 |
|
* Scheme vs C:: Why Scheme is more hackable than C. |
25 |
|
* Testbed Example:: Example: using Guile in a testbed. |
26 |
|
* Programming Options:: Options for Guile programming. |
27 |
|
* User Programming:: How about application users? |
28 |
|
@end menu |
29 |
|
|
30 |
|
|
31 |
|
@node Extending Dia |
32 |
|
@section How One Might Extend Dia Using Guile |
33 |
|
|
34 |
|
Dia is a free software program for drawing schematic diagrams like flow |
35 |
|
charts and floor plans (REFFIXME). This section conducts the thought |
36 |
|
experiment of adding Guile to Dia. In so doing, it aims to illustrate |
37 |
|
several of the steps and considerations involved in adding Guile to |
38 |
|
applications in general. |
39 |
|
|
40 |
|
@menu |
41 |
|
* Dia Objective:: Deciding why you want to add Guile. |
42 |
|
* Dia Steps:: Four steps required to add Guile. |
43 |
|
* Dia Smobs:: How to represent Dia data in Scheme. |
44 |
|
* Dia Primitives:: Writing Guile primitives for Dia. |
45 |
|
* Dia Hook:: Providing a hook for Scheme evaluation. |
46 |
|
* Dia Structure:: Overall structure for adding Guile. |
47 |
|
* Dia Advanced:: Going further with Dia and Guile. |
48 |
|
@end menu |
49 |
|
|
50 |
|
|
51 |
|
@node Dia Objective |
52 |
|
@subsection Deciding Why You Want to Add Guile |
53 |
|
|
54 |
|
First off, you should understand why you want to add Guile to Dia at |
55 |
|
all, and that means forming a picture of what Dia does and how it does |
56 |
|
it. So, what are the constituents of the Dia application? |
57 |
|
|
58 |
|
@itemize @bullet |
59 |
|
@item |
60 |
|
Most importantly, the @dfn{application domain objects} --- in other |
61 |
|
words, the concepts that differentiate Dia from another application such |
62 |
|
as a word processor or spreadsheet: shapes, templates, connectors, |
63 |
|
pages, plus the properties of all these things. |
64 |
|
|
65 |
|
@item |
66 |
|
The code that manages the graphical face of the application, including |
67 |
|
the layout and display of the objects above. |
68 |
|
|
69 |
|
@item |
70 |
|
The code that handles input events, which indicate that the application |
71 |
|
user is wanting to do something. |
72 |
|
@end itemize |
73 |
|
|
74 |
|
@noindent |
75 |
|
(In other words, a textbook example of the @dfn{model - view - |
76 |
|
controller} paradigm.) |
77 |
|
|
78 |
|
Next question: how will Dia benefit once the Guile integration is |
79 |
|
complete? Several (positive!) answers are possible here, and the choice |
80 |
|
is obviously up to the application developers. Still, one answer is |
81 |
|
that the main benefit will be the ability to manipulate Dia's |
82 |
|
application domain objects from Scheme. |
83 |
|
|
84 |
|
Suppose that Dia made a set of procedures available in Scheme, |
85 |
|
representing the most basic operations on objects such as shapes, |
86 |
|
connectors, and so on. Using Scheme, the application user could then |
87 |
|
write code that builds upon these basic operations to create more |
88 |
|
complex procedures. For example, given basic procedures to enumerate |
89 |
|
the objects on a page, to determine whether an object is a square, and |
90 |
|
to change the fill pattern of a single shape, the user can write a |
91 |
|
Scheme procedure to change the fill pattern of all squares on the |
92 |
|
current page: |
93 |
|
|
94 |
|
@lisp |
95 |
|
(define (change-squares'-fill-pattern new-pattern) |
96 |
|
(for-each-shape current-page |
97 |
|
(lambda (shape) |
98 |
|
(if (square? shape) |
99 |
|
(change-fill-pattern shape new-pattern))))) |
100 |
|
@end lisp |
101 |
|
|
102 |
|
|
103 |
|
@node Dia Steps |
104 |
|
@subsection Four Steps Required to Add Guile |
105 |
|
|
106 |
|
Assuming this objective, four steps are needed to achieve it. |
107 |
|
|
108 |
|
First, you need a way of representing your application-specific objects |
109 |
|
--- such as @code{shape} in the previous example --- when they are |
110 |
|
passed into the Scheme world. Unless your objects are so simple that |
111 |
|
they map naturally into builtin Scheme data types like numbers and |
112 |
|
strings, you will probably want to use Guile's @dfn{SMOB} interface to |
113 |
|
create a new Scheme data type for your objects. |
114 |
|
|
115 |
|
Second, you need to write code for the basic operations like |
116 |
|
@code{for-each-shape} and @code{square?} such that they access and |
117 |
|
manipulate your existing data structures correctly, and then make these |
118 |
|
operations available as @dfn{primitives} on the Scheme level. |
119 |
|
|
120 |
|
Third, you need to provide some mechanism within the Dia application |
121 |
|
that a user can hook into to cause arbitrary Scheme code to be |
122 |
|
evaluated. |
123 |
|
|
124 |
|
Finally, you need to restructure your top-level application C code a |
125 |
|
little so that it initializes the Guile interpreter correctly and |
126 |
|
declares your @dfn{SMOBs} and @dfn{primitives} to the Scheme world. |
127 |
|
|
128 |
|
The following subsections expand on these four points in turn. |
129 |
|
|
130 |
|
|
131 |
|
@node Dia Smobs |
132 |
|
@subsection How to Represent Dia Data in Scheme |
133 |
|
|
134 |
|
For all but the most trivial applications, you will probably want to |
135 |
|
allow some representation of your domain objects to exist on the Scheme |
136 |
|
level. This is where the idea of SMOBs comes in, and with it issues of |
137 |
|
lifetime management and garbage collection. |
138 |
|
|
139 |
|
To get more concrete about this, let's look again at the example we gave |
140 |
|
earlier of how application users can use Guile to build higher-level |
141 |
|
functions from the primitives that Dia itself provides. |
142 |
|
|
143 |
|
@lisp |
144 |
|
(define (change-squares'-fill-pattern new-pattern) |
145 |
|
(for-each-shape current-page |
146 |
|
(lambda (shape) |
147 |
|
(if (square? shape) |
148 |
|
(change-fill-pattern shape new-pattern))))) |
149 |
|
@end lisp |
150 |
|
|
151 |
|
Consider what is stored here in the variable @code{shape}. For each |
152 |
|
shape on the current page, the @code{for-each-shape} primitive calls |
153 |
|
@code{(lambda (shape) @dots{})} with an argument representing that |
154 |
|
shape. Question is: how is that argument represented on the Scheme |
155 |
|
level? The issues are as follows. |
156 |
|
|
157 |
|
@itemize @bullet |
158 |
|
@item |
159 |
|
Whatever the representation, it has to be decodable again by the C code |
160 |
|
for the @code{square?} and @code{change-fill-pattern} primitives. In |
161 |
|
other words, a primitive like @code{square?} has somehow to be able to |
162 |
|
turn the value that it receives back into something that points to the |
163 |
|
underlying C structure describing a shape. |
164 |
|
|
165 |
|
@item |
166 |
|
The representation must also cope with Scheme code holding on to the |
167 |
|
value for later use. What happens if the Scheme code stores |
168 |
|
@code{shape} in a global variable, but then that shape is deleted (in a |
169 |
|
way that the Scheme code is not aware of), and later on some other |
170 |
|
Scheme code uses that global variable again in a call to, say, |
171 |
|
@code{square?}? |
172 |
|
|
173 |
|
@item |
174 |
|
The lifetime and memory allocation of objects that exist @emph{only} in |
175 |
|
the Scheme world is managed automatically by Guile's garbage collector |
176 |
|
using one simple rule: when there are no remaining references to an |
177 |
|
object, the object is considered dead and so its memory is freed. But |
178 |
|
for objects that exist in both C and Scheme, the picture is more |
179 |
|
complicated; in the case of Dia, where the @code{shape} argument passes |
180 |
|
transiently in and out of the Scheme world, it would be quite wrong the |
181 |
|
@strong{delete} the underlying C shape just because the Scheme code has |
182 |
|
finished evaluation. How do we avoid this happening? |
183 |
|
@end itemize |
184 |
|
|
185 |
|
One resolution of these issues is for the Scheme-level representation of |
186 |
|
a shape to be a new, Scheme-specific C structure wrapped up as a SMOB. |
187 |
|
The SMOB is what is passed into and out of Scheme code, and the |
188 |
|
Scheme-specific C structure inside the SMOB points to Dia's underlying C |
189 |
|
structure so that the code for primitives like @code{square?} can get at |
190 |
|
it. |
191 |
|
|
192 |
|
To cope with an underlying shape being deleted while Scheme code is |
193 |
|
still holding onto a Scheme shape value, the underlying C structure |
194 |
|
should have a new field that points to the Scheme-specific SMOB. When a |
195 |
|
shape is deleted, the relevant code chains through to the |
196 |
|
Scheme-specific structure and sets its pointer back to the underlying |
197 |
|
structure to NULL. Thus the SMOB value for the shape continues to |
198 |
|
exist, but any primitive code that tries to use it will detect that the |
199 |
|
underlying shape has been deleted because the underlying structure |
200 |
|
pointer is NULL. |
201 |
|
|
202 |
|
So, to summarize the steps involved in this resolution of the problem |
203 |
|
(and assuming that the underlying C structure for a shape is |
204 |
|
@code{struct dia_shape}): |
205 |
|
|
206 |
|
@itemize @bullet |
207 |
|
@item |
208 |
|
Define a new Scheme-specific structure that @emph{points} to the |
209 |
|
underlying C structure: |
210 |
|
|
211 |
|
@lisp |
212 |
|
struct dia_guile_shape |
213 |
|
@{ |
214 |
|
struct dia_shape * c_shape; /* NULL => deleted */ |
215 |
|
@} |
216 |
|
@end lisp |
217 |
|
|
218 |
|
@item |
219 |
|
Add a field to @code{struct dia_shape} that points to its @code{struct |
220 |
|
dia_guile_shape} if it has one --- |
221 |
|
|
222 |
|
@lisp |
223 |
|
struct dia_shape |
224 |
|
@{ |
225 |
|
@dots{} |
226 |
|
struct dia_guile_shape * guile_shape; |
227 |
|
@} |
228 |
|
@end lisp |
229 |
|
|
230 |
|
@noindent |
231 |
|
--- so that C code can set @code{guile_shape->c_shape} to NULL when the |
232 |
|
underlying shape is deleted. |
233 |
|
|
234 |
|
@item |
235 |
|
Wrap @code{struct dia_guile_shape} as a SMOB type. |
236 |
|
|
237 |
|
@item |
238 |
|
Whenever you need to represent a C shape onto the Scheme level, create a |
239 |
|
SMOB instance for it, and pass that. |
240 |
|
|
241 |
|
@item |
242 |
|
In primitive code that receives a shape SMOB instance, check the |
243 |
|
@code{c_shape} field when decoding it, to find out whether the |
244 |
|
underlying C shape is still there. |
245 |
|
@end itemize |
246 |
|
|
247 |
|
As far as memory management is concerned, the SMOB values and their |
248 |
|
Scheme-specific structures are under the control of the garbage |
249 |
|
collector, whereas the underlying C structures are explicitly managed in |
250 |
|
exactly the same way that Dia managed them before we thought of adding |
251 |
|
Guile. |
252 |
|
|
253 |
|
When the garbage collector decides to free a shape SMOB value, it calls |
254 |
|
the @dfn{SMOB free} function that was specified when defining the shape |
255 |
|
SMOB type. To maintain the correctness of the @code{guile_shape} field |
256 |
|
in the underlying C structure, this function should chain through to the |
257 |
|
underlying C structure (if it still exists) and set its |
258 |
|
@code{guile_shape} field to NULL. |
259 |
|
|
260 |
|
For full documentation on defining and using SMOB types, see |
261 |
|
@ref{Defining New Types (Smobs)}. |
262 |
|
|
263 |
|
|
264 |
|
@node Dia Primitives |
265 |
|
@subsection Writing Guile Primitives for Dia |
266 |
|
|
267 |
|
Once the details of object representation are decided, writing the |
268 |
|
primitive function code that you need is usually straightforward. |
269 |
|
|
270 |
|
A primitive is simply a C function whose arguments and return value are |
271 |
|
all of type @code{SCM}, and whose body does whatever you want it to do. |
272 |
|
As an example, here is a possible implementation of the @code{square?} |
273 |
|
primitive: |
274 |
|
|
275 |
|
@lisp |
276 |
|
#define FUNC_NAME "square?" |
277 |
|
static SCM square_p (SCM shape) |
278 |
|
@{ |
279 |
|
struct dia_guile_shape * guile_shape; |
280 |
|
|
281 |
|
/* Check that arg is really a shape SMOB. */ |
282 |
|
SCM_VALIDATE_SHAPE (SCM_ARG1, shape); |
283 |
|
|
284 |
|
/* Access Scheme-specific shape structure. */ |
285 |
|
guile_shape = SCM_SMOB_DATA (shape); |
286 |
|
|
287 |
|
/* Find out if underlying shape exists and is a |
288 |
|
square; return answer as a Scheme boolean. */ |
289 |
|
return SCM_BOOL (guile_shape->c_shape && |
290 |
|
(guile_shape->c_shape->type == DIA_SQUARE)); |
291 |
|
@} |
292 |
|
#undef FUNC_NAME |
293 |
|
@end lisp |
294 |
|
|
295 |
|
Notice how easy it is to chain through from the @code{SCM shape} |
296 |
|
parameter that @code{square_p} receives --- which is a SMOB --- to the |
297 |
|
Scheme-specific structure inside the SMOB, and thence to the underlying |
298 |
|
C structure for the shape. |
299 |
|
|
300 |
|
In this code, @code{SCM_SMOB_DATA} and @code{SCM_BOOL} are macros from |
301 |
|
the standard Guile API. @code{SCM_VALIDATE_SHAPE} is a macro that you |
302 |
|
should define as part of your SMOB definition: it checks that the passed |
303 |
|
parameter is of the expected type. This is needed to guard against |
304 |
|
Scheme code using the @code{square?} procedure incorrectly, as in |
305 |
|
@code{(square? "hello")}; Scheme's latent typing means that usage errors |
306 |
|
like this must be caught at run time. |
307 |
|
|
308 |
|
Having written the C code for your primitives, you need to make them |
309 |
|
available as Scheme procedures by calling the @code{scm_c_define_gsubr} |
310 |
|
function. @code{scm_c_define_gsubr} (REFFIXME) takes arguments that |
311 |
|
specify the Scheme-level name for the primitive and how many required, |
312 |
|
optional and rest arguments it can accept. The @code{square?} primitive |
313 |
|
always requires exactly one argument, so the call to make it available |
314 |
|
in Scheme reads like this: |
315 |
|
|
316 |
|
@lisp |
317 |
|
scm_c_define_gsubr ("square?", 1, 0, 0, square_p); |
318 |
|
@end lisp |
319 |
|
|
320 |
|
For where to put this call, see the subsection after next on the |
321 |
|
structure of Guile-enabled code (@pxref{Dia Structure}). |
322 |
|
|
323 |
|
|
324 |
|
@node Dia Hook |
325 |
|
@subsection Providing a Hook for the Evaluation of Scheme Code |
326 |
|
|
327 |
|
To make the Guile integration useful, you have to design some kind of |
328 |
|
hook into your application that application users can use to cause their |
329 |
|
Scheme code to be evaluated. |
330 |
|
|
331 |
|
Technically, this is straightforward; you just have to decide on a |
332 |
|
mechanism that is appropriate for your application. Think of Emacs, for |
333 |
|
example: when you type @kbd{@key{ESC} :}, you get a prompt where you can |
334 |
|
type in any Elisp code, which Emacs will then evaluate. Or, again like |
335 |
|
Emacs, you could provide a mechanism (such as an init file) to allow |
336 |
|
Scheme code to be associated with a particular key sequence, and |
337 |
|
evaluate the code when that key sequence is entered. |
338 |
|
|
339 |
|
In either case, once you have the Scheme code that you want to evaluate, |
340 |
|
as a null terminated string, you can tell Guile to evaluate it by |
341 |
|
calling the @code{scm_c_eval_string} function. |
342 |
|
|
343 |
|
|
344 |
|
@node Dia Structure |
345 |
|
@subsection Top-level Structure of Guile-enabled Dia |
346 |
|
|
347 |
|
Let's assume that the pre-Guile Dia code looks structurally like this: |
348 |
|
|
349 |
|
@itemize @bullet |
350 |
|
@item |
351 |
|
@code{main ()} |
352 |
|
|
353 |
|
@itemize @bullet |
354 |
|
@item |
355 |
|
do lots of initialization and setup stuff |
356 |
|
@item |
357 |
|
enter Gtk main loop |
358 |
|
@end itemize |
359 |
|
@end itemize |
360 |
|
|
361 |
|
When you add Guile to a program, one (rather technical) requirement is |
362 |
|
that Guile's garbage collector needs to know where the bottom of the C |
363 |
|
stack is. The easiest way to ensure this is to use |
364 |
|
@code{scm_boot_guile} like this: |
365 |
|
|
366 |
|
@itemize @bullet |
367 |
|
@item |
368 |
|
@code{main ()} |
369 |
|
|
370 |
|
@itemize @bullet |
371 |
|
@item |
372 |
|
do lots of initialization and setup stuff |
373 |
|
@item |
374 |
|
@code{scm_boot_guile (argc, argv, inner_main, NULL)} |
375 |
|
@end itemize |
376 |
|
|
377 |
|
@item |
378 |
|
@code{inner_main ()} |
379 |
|
|
380 |
|
@itemize @bullet |
381 |
|
@item |
382 |
|
define all SMOB types |
383 |
|
@item |
384 |
|
export primitives to Scheme using @code{scm_c_define_gsubr} |
385 |
|
@item |
386 |
|
enter Gtk main loop |
387 |
|
@end itemize |
388 |
|
@end itemize |
389 |
|
|
390 |
|
In other words, you move the guts of what was previously in your |
391 |
|
@code{main} function into a new function called @code{inner_main}, and |
392 |
|
then add a @code{scm_boot_guile} call, with @code{inner_main} as a |
393 |
|
parameter, to the end of @code{main}. |
394 |
|
|
395 |
|
Assuming that you are using SMOBs and have written primitive code as |
396 |
|
described in the preceding subsections, you also need to insert calls to |
397 |
|
declare your new SMOBs and export the primitives to Scheme. These |
398 |
|
declarations must happen @emph{inside} the dynamic scope of the |
399 |
|
@code{scm_boot_guile} call, but also @emph{before} any code is run that |
400 |
|
could possibly use them --- the beginning of @code{inner_main} is an |
401 |
|
ideal place for this. |
402 |
|
|
403 |
|
|
404 |
|
@node Dia Advanced |
405 |
|
@subsection Going Further with Dia and Guile |
406 |
|
|
407 |
|
The steps described so far implement an initial Guile integration that |
408 |
|
already gives a lot of additional power to Dia application users. But |
409 |
|
there are further steps that you could take, and it's interesting to |
410 |
|
consider a few of these. |
411 |
|
|
412 |
|
In general, you could progressively move more of Dia's source code from |
413 |
|
C into Scheme. This might make the code more maintainable and |
414 |
|
extensible, and it could open the door to new programming paradigms that |
415 |
|
are tricky to effect in C but straightforward in Scheme. |
416 |
|
|
417 |
|
A specific example of this is that you could use the guile-gtk package, |
418 |
|
which provides Scheme-level procedures for most of the Gtk+ library, to |
419 |
|
move the code that lays out and displays Dia objects from C to Scheme. |
420 |
|
|
421 |
|
As you follow this path, it naturally becomes less useful to maintain a |
422 |
|
distinction between Dia's original non-Guile-related source code, and |
423 |
|
its later code implementing SMOBs and primitives for the Scheme world. |
424 |
|
|
425 |
|
For example, suppose that the original source code had a |
426 |
|
@code{dia_change_fill_pattern} function: |
427 |
|
|
428 |
|
@lisp |
429 |
|
void dia_change_fill_pattern (struct dia_shape * shape, |
430 |
|
struct dia_pattern * pattern) |
431 |
|
@{ |
432 |
|
/* real pattern change work */ |
433 |
|
@} |
434 |
|
@end lisp |
435 |
|
|
436 |
|
During initial Guile integration, you add a @code{change_fill_pattern} |
437 |
|
primitive for Scheme purposes, which accesses the underlying structures |
438 |
|
from its SMOB values and uses @code{dia_change_fill_pattern} to do the |
439 |
|
real work: |
440 |
|
|
441 |
|
@lisp |
442 |
|
SCM change_fill_pattern (SCM shape, SCM pattern) |
443 |
|
@{ |
444 |
|
struct dia_shape * d_shape; |
445 |
|
struct dia_pattern * d_pattern; |
446 |
|
|
447 |
|
@dots{} |
448 |
|
|
449 |
|
dia_change_fill_pattern (d_shape, d_pattern); |
450 |
|
|
451 |
|
return SCM_UNSPECIFIED; |
452 |
|
@} |
453 |
|
@end lisp |
454 |
|
|
455 |
|
At this point, it makes sense to keep @code{dia_change_fill_pattern} and |
456 |
|
@code{change_fill_pattern} separate, because |
457 |
|
@code{dia_change_fill_pattern} can also be called without going through |
458 |
|
Scheme at all, say because the user clicks a button which causes a |
459 |
|
C-registered Gtk+ callback to be called. |
460 |
|
|
461 |
|
But, if the code for creating buttons and registering their callbacks is |
462 |
|
moved into Scheme (using guile-gtk), it may become true that |
463 |
|
@code{dia_change_fill_pattern} can no longer be called other than |
464 |
|
through Scheme. In which case, it makes sense to abolish it and move |
465 |
|
its contents directly into @code{change_fill_pattern}, like this: |
466 |
|
|
467 |
|
@lisp |
468 |
|
SCM change_fill_pattern (SCM shape, SCM pattern) |
469 |
|
@{ |
470 |
|
struct dia_shape * d_shape; |
471 |
|
struct dia_pattern * d_pattern; |
472 |
|
|
473 |
|
@dots{} |
474 |
|
|
475 |
|
/* real pattern change work */ |
476 |
|
|
477 |
|
return SCM_UNSPECIFIED; |
478 |
|
@} |
479 |
|
@end lisp |
480 |
|
|
481 |
|
So further Guile integration progressively @emph{reduces} the amount of |
482 |
|
functional C code that you have to maintain over the long term. |
483 |
|
|
484 |
|
A similar argument applies to data representation. In the discussion of |
485 |
|
SMOBs earlier, issues arose because of the different memory management |
486 |
|
and lifetime models that normally apply to data structures in C and in |
487 |
|
Scheme. However, with further Guile integration, you can resolve this |
488 |
|
issue in a more radical way by allowing all your data structures to be |
489 |
|
under the control of the garbage collector, and kept alive by references |
490 |
|
from the Scheme world. Instead of maintaining an array or linked list |
491 |
|
of shapes in C, you would instead maintain a list in Scheme. |
492 |
|
|
493 |
|
Rather like the coalescing of @code{dia_change_fill_pattern} and |
494 |
|
@code{change_fill_pattern}, the practical upshot of such a change is |
495 |
|
that you would no longer have to keep the @code{dia_shape} and |
496 |
|
@code{dia_guile_shape} structures separate, and so wouldn't need to |
497 |
|
worry about the pointers between them. Instead, you could change the |
498 |
|
SMOB definition to wrap the @code{dia_shape} structure directly, and |
499 |
|
send @code{dia_guile_shape} off to the scrap yard. Cut out the middle |
500 |
|
man! |
501 |
|
|
502 |
|
Finally, we come to the holy grail of Guile's free software / extension |
503 |
|
language approach. Once you have a Scheme representation for |
504 |
|
interesting Dia data types like shapes, and a handy bunch of primitives |
505 |
|
for manipulating them, it suddenly becomes clear that you have a bundle |
506 |
|
of functionality that could have far-ranging use beyond Dia itself. In |
507 |
|
other words, the data types and primitives could now become a library, |
508 |
|
and Dia becomes just one of the many possible applications using that |
509 |
|
library --- albeit, at this early stage, a rather important one! |
510 |
|
|
511 |
|
In this model, Guile becomes just the glue that binds everything |
512 |
|
together. Imagine an application that usefully combined functionality |
513 |
|
from Dia, Gnumeric and GnuCash --- it's tricky right now, because no |
514 |
|
such application yet exists; but it'll happen some day @dots{} |
515 |
|
|
516 |
|
|
517 |
|
@node Scheme vs C |
518 |
|
@section Why Scheme is More Hackable Than C |
519 |
|
|
520 |
|
Underlying Guile's value proposition is the assumption that programming |
521 |
|
in a high level language, specifically Guile's implementation of Scheme, |
522 |
|
is necessarily better in some way than programming in C. What do we |
523 |
|
mean by this claim, and how can we be so sure? |
524 |
|
|
525 |
One class of advantages applies not only to Scheme, but more generally |
One class of advantages applies not only to Scheme, but more generally |
526 |
to any interpretable, high level, scripting language, such as Emacs |
to any interpretable, high level, scripting language, such as Emacs |
542 |
handling that make common programming tasks easier. |
handling that make common programming tasks easier. |
543 |
@end itemize |
@end itemize |
544 |
|
|
545 |
In the case of Scheme, further features that make programming easier --- |
In the case of Scheme, particular features that make programming easier |
546 |
and more fun! --- are its powerful mechanisms for abstracting parts of |
--- and more fun! --- are its powerful mechanisms for abstracting parts |
547 |
programs (closures --- @pxref{About Closure}) and for iteration |
of programs (closures --- @pxref{About Closure}) and for iteration |
548 |
(@pxref{while do}). |
(@pxref{while do}). |
549 |
|
|
550 |
The evidence in support of this argument is empirical: the huge amount |
The evidence in support of this argument is empirical: the huge amount |
557 |
functionality could have been added to these applications just by |
functionality could have been added to these applications just by |
558 |
writing new code in their base implementation languages. |
writing new code in their base implementation languages. |
559 |
|
|
|
@menu |
|
|
* Testbed Example:: Example: using Guile in a testbed. |
|
|
* Programming Options:: Options for Guile programming. |
|
|
* User Programming:: How about application users? |
|
|
@end menu |
|
|
|
|
560 |
|
|
561 |
@node Testbed Example |
@node Testbed Example |
562 |
@section Example: Using Guile for an Application Testbed |
@section Example: Using Guile for an Application Testbed |