@@ 0,0 1,23 @@
+A small utility macro to allow defines in expression context in the "toplevel" of function bodies.
+Install it in your site-dir and import it using (use-modules (syntax def))
+
+## Example
+
+ (use-modules (syntax def))
+ (def (divide-minus-one a b)
+ (when (= b 1) (error "We don't allow that here"))
+ (define b* (- b 1))
+ (/ a b*))
+
+This transforms all defines in expression context to (letrec ...). It also supports using (def ...) in expression
+context, but those are transformed into let*, which has less overhead in guile (2.2 at least).
+
+## Portability
+The macros are currently written in syntax-rules. If that isn't supported in your scheme, then I'm not really sure
+it is a scheme.
+
+## License
+Permissified ISC.
+
+## DOCUMENTATION
+There is none, however there are is info in the source comments.
@@ 0,0 1,107 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Copyright 2019 Linus Björnstam
+;;
+;; Permission to use, copy, modify, and/or distribute this software for any
+;; purpose with or without fee is hereby granted, provided that the above
+;; copyright notice and this permission notice appear in all source copies.
+;; The software is provided "as is", without any express or implied warranties.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; A small extension to define* that allows for arbitrary positions of defines in
+;; the toplevel of a function body. Guile follows r6rs in that it does not allow
+;; defines in "expression context", which means all (define ...) must happen at
+;; the top of a funciton definition. This macro solves that, in that it allows defines
+;; at any "toplevel" place within the function body.
+;;
+;; Example:
+;; in guile the following is not allowed:
+;;
+;; (define (do-stuff a b)
+;; (define c (wowza a))
+;; (unless c (error "holy hell"))
+;; (define abc (+ a b c))
+;; (/ 100 abc))
+;;
+;; because (define abc ...) is in expression context.
+;; You solve this by using let, let*, letrec or letrec* as appropriate.
+;; OR by using this macro.
+;; The above code would work just fine if you replaced the top define with def.
+;; It transforms defines in expression context to letrec, and as an added bonus
+;; transforms (def ...) in expression context to (let* ...). Why? Because
+;; it is less heavy than letrec. If you have a function that is called a million times
+;; that has very little overhead, you will actually have quite a speedup by not using
+;; defines in the function body, at least on guile 2.2.
+;;
+;;; How does it work?
+;; Well, I'm glad you asked! The magic macro is %body, which walks through the body of
+;; def. It if finds a define, it dispatches that part of the body to %define.
+;; %define takes all defines it can find in a row and turns them into a letrec.
+;;
+;; If %body finds a (def ...) it turns it into a simple (let ...). Guile transforms
+;; any chained lets into let*.
+;;
+;;; What are the finer details?
+;; It does not recursively walk the body, so only "local toplevel" defines/defs are
+;; transformed. Doing that would be non-trivial using syntax-rules and quite simple
+;; using syntax-case. I spent a total of 5 minutes writing this macro, and getting the
+;; inns and outs of recursive body transversal correct would have taken some more time.
+;;
+;; (def (name formals ...) body ...) gets transformed into (define* ...). This is a fine
+;; transformation to do, since any define* that does not use the extra features is the same
+;; as a regular define in every way. Internal (define (...) ...) are converted to lambda*.
+;; This is fine for the same reason.
+;;
+;;; Is it well tested?
+;; I wrote this code in 6 minutes, and it worked as I expected on the first try. I did not
+;; do any testing whatsoever. It might actually not work at all for you.
+;;
+;;; Future of this macro?
+;; I will probably convert it to syntax-case to do proper transversals and rewriting of
+;; function bodies. I want to allow for arbitrary placement of defines and defs, like
+;; for example in cond clauses.
+
+(define-module (syntax def)
+ #:export (def))
+
+(define-syntax %define
+ (syntax-rules (define)
+ ((_ (bindings ...) (define (name formals ...) body ...) rest ...)
+ (%define (bindings ... (name (%lambda (formals ...) body ...))) rest ...))
+ ((_ (bindings ...) (define name expr) rest ...)
+ (%define (bindings ... (name expr)) rest ...))
+ ((_ bindings rest ...)
+ (letrec bindings
+ (%body rest ...)))))
+
+
+(define-syntax %lambda
+ (syntax-rules ()
+ ((_ (. formals) body ...)
+ (lambda* formals body ...))
+ ((_ (formals ...) body ...)
+ (lambda* (formals ...) body ...))))
+
+(define-syntax %body
+ (syntax-rules (def define)
+ ((_ (define stuff ...) rest ...)
+ (%define () (define stuff ...) rest ...))
+ ((_ (def (name formals ...) body ...) rest ...)
+ (let ((name (%lambda (formals ...) (%body body ...))))
+ (%body rest ...)))
+ ((_ (def name expr) rest ...)
+ (let ((name expr))
+ (%body rest ...)))
+
+ ;; Just a simple expression and nothing more.
+ ;; %body is now unnecessary and it can die.
+ ((_ end)
+ end)
+ ;; A non-def(ine) expression. Examine the rest!
+ ((_ expr rest ...)
+ (begin expr (%body rest ...)))))
+
+(define-syntax def
+ (syntax-rules ()
+ ((_ name expr) (define name expr))
+ ((_ (name formals ...) body ...)
+ (define* (name formals ...) (%body body ...)))))