;
; Расширения Script-Fu
;
; Возвращает список файлов из dir
; Пример: (hl-file-list "/tmp")
(define (hl-file-list dir)
(cadr (file-glob (string-append dir "/*") 0)))
; Загрузить файл jpg
; Пример: (hl-jpeg-load "/tmp/butt/video1.jpg")
; Возвращает: image
(define (hl-jpeg-load filename)
(car (file-jpeg-load RUN-NONINTERACTIVE filename filename)))
; Склеить вертикально два одинаковых по размеру файла jpg в один
(define (hl-jpeg-vcombine file1 file2 file3)
(let* (
(img1 (hl-jpeg-load file1))
(img2 (hl-jpeg-load file2))
(h-height (car (gimp-image-height img1)))
(f-width (car (gimp-image-width img1)))
; Создадим "подложку"
(img (car (gimp-image-new f-width (* h-height 2) RGB)))
; Обозначим локальные переменные
(dra) (dra-copy))
; Снимем копию дравабле первого файла и добавим её
; в верхнюю часть подложки
(set! dra-copy (car (gimp-image-get-active-layer img1)))
(set! dra-copy (car (gimp-layer-new-from-drawable dra-copy img)))
(gimp-image-add-layer img dra-copy -1)
; Добавим копию второго имаге вниз подложки
(set! dra-copy (car (gimp-image-get-active-layer img2)))
(set! dra-copy (car (gimp-layer-new-from-drawable dra-copy img)))
(gimp-image-add-layer img dra-copy -1)
(gimp-layer-set-offsets dra-copy 0 h-height)
; Сохраним изображение в file3
(set! dra (car (gimp-image-merge-visible-layers img 0)))
(file-png-save 1 img dra file3 file3 0 9 0 0 0 1 1)
; Подчистим за собой мусор
(hl-delete-images (list img img1 img2))))
; Удаляет загруженные изображения из памяти
(define (hl-delete-images image-list)
(map (lambda (x) (gimp-image-delete x)) image-list))
; Уменьшить размеры jpg. new-len: новая длина стороны
; flag: "w" или "h", смотря по какой стороне ориентироваться с размерами
(define (hl-resize-jpg file-in file-out new-len flag)
(let* (
(img (car (file-jpeg-load 1 file-in file-in)))
(dra (car (gimp-image-get-active-layer img)))
(old-h (car (gimp-image-height img)))
(old-w (car (gimp-image-width img)))
(new-h) (new-w))
; Вычислим новые размеры картинки
(if (string=? flag "w")
(begin
(set! new-w new-len)
(set! new-h (* old-h (/ new-w old-w))))
(begin
(set! new-h new-len)
(set! new-w (* old-w (/ new-h old-h)))))
; Изменим размеры jpg
(gimp-drawable-transform-scale dra 0 0 new-w new-h 0 3 FALSE 3 2)
(gimp-image-crop img new-w new-h 0 0)
; Сохраним картинку
(file-jpeg-save 1 img dra file-out file-out .95 0 0 0 " " 0 1 0 1)
; Очистим мусор
(gimp-image-delete img)))
; Создать картинку размерами x y
(define (hl-make-image x y)
(let* (
(img (car (gimp-image-new x y RGB)))
(dra (car (gimp-layer-new img x y RGB-IMAGE "Background" 100 NORMAL-MODE))))
(gimp-image-add-layer img dra -1)
(gimp-edit-clear dra)
(list img dra)))
; Выбрать область с закруглёнными краями
(define (hl-select-round img x y ox oy)
(gimp-rect-select img x y ox oy REPLACE FALSE 0)
(script-fu-selection-rounded-rectangle img FALSE 50 FALSE))
;
; Расширения TinyScheme
;
; Отрезает последние num символов от строки
(define (chop str num)
(substring str 0 (- (string-length str) num)))
; Проверяет, принадлежит ли значение списку
; Пример: (in-list? 3 '(1 2 3 4 5 6))
(define (in-list? itm lst)
(let* (
(found 0))
(for-each (lambda (x)
(if ((if (string? x) string=? =) x itm) (set! found (+ found 1))))
lst)
(if (> found 0) #t #f)))
; Возвращает уникальные значения списка
(define (unique lst)
(let* (
(out-list '()))
(for-each (lambda (x)
(if (in-list? x out-list) #f (set! out-list (append out-list (list x)))))
lst)
out-list))
; Вырезать имя файла из полного пути
; (hl-filename "/tmp/test.jpg") -> "test.jpg"
(define (hl-filename path)
(let* (
(f-len (string-length path))
(s-len 1))
(while (and
(<= s-len f-len)
(not (re-match "/" (substring path (- f-len s-len)))))
(set! s-len (+ s-len 1)))
(substring path (+ (- f-len s-len) 1))))
;
; Рабочие процедуры
;
; Загрузить кучу кнопок вида "test1.jpg" и "test2.jpg", изменить их
; размер до 54 по вертикали, склеить их попарно в файлы для rollover
; кнопок на сайте.
(define (hl-resize-buttons)
(let* (
(in-dir "/home/oleg/gimp/indir")
(out-dir "/home/oleg/gimp/outdir")
; В button-list лежит список файлов типа '("test", "about", "home")
(button-list (unique (map hl-filename (map
(lambda (x) (chop x 5)) (hl-file-list in-dir))))))
(for-each (lambda (x)
; Делаем ресайз кнопок
(hl-resize-jpg (string-append in-dir "/" x "1.jpg")
(string-append out-dir "/" x "1.jpg") 54 "h")
(hl-resize-jpg (string-append in-dir "/" x "2.jpg")
(string-append out-dir "/" x "2.jpg") 54 "h")
(hl-jpeg-vcombine
(string-append out-dir "/" x "1.jpg")
(string-append out-dir "/" x "2.jpg")
(string-append out-dir "/" x ".png")))
button-list)))
; Сделать кнопку в стиле веб-два-ноль с заданным текстом
; (hl-button "Нажмите здесь!" "Courier" "sample.png" '(224 224 255) '(80 80 255) '(255 255 255))
; Цвета (1-2-3): фон, цвет кнопки, цвет текста
(define (hl-button text font name color-1 color-2 color-3)
(let* (
(tx (car (gimp-text-get-extents-fontname text 26 0 font)))
(ty (cadr (gimp-text-get-extents-fontname text 26 0 font)))
(image (nl-make-image (+ tx 44) 44)))
; Очищаем фон, ставим бэкграунд
(gimp-context-set-foreground color-1)
(gimp-edit-fill (cadr image) 0)
(gimp-context-set-background color-1)
; Заполняем большой прямоугольник
(hl-select-round (car image) 4 4 (+ tx 30) ty)
(gimp-context-set-foreground color-2)
(gimp-edit-fill (cadr image) 0)
; Отбрасываем тень
(script-fu-drop-shadow (car image) (cadr image) 4 4 6 color-2 80 0)
; Заполняем малый прямоугольник градиентом
(hl-select-round (car image) 6 6 (+ tx 26) (- ty 12))
(gimp-blend (cadr image) FG-BG-RGB-MODE NORMAL-MODE GRADIENT-LINEAR
100 0 REPEAT-NONE FALSE FALSE 0 0 FALSE 0 (- ty 12) 0 -26)
; Добавляем текст
(gimp-context-set-foreground color-3)
(gimp-text-fontname (car image) (cadr image) 19 4 text 0 TRUE 26 1 font)
; Сохраняем файл
(gimp-image-merge-visible-layers (car image) 0)
(file-png-save 1
(car image)
(car (gimp-image-get-active-layer (car image)))
name
name
0 9 0 0 0 1 1)
; Удаляем изображение из памяти
(gimp-image-delete (car image))))
; Нарисовать карандаш 24х24 пиксела
; Работаем с векторами и кривыми Безье. Сделав всё в
; векторном виде, закрашиваем и изменяем размер с 240х240 до 24х24
; Получается а-ля-иконка
(define (hl-pencil)
(let* (
(img (hl-make-image 240 240))
(image (car img))
(layer (cadr img))
(pbody 0)
(stro 0)
(nose 0))
; Очищаем фон
(gimp-context-set-foreground '(244 244 255))
(gimp-edit-fill layer 0)
; Задаём цвет карандаша
(gimp-context-set-foreground '(0 0 255))
; Новые вектора
(set! pbody (car (gimp-vectors-new image "pencil")))
(gimp-image-add-vectors image pbody -1)
; Рисуем туловище карандаша
(set! stro (car (gimp-vectors-bezier-stroke-new-moveto pbody 180 20)))
(gimp-vectors-bezier-stroke-lineto pbody stro 70 130)
(gimp-vectors-bezier-stroke-conicto pbody stro 105 135 110 170)
(gimp-vectors-bezier-stroke-lineto pbody stro 220 60)
(gimp-vectors-bezier-stroke-conicto pbody stro 215 25 180 20)
; Закрашиваем туловище
(gimp-vectors-to-selection pbody 0 TRUE FALSE 0 0)
(gimp-blend layer FG-BG-RGB-MODE NORMAL-MODE GRADIENT-LINEAR
100 0 REPEAT-NONE FALSE FALSE 0 0 FALSE 125 75 240 240)
(gimp-selection-none image)
; Рисуем носик карандаша
(set! nose (car (gimp-vectors-new image "pencil")))
(gimp-image-add-vectors image nose -1)
(set! stro (car (gimp-vectors-bezier-stroke-new-moveto nose 70 130)))
(gimp-vectors-bezier-stroke-lineto nose stro 20 220)
(gimp-vectors-bezier-stroke-lineto nose stro 110 170)
(gimp-vectors-bezier-stroke-conicto nose stro 105 135 70 130)
; Закрашиваем носик
(gimp-vectors-to-selection nose 0 TRUE FALSE 0 0)
(gimp-blend layer FG-BG-RGB-MODE NORMAL-MODE GRADIENT-LINEAR
100 0 REPEAT-NONE FALSE FALSE 0 0 FALSE -30 30 170 230)
(gimp-selection-none image)
; Изменяем размер
(gimp-image-scale image 24 24)
(gimp-display-new image)))
;
; Отладочные участки
;
; Показываем изображение
; (gimp-display-new img)
; Список шрифтов (можно напамить на него hl-button)
; (gimp-fonts-get-list "")
; Отштриховываем вектора
; (gimp-context-set-brush "Circle (03)")
; (gimp-context-set-foreground '(0 0 255))
; (gimp-edit-stroke-vectors layer nose)
Показаны сообщения с ярлыком Script-Fu. Показать все сообщения
Показаны сообщения с ярлыком Script-Fu. Показать все сообщения
пятница, 19 марта 2010 г.
Script-Fu: resize, combine, vectors, regexp
Текущая библиотека разных моих мелких функций на Скрипт-Фу. Очень жаль, что Блогспот не даёт прикладывать файлы в виде файлов целиком.
четверг, 18 марта 2010 г.
Команды/константы Script-Fu
Более-менее полный список команд найти несложно, если погуглить что-нибудь типа "file-bmp-load" "file-bz2-load".
Ещё несколько забавных команд лежит в файле .gimprc (не пользовательском, а в основном, в /etc).
Польза от все этого непотребства, впрочем, сомнительна.
Единственное, что я пока нашёл ценного, две константы:
RUN-INTERACTIVE (0)
RUN-NONINTERACTIVE (1)
Кое-что любопытное (скрипт массовой обработки фотографий):
http://svvord.livejournal.com/882.html
Надо бы, наверное, сказать тому товарищу, что вместо (define) лучше назначать переменные через let*...
Ещё несколько забавных команд лежит в файле .gimprc (не пользовательском, а в основном, в /etc).
Польза от все этого непотребства, впрочем, сомнительна.
Единственное, что я пока нашёл ценного, две константы:
RUN-INTERACTIVE (0)
RUN-NONINTERACTIVE (1)
Кое-что любопытное (скрипт массовой обработки фотографий):
http://svvord.livejournal.com/882.html
Надо бы, наверное, сказать тому товарищу, что вместо (define) лучше назначать переменные через let*...
dir или ls в Script-Fu
Сбылась мечта бесчисленных поколений. Я разобрался как делать "ls" в Script-Fu.
Второй параметр у file-glob -- кодировка возвращаемых имён. В Windows, вроде как, ни на что не влияет.
> (file-glob "c:\\tmp\\Тест\\*" 0)
(7 ("c:\\tmp\\Тест\\test.bmp" "c:\\tmp\\Тест\\test.dds" "c:\\tmp\\Тест\\test.png" "c:\\tmp\\Тест\\test1.bmp" "c:\\tmp\\Тест\\test1.gif" "c:\\tmp\\Тест\\test2.bmp" "c:\\tmp\\Тест\\tmp.sql"))
> (nth 2 (cadr (file-glob "c:\\tmp\\Тест\\*" 0)))
"c:\\tmp\\Тест\\test.png"
> (file-glob "c:\\tmp\\Тест\\*.bmp" 0)
(3 ("c:\\tmp\\Тест\\test.bmp" "c:\\tmp\\Тест\\test1.bmp" "c:\\tmp\\Тест\\test2.bmp"))
Второй параметр у file-glob -- кодировка возвращаемых имён. В Windows, вроде как, ни на что не влияет.
TinyScheme Manual
Взят из исходников GIMP 2.67
TinySCHEME Version 1.38
"Safe if used as prescribed"
-- Philip K. Dick, "Ubik"
This software is open source, covered by a BSD-style license.
Please read accompanying file COPYING.
-------------------------------------------------------------------------------
This Scheme interpreter is based on MiniSCHEME version 0.85k4
(see miniscm.tar.gz in the Scheme Repository)
Original credits in file MiniSCHEMETribute.txt.
D. Souflis (dsouflis@acm.org)
-------------------------------------------------------------------------------
What is TinyScheme?
-------------------
TinyScheme is a lightweight Scheme interpreter that implements as large
a subset of R5RS as was possible without getting very large and
complicated. It is meant to be used as an embedded scripting interpreter
for other programs. As such, it does not offer IDEs or extensive toolkits
although it does sport a small top-level loop, included conditionally.
A lot of functionality in TinyScheme is included conditionally, to allow
developers freedom in balancing features and footprint.
As an embedded interpreter, it allows multiple interpreter states to
coexist in the same program, without any interference between them.
Programmatically, foreign functions in C can be added and values
can be defined in the Scheme environment. Being a quite small program,
it is easy to comprehend, get to grips with, and use.
Known bugs
----------
TinyScheme is known to misbehave when memory is exhausted.
Things that keep missing, or that need fixing
---------------------------------------------
There are no hygienic macros. No rational or
complex numbers. No unwind-protect and call-with-values.
Maybe (a subset of) SLIB will work with TinySCHEME...
Decent debugging facilities are missing. Only tracing is supported
natively.
Scheme Reference
----------------
If something seems to be missing, please refer to the code and
"init.scm", since some are library functions. Refer to the MiniSCHEME
readme as a last resort.
Environments
(interaction-environment)
See R5RS. In TinySCHEME, immutable list of association lists.
(current-environment)
The environment in effect at the time of the call. An example of its
use and its utility can be found in the sample code that implements
packages in "init.scm":
(macro (package form)
`(apply (lambda ()
,@(cdr form)
(current-environment))))
The environment containing the (local) definitions inside the closure
is returned as an immutable value.
(defined? <symbol>) (defined? <symbol> <environment>)
Checks whether the given symbol is defined in the current (or given)
environment.
Symbols
(gensym)
Returns a new interned symbol each time. Will probably move to the
library when string->symbol is implemented.
Directives
(gc)
Performs garbage collection immediatelly.
(gcverbose) (gcverbose <bool>)
The argument (defaulting to #t) controls whether GC produces
visible outcome.
(quit) (quit <num>)
Stops the interpreter and sets the 'retcode' internal field (defaults
to 0). When standalone, 'retcode' is returned as exit code to the OS.
(tracing <num>)
1, turns on tracing. 0 turns it off. (Only when USE_TRACING is 1).
Mathematical functions
Since rationals and complexes are absent, the respective functions
are also missing.
Supported: exp, log, sin, cos, tan, asin, acos, atan, floor, ceiling,
trunc, round and also sqrt and expt when USE_MATH=1.
Number-theoretical quotient, remainder and modulo, gcd, lcm.
Library: exact?, inexact?, odd?, even?, zero?, positive?, negative?,
exact->inexact. inexact->exact is a core function.
Type predicates
boolean?,eof-object?,symbol?,number?,string?,integer?,real?,list?,null?,
char?,port?,input-port?,output-port?,procedure?,pair?,environment?',
vector?. Also closure?, macro?.
Types
Types supported:
Numbers (integers and reals)
Symbols
Pairs
Strings
Characters
Ports
Eof object
Environments
Vectors
Literals
String literals can contain escaped quotes \" as usual, but also
\n, \r, \t, \xDD (hex representations) and \DDD (octal representations).
Note also that it is possible to include literal newlines in string
literals, e.g.
(define s "String with newline here
and here
that can function like a HERE-string")
Character literals contain #\space and #\newline and are supplemented
with #\return and #\tab, with obvious meanings. Hex character
representations are allowed (e.g. #\x20 is #\space).
When USE_ASCII_NAMES is defined, various control characters can be
refered to by their ASCII name.
0 #\nul 17 #\dc1
1 #\soh 18 #\dc2
2 #\stx 19 #\dc3
3 #\etx 20 #\dc4
4 #\eot 21 #\nak
5 #\enq 22 #\syn
6 #\ack 23 #\etv
7 #\bel 24 #\can
8 #\bs 25 #\em
9 #\ht 26 #\sub
10 #\lf 27 #\esc
11 #\vt 28 #\fs
12 #\ff 29 #\gs
13 #\cr 30 #\rs
14 #\so 31 #\us
15 #\si
16 #\dle 127 #\del
Numeric literals support #x #o #b and #d. Flonums are currently read only
in decimal notation. Full grammar will be supported soon.
Quote, quasiquote etc.
As usual.
Immutable values
Immutable pairs cannot be modified by set-car! and set-cdr!.
Immutable strings cannot be modified via string-set!
I/O
As per R5RS, plus String Ports (see below).
current-input-port, current-output-port,
close-input-port, close-output-port, input-port?, output-port?,
open-input-file, open-output-file.
read, write, display, newline, write-char, read-char, peek-char.
char-ready? returns #t only for string ports, because there is no
portable way in stdio to determine if a character is available.
Also open-input-output-file, set-input-port, set-output-port (not R5RS)
Library: call-with-input-file, call-with-output-file,
with-input-from-file, with-output-from-file and
with-input-output-from-to-files, close-port and input-output-port?
(not R5RS).
String Ports: open-input-string, open-output-string, get-output-string,
open-input-output-string. Strings can be used with I/O routines.
Vectors
make-vector, vector, vector-length, vector-ref, vector-set!, list->vector,
vector-fill!, vector->list, vector-equal? (auxiliary function, not R5RS)
Strings
string, make-string, list->string, string-length, string-ref, string-set!,
substring, string->list, string-fill!, string-append, string-copy.
string=?, string<?, string>?, string>?, string<=?, string>=?.
(No string-ci*? yet). string->number, number->string. Also atom->string,
string->atom (not R5RS).
Symbols
symbol->string, string->symbol
Characters
integer->char, char->integer.
char=?, char<?, char>?, char<=?, char>=?.
(No char-ci*?)
Pairs & Lists
cons, car, cdr, list, length, map, for-each, foldr, list-tail,
list-ref, last-pair, reverse, append.
Also member, memq, memv, based on generic-member, assoc, assq, assv
based on generic-assoc.
Streams
head, tail, cons-stream
Control features
Apart from procedure?, also macro? and closure?
map, for-each, force, delay, call-with-current-continuation (or call/cc),
eval, apply. 'Forcing' a value that is not a promise produces the value.
There is no call-with-values, values, nor dynamic-wind. Dynamic-wind in
the presence of continuations would require support from the abstract
machine itself.
Property lists
TinyScheme inherited from MiniScheme property lists for symbols.
put, get.
Dynamically-loaded extensions
(load-extension <filename without extension>)
Loads a DLL declaring foreign procedures.
Esoteric procedures
(oblist)
Returns the oblist, an immutable list of all the symbols.
(macro-expand <form>)
Returns the expanded form of the macro call denoted by the argument
(define-with-return (<procname> <args>...) <body>)
Like plain 'define', but makes the continuation available as 'return'
inside the procedure. Handy for imperative programs.
(new-segment <num>)
Allocates more memory segments.
defined?
See "Environments"
(get-closure-code <closure>)
Gets the code as scheme data.
(make-closure <code> <environment>)
Makes a new closure in the given environment.
Obsolete procedures
(print-width <object>)
Programmer's Reference
----------------------
The interpreter state is initialized with "scheme_init".
Custom memory allocation routines can be installed with an alternate
initialization function: "scheme_init_custom_alloc".
Files can be loaded with "scheme_load_file". Strings containing Scheme
code can be loaded with "scheme_load_string". It is a good idea to
"scheme_load" init.scm before anything else.
External data for keeping external state (of use to foreign functions)
can be installed with "scheme_set_external_data".
Foreign functions are installed with "assign_foreign". Additional
definitions can be added to the interpreter state, with "scheme_define"
(this is the way HTTP header data and HTML form data are passed to the
Scheme script in the Altera SQL Server). If you wish to define the
foreign function in a specific environment (to enhance modularity),
use "assign_foreign_env".
The procedure "scheme_apply0" has been added with persistent scripts in
mind. Persistent scripts are loaded once, and every time they are needed
to produce HTTP output, appropriate data are passed through global
definitions and function "main" is called to do the job. One could
add easily "scheme_apply1" etc.
The interpreter state should be deinitialized with "scheme_deinit".
DLLs containing foreign functions should define a function named
init_<base-name>. E.g. foo.dll should define init_foo, and bar.so
should define init_bar. This function should assign_foreign any foreign
function contained in the DLL.
The first dynamically loaded extension available for TinyScheme is
a regular expression library. Although it's by no means an
established standard, this library is supposed to be installed in
a directory mirroring its name under the TinyScheme location.
Foreign Functions
-----------------
The user can add foreign functions in C. For example, a function
that squares its argument:
pointer square(scheme *sc, pointer args) {
if(args!=sc->NIL) {
if(sc->isnumber(sc->pair_car(args))) {
double v=sc->rvalue(sc->pair_car(args));
return sc->mk_real(sc,v*v);
}
}
return sc->NIL;
}
Foreign functions are now defined as closures:
sc->interface->scheme_define(
sc,
sc->global_env,
sc->interface->mk_symbol(sc,"square"),
sc->interface->mk_foreign_func(sc, square));
Foreign functions can use the external data in the "scheme" struct
to implement any kind of external state.
External data are set with the following function:
void scheme_set_external_data(scheme *sc, void *p);
As of v.1.17, the canonical way for a foreign function in a DLL to
manipulate Scheme data is using the function pointers in sc->interface.
Standalone
----------
Usage: tinyscheme -?
or: tinyscheme [<file1> <file2> ...]
followed by
-1 <file> [<arg1> <arg2> ...]
-c <Scheme commands> [<arg1> <arg2> ...]
assuming that the executable is named tinyscheme.
Use - in the place of a filename to denote stdin.
The -1 flag is meant for #! usage in shell scripts. If you specify
#! /somewhere/tinyscheme -1
then tinyscheme will be called to process the file. For example, the
following script echoes the Scheme list of its arguments.
#! /somewhere/tinyscheme -1
(display *args*)
The -c flag permits execution of arbitrary Scheme code.
Error Handling
--------------
Errors are recovered from without damage. The user can install his
own handler for system errors, by defining *error-hook*. Defining
to '() gives the default behavior, which is equivalent to "error".
USE_ERROR_HOOK must be defined.
A simple exception handling mechanism can be found in "init.scm".
A new syntactic form is introduced:
(catch <expr returned exceptionally>
<expr1> <expr2> ... <exprN>)
"Catch" establishes a scope spanning multiple call-frames
until another "catch" is encountered.
Exceptions are thrown with:
(throw "message")
If used outside a (catch ...), reverts to (error "message").
Example of use:
(define (foo x) (write x) (newline) (/ x 0))
(catch (begin (display "Error!\n") 0)
(write "Before foo ... ")
(foo 5)
(write "After foo"))
The exception mechanism can be used even by system errors, by
(define *error-hook* throw)
which makes use of the error hook described above.
If necessary, the user can devise his own exception mechanism with
tagged exceptions etc.
Reader extensions
-----------------
When encountering an unknown character after '#', the user-specified
procedure *sharp-hook* (if any), is called to read the expression.
This can be used to extend the reader to handle user-defined constants
or whatever. It should be a procedure without arguments, reading from
the current input port (which will be the load-port).
Colon Qualifiers - Packages
---------------------------
When USE_COLON_HOOK=1:
The lexer now recognizes the construction <qualifier>::<symbol> and
transforms it in the following manner (T is the transformation function):
T(<qualifier>::<symbol>) = (*colon-hook* 'T(<symbol>) <qualifier>)
where <qualifier> is a symbol not containing any double-colons.
As the definition is recursive, qualifiers can be nested.
The user can define his own *colon-hook*, to handle qualified names.
By default, "init.scm" defines *colon-hook* as EVAL. Consequently,
the qualifier must denote a Scheme environment, such as one returned
by (interaction-environment). "Init.scm" defines a new syntantic form,
PACKAGE, as a simple example. It is used like this:
(define toto
(package
(define foo 1)
(define bar +)))
foo ==> Error, "foo" undefined
(eval 'foo) ==> Error, "foo" undefined
(eval 'foo toto) ==> 1
toto::foo ==> 1
((eval 'bar toto) 2 (eval 'foo toto)) ==> 3
(toto::bar 2 toto::foo) ==> 3
(eval (bar 2 foo) toto) ==> 3
If the user installs another package infrastructure, he must define
a new 'package' procedure or macro to retain compatibility with supplied
code.
Note: Older versions used ':' as a qualifier. Unfortunately, the use
of ':' as a pseudo-qualifier in existing code (i.e. SLIB) essentially
precludes its use as a real qualifier.
Подписаться на:
Сообщения (Atom)