Cleanest way to make a "derived" identifier? - syntax

It's very common for Scheme macros to make "derived" identifiers, like how defining a record type foo (using the R6RS syntactic record API) will by default define a constructor called make-foo. I wanted to do something similar in my own macro, but I couldn't find any clean way within the standard libraries. I ended up writing this:
(define (identifier-add-prefix identifier prefix)
(datum->syntax identifier
(string->symbol (string-append prefix
(symbol->string (syntax->datum identifier)))))
I convert a syntax object (assumed to be an identifier) into a datum, convert that symbol into a string, make a new string with the prefix prepended, convert that string into a symbol, and then finally turn that symbol into an identifier in the same syntactic environment as identifier.
This works, but it seems roundabout and messy. Is there a cleaner or more idiomatic way to do this?

Although it might not be a hygienic macro, i suppose you could use define-syntax like this (in chicken scheme).
For chicken scheme the documentation for macros is here. Also this SO question sheds some light on chicken scheme macros. Finally i don't know if this would be an idiomatic way to approach the problem.
(use format)
(use srfi-13)
(define-syntax recgen
(lambda (expr inject compare)
`(define (,(string->symbol (string-append "make-" (cadr expr))) ) (format #t "called"))))
#> (recgen "bar")
#> (make-bar)
called
The single define above could be changed to a (begin ... ) that defines getters/setters or other ways to interact with the record.

Related

More macro woes

I am still having some troubles with this concept. The key paragraph in the r7rs standard is:
"Identifiers that appear in the template but are not pattern
variables or the identifier ellipsis are inserted into the output as literal identifiers. If a literal identifier is inserted as a
free identifier then it refers to the binding of that identifier
within whose scope the instance of syntax-rules appears.
If a literal identifier is inserted as a bound identifier then
it is in effect renamed to prevent inadvertent captures of
free identifiers."
By "bound identifier" am I right that it means any argument to a lambda, a top-level define or a syntax definition ie. define-syntax, let-syntax or let-rec-syntax? (I think I could handle internal defines with a trick at compile time converting them to lambdas.)
By "free identifier" does it mean any other identifier that presumably is defined beforehand with a "bound identifier" expression?
I wonder about the output of code like this:
(define x 42)
(define-syntax double syntax-rules ()
((_) ((lambda () (+ x x)))))
(set! x 3)
(double)
Should the result be 84 or 6?
What about this:
(define x 42)
(define-syntax double syntax-rules ()
((_) ((lambda () (+ x x)))))
(define (proc)
(define x 3)
(double))
(proc)
Am I right to suppose that since define-syntax occurs at top-level, all its free references refer to top-level variables that may or may not exist at the point of definition. So to avoid collisions with local variables at the point of use, we should rename the outputted free reference, say append a '%' to the name (and disallow the user to create symbols with % in them). As well as duplicate the reference to the top-level variable, this time with the % added.
If a macro is defined in some form of nested scope (with let-syntax or let-rec-syntax) this is even trickier if it refers to scoped variables. When there is a use of the macro it will have to expand these references to their form at point of definition of the macro rather than point of use. So I'm guessing the best way is expand it naturally and scan the result for lambdas, if it finds one, rename its arguments at point of definition, as the r7rs suggests. But what about references internal to this lambda, should we change these as well? This seems obvious but was not explicitly stated in the standard.
Also I'm still not sure whether it is best to have a separate expansion phase separate from the compiler, or to interweave expanding macros with compiling code.
Thanks, and excuse me if I've missed something obviously, relatively new to this.
Steve
In your first example, properly written:
(define x 42)
(define-syntax double
(syntax-rules ()
( (_) ((lambda () (+ x x))) ) ))
(set! x 3)
(double)
the only possibility is 6 as there is only one variable called x.
In your second example, properly written:
(define x 42)
(define-syntax double
(syntax-rules ()
((_) ((lambda () (+ x x))) )))
(define (proc)
(define x 3)
(double))
(proc)
the hygienic nature of the Scheme macro system prevents capture of the unrelated local x, so the result is 84.
In general, identifiers (like your x) within syntax-rules refer to what they lexically refer to (the global x in your case). And that binding will be preserved because of hygiene. Because of hygiene you do not have to worry about unintended capture.
Thanks, I think I understand... I still wonder how in certain advanced circumstances hygiene is achieved, eg. the following:
(define (myproc x)
(let-syntax ((double (syntax-rules ()
((double) (+ x x)))))
((lambda (x) (double)) 3)))
(myproc 42)
The site comes up with 84 rather than 6. I wonder how this (correct) referential transparency is achieved just by renaming. The transformer output does not bind new variables, yet still when it expands on line 4, we have to find a way to get to the desired x rather than the most recent.
The best way I can think of is simply rename every time a lambda argument or definition shadows another, ie. keep appending %1, %2 etc... macro outputs will have their exact versions named (eg. x%1) while references to identifiers simply have their unadorned name x and the correct variable is found at compile time.
Thanks, I hope for any clarification.
Steve

Racket macro to define functions given a repeated pattern

The problem is quite difficult to explain because I need to collect my thoughts, so bear with me. I've been able to reduce the problem to a minimal example for illustrative purposes. The example will not make any sense as to what this would be useful for, but I digress. Say I want to extend the racket language to write things that look like this:
(define-something
(['a] 'whatever)
(['b 'c] 'whatever2))
Between the square brackets is a sequence of one or more symbols, followed by a sequence of racket expressions (the whatever's, which are not important for the problem statement)
The example would match a macro that looks something like this:
(define-syntax (define-something stx)
(syntax-case stx ()
[(_ ([symb ...] body ...) ...)
#'()]))
Actually here we match 0 or more symbols, but we can assume there is always going to be at least one.
In the macro's body I want to generate function definitions using the concatenated symbols as the identifier. So for our silly example the macro would expand to something like:
(define (a) 'whatever)
(define (bc) 'whatever2)
I have found a similar question where the poster generates functions using a pre-defined list of strings, but I am not that fluent with macro's so I have not been able to translate the concepts to solve my problem. I thought perhaps I could try generating a similar list (by concatenating the symbols) and applying their tactic, but I've been getting way too confused with all the ellipses in my macro definition. I'm also a bit confused about their use of an ellipsis in with-syntax.
It’s possible to solve this with with-syntax and syntax-case, but the easiest way to do this is by using syntax-parse’s syntax classes. By defining a syntax class that parses a list of symbols and produces a single concatenated identifier, you can lift the symbol parsing out of the macro body:
(require (for-syntax syntax/parse
racket/string))
(begin-for-syntax
(define-syntax-class sym-list
#:attributes [concatenated-id]
(pattern (~and stx (sym:id ...))
#:attr concatenated-id
(let* ([syms (syntax->datum #'(sym ...))]
[strs (map symbol->string syms)]
[str (string-append* strs)]
[sym (string->symbol str)])
(datum->syntax #'stx sym #'stx #'stx)))))
Now you can define your macro pretty easily:
(define-syntax (define-something stx)
(syntax-parse stx
[(_ (syms:sym-list body ...) ...)
#'(begin
(define (syms.concatenated-id) body ...)
...)]))
Note that this uses unquoted symbols in the name clause, so it would work like this:
(define-something
([a] 'whatever)
([b c] 'whatever2))
The names can’t be expressions that evaluate to symbols because the information needs to be known at compile-time to be available to macro expansion. Since you mentioned in a comment that this is for an FRP-like system, your signal graph will need to be static, like Elm’s is for example. If you want the ability to construct a dynamic signal graph, you’ll need a more complex strategy than macros since that information will need to be resolved at runtime.

Looking for convenient way to define lexically scoped aliases for functions

I'm looking for the closest equivalent (both typographically and semantically) to what the following would do if functions in Elisp were "first-class":
(let ((f function-with-very-long-name))
(progn
...
(f ...) ;; evaluates to (function-with-very-long-name ...)
...
)
)
IOW, I'm looking for a convenient way to define lexically scoped aliases for functions.
The closest I've found involves binding the aliasing symbol (f in the example above) to a lambda that in turn calls the aliased function. I find this approach typographically cumbersome. (It negates whatever typographic simplification the rest of the code may have gained from the aliasing.)
Is there anything better?
I think the simplest way is to use cl-flet or cl-labels (the exact names may depend on which version of Emacs you are using, due to the great cl-* renaming. You can also use cl-letf with (symbol-function 'symbol) if you prefer, though I think that's needlessly obscure.
You can use funcall for this. For example, the let below passes 21 to a-function-with-an-extremely-long-name, which doubles it and returns 42:
(defun a-function-with-an-extremely-long-name (i) (* 2 i))
(let ((f 'a-function-with-an-extremely-long-name))
(funcall f 21))

How do I use with-type to use Typed Racket fragments within untyped modules?

The Typed Racket reference indicates that it's possible to use with-type to created “typed regions” within untyped code.
The with-type form allows for localized Typed Racket regions in otherwise untyped code.
It’s a little unclear how to actually use this, though. Obviously, using such a feature needs to take place within an untyped module using #lang racket or something similar. How should the with-type binding be imported?
A naïve attempt is just to require Typed Racket, but this causes failures with how TR overwrites existing syntactic forms.
(require typed/racket)
(struct point (x y)) ; complains about missing type annotations
Trying to use only-in to simply require with-type and nothing else sort of works, but then none of the required type bindings (such as Number or ->) exist.
It seems like the only way to do this would be to manually use only-in to import only the things that I need, but this feels laborious. I could also use prefix-in, but then of course everything would be scattered with prefixes.
Is there a recommended way of doing this, or is this feature somewhat deprecated?
I don't know the fundamental answer. A guess is that it's the sort of thing that would be useful when writing macros, as opposed to code you'd write directly?
A practical idea: You can use local-require to limit the "contamination" of the TR require. And you can flip to using except-in if that's less work then only-in.
For instance this example from the docs get close, but gives a weird error presumably because it's using TR's quote:
#lang racket/base
(let ([x 'hello])
(local-require typed/racket)
(with-type
#:result String
#:freevars ([x String])
(string-append x ", world")))
; /tmp/so.rkt:7:21: quote: identifier used out of context
; in: quote
Excluding that with except-in gives the desired error:
(let ([x 'hello])
(local-require (except-in typed/racket quote))
(with-type
#:result String
#:freevars ([x String])
(string-append x ", world")))
; x: broke its contract
; promised: String
; produced: 'hello
; in: String
; contract from: /tmp/so.rkt
; blaming: /tmp/so.rkt
; (assuming the contract is correct)
; at: /tmp/so.rkt:14.17
But yeah. This is just fiddling with the edges and not getting to the heart of it.
I would just use except-in (or perhaps rename-in) to avoid the few identifiers that don't work in both typed and untyped programs. Like this modification of Greg's program:
#lang racket/base
(require (except-in typed/racket struct))
(struct point (x y))
(let ([x 'hello])
(with-type
#:result String
#:freevars ([x String])
(string-append x ", world")))

Aliases for keywords

(define defun define)
It raises error define: not allowed in an expression context in: define in Racket. How to create aliases for fundamental constructs like define, let, lambda?
define is a syntax, not a first-class object. You cannot refer to it as an object.
As Justin said, you can create a macro. But note that Lisp-style defun has different syntax to Scheme-style define, and your macro should take that into account:
(define-syntax-rule (defun name params body ...)
(define (name . params)
body ...))
Not sure about Racket specifically, but the more general problem is that in Scheme define, let and lambda are syntax and/or special forms rather than functions. So you cannot reference them in an expression context like you could if they were defined as functions.
But instead, you can define a macro defun that expands into a define expression.
With normal procedures you can alias with define:
(define first car) ; first isn't defined in R[67]RS
However define and defun isn't form compatible. This macro will make a global defun that works as in Common Lisp:
#!r6rs
(import (rnrs base))
(define-syntax defun
(syntax-rules ()
((defun name args . body)
(define (name . args) . body))))
define in Scheme has more hats than defun, mostly because of the one-namespace nature of Scheme. define works as labels, flet, defconstant and setq (but for previously bound, one need to use set! to update).

Resources