-
Notifications
You must be signed in to change notification settings - Fork 0
5. GimpλLib's philosophy
As a first conclusion, remember that GimpλLib increases portability and compliance with R4RS, R5RS and some SRFI standards. The λLib favorably moves the portability slider. According to the SRFI modules, the compatibility is variable but better of course than without the corresponding .scm of the λLib.
The second call to a function with the same parameters is much faster than the first one.
To save a few hundred microseconds at runtime, move the *.scm scripts you don’t use elsewhere than in:
C:\Users\YourUserName\AppData\Roaming\GIMP\2.10\scripts
However, keep scripts whose name starts with 0 or resolve dependencies.
For example, if you don’t have the use of some kind of stack called box, move 2srfi-111-box.scm
to your archive folder.
Are chased loops with macro do replaced by let loop.
TinyScheme does not have a standard mechanism to evolve the syntax by define-syntax
and syntax-rules
at the foundation of the majority of SRFIs.
Its macro system by the macro keyword and its define-macro overload, defined in script-fu.init
, are extremely slow (in ms) in a scale of 10 in terms of execution compared to a classic lambda function (rather in hundreds of µs). That’s why when AlSchemist starts with a macro implementation, it’s to help understand. Then AlSchemist tries to provide an alternative faster lambda function.
Continuation programming consists in passing the function g(y)
as an additional parameter of the first function f(x)
to produce an anonymous lambda function accepting the parameter y
. For AlSchemist, g
appears as a continuation of `f. Continuation programming has been enhanced by classic sequential or nested calls.
In Tinyscheme, programming by continuation turns out to be more penalizing than the sequential call of functions with their parameters.
Consider two functions (f x)
followed by (g y)
with the parameter y
depending on the result of (f x)
.
( (f x g) y) ; programmation by continuation : g is the continuation of f
#| faster alternatives: |#
(g (f x)) ; nested call of type function composition. See (compose g f) in 2srfi-013-string.scm
(let* ( (y (f x) ) ; with the local temporary variable y
(g y)
)
The preceding code snippet cannot be executed in the Script-Fu console because the definition of functions f
, g
, and the value of x
and y
have not been defined.
The author of λLib, AlSchemist refuses any overloading of basic primitives. It’s to preserve performance and understanding. Even if it is opposed to the SRFI standards. For example SRFI-9 Record succinctly requests that “Records are disjoint from the types listed in Section 4.2 of R5RS.”
The reader will find this comment:
"; AlSchemist removed all alterations of basic primitives about vector."
A record of the λLib is and will remain a vector. However the λLib provides the record? predicate to distinguish a standard vector from a record vector. And further “so AlSchemist does not overwrite EVAL.” If you want to override, also change the name of the function while preserving the basic primitive.
Firstly, the λLib does not erase any files. Then, by design the λLib cannot access neither the Windows registry nor the Microsoft PowerShell.
Finally AlSchemist removed functions rated as dangerous in the category of setters. A setter has its name ended with an exclamation point. That is to say, a setter modifies the content of an existing variable given as parameter without creating a new one.
Thus AlSchemist considers the Script-Fu plugin of Gimp insufficiently robust to call append!
without danger and its derivatives concatenate!
pair-fold-right
pair-fold
append-map!
However, the interested reader will find the entire original source code of the SRFI 1 List for her own experiments. append!
runs faster than the setter set!
in the append
context without an exclamation mark. But AlSchemist found that the patched lists did not resist to a heavy use (1000 times) without scratching the Script-Fu plugin.
However, the Gimp application is enough robust to recover a fatal error in the Script-Fu plugin.
As a consolation, AlSchemist keeps circular-list
in 1srfi-001-list.scm
with the warning:
"Caution: a circular list does not have any limit."
Consequently, the user of an infinite circular list will have to take precautions in the programming. Otherwise he could be forced to close manually the Script-Fu plugin by clicking on the closing cross.
As you might expect, the rule is that you don’t display an infinite circular list. In addition, do not search to know the size by without the suffix length
+
. Because the size of an infinite circular list takes a computation time by definition infinite. The proper-list?
predicate properly fails by returning #f
as length+
when its parameter is an infinite circular list.
Hereafter enclosed is a numerical example of the use of a circular list, which provides the succession of numbers 1 0 1 0 1 0… to infinity.
; How to increment the first and the third number in the list (3 1 4 1) with a circular list?
(map + '(3 1 4 1) (circular-list 1 0))
;-> (4 1 5 1)
🟩 On the left, vertically aligned parentheses in GimpλLib's Script-Fu source code vs. the legacy version on the right
The legacy Lisp standard of pretty-print, found on the right, accumulates all closing parentheses to the right of the last expression of each function without any alignment.
In Lisp dialects in which TinyScheme belongs, the developer often has to solve the eternal research for the missing or unbalanced closing parenthesis. Fortunately NotePad++ provides a visual aid with the colorful matching of same-level parenthesis.
AlSchemist goes further with the GimpλLib by proposing in the left margin the vertical alignment of the parentheses.
Specifically, in reality, the parenthesis matching can be crossed between the closing parentheses tabulated on the last line of each function and their corresponding opening parenthesis. Initially, there was only one closing parenthesis per line but this took up too much space with almost empty lines containing only one closing parenthesis.
The airy formatting of the λLib facilitates the identification of missing parentheses during the evolution of a function.
- NotePad++ keyboard shortcut
Ctrl
+Alt
+B
selects a defined function or well formed expression only if its parenthesis are well balanced to avoid the dreaded#<EOF>
error in the Script-Fu console. -
Ctrl
+B
navigates between the opening parenthesis and the corresponding closing parenthesis in the editor.
AlSchemist rewrote in NotePad++ all the functions of the λLib according to his own pretty-print (pp
) based on the 4-spaces tab instead of only 2-spaces.
The legacy standard is based on a spacing of only two spaces in the left margin. This produced monuments such as stdio:iprintf
or stdio:scan-and-set
from Aubrey’s SLIB to be compared with 0ts-stdio.scm
of rank 0 in the λLib. The prefix “ts” means TinyScheme.
SRFI 159 Combinator Formatting was abandoned in favor of SRFI 166 Monadic Formatting by the same Alex, SRFI judged according to AlSchemist out of the TinyScheme feasibility for a first version of the λLib.
The legacy limit of 80 characters per line of source code is becoming obsolete with modern screens. AlSchemist allows up to a hundred characters per line for the λLib in NotePad++. There is no width limit for error messages and copyright notices. The λLib was not designed to be printed.
Finally, the λLib is intended to be educational with an exceptional rate of comments approaching 50%.
According to AlSchemist, the most educational way internationally to understand a Scheme function is to provide at least one executable example as well as the expected concrete result rather than abstract generic symbolic formulas or nested functions for performance.
For example:
- The legacy version of
pp-call
for source code formatting is nested inside thepp
function, itself nested ingeneric-write
. It is therefore not possible to reconstruct the individual context to callpp-call
in order to know what it returns. -
pp-call
version of the Gimp lambda library can be directly called in the Script-Fu console because the entire context is given through the input parameters:
(pp-call '(IF condition partThen partElse) 0 0 #f)
;-> The result displayed in the Script-Fu console is:
(IF condition
partThen
partElse
)1
The number 1, which follows the closing parenthesis, is the column of the closing parenthesis, that is to say that the last parenthesis has been closed in column 1.