Quoting a function name then using it - racket

I'm writing a program to log to various places. In it I have some log functions:
(define (write-to-file destination content)
(with-output-to-file destination
(λ ()
(displayln
content))
#:mode 'text #:exists 'append))
(define (write-to-port destination content)
(displayln content destination))
I want to use these functions at run-time. So I have made a list of lists to hold my configuration:
(define log-destinations
'((write-to-file "my.log")
(write-to-port (current-error-port))))
So I have a function that recursively consumes the list log-destinations:
(define (send-log-content content destinations)
(unless (null? destinations)
(let ([ destination (car destinations)])
(#%app (car destination) (cadr destination) content))
(send-log-content content (cdr destinations))))
However at runtime I'm getting:
application: not a procedure;
expected a procedure that can be applied to arguments
given: 'write-to-file
arguments...:
"my.log"
"[info] web: 2021/03/21 16:26:35 +11:00 /\n"
context...:
Which suggests I've not quoted the function name properly. So how do I quote the function name appropriately in log-destinations so it can be called correctly at runtime?

With the list literal here:
(define log-destinations
'((write-to-file "my.log")
(write-to-port (current-error-port))))
write-to-file and write-to-port are symbols, and (current-error-port) is a quoted list. You need the sublists in log-destinations to contain the procedures write-to-file and write-to-port. Further, you need to actually complete the evaluation of (current-error-port) to get the error port, which is to say that you need to evaluate the arguments within your lists.
Quoting a list to create a list literal means that the arguments will not be evaluated when the list is created. But, you can use the list procedure to create lists while evaluating the arguments:
(define log-destinations
(list (list write-to-file "my.log")
(list write-to-port (current-error-port))))
Alternatively, you could use the backquote syntax, i.e., quasiquotation. Quasiquotation allows you to create a list template with some control over how the list members are evaluated. Use a backquote to quasiquote a list, then place a comma before arguments which should be evaluated:
(define log-destinations
`((,write-to-file "my.log")
(,write-to-port ,(current-error-port))))
It isn't clear to me why you are using #%app; my guess is that you were thinking of (current-error-port) as a list in the procedure application. With the above changes you should be able to change the procedure call to:
((car destination) (cadr destination) content)

Related

How can I modify the #+ and #- readtable macros in Lisp?

Short version:
I want to change the #+ and #- reader macros to apply to all immediately subsequent tokens starting with ##, in addition to the following token. Therefore, the following code...
#+somefeature
##someattribute1
##someattribute2
(defun ...)
...would, in the absence of somefeature, result in no code.
Long version:
I have written my own readtable-macros which apply transformations to subsequent code. For example:
##traced
(defun ...)
This yields a function that writes its arguments and return values to a file, for debugging.
This fails, however, when used in conjunction with the #+ reader macro:
#+somefeature
##traced
(defun ...)
In the absence of somefeature, the function continues to be defined, albeit without the ##traced modification. This is obviously not the desired outcome.
One possible solution would be to use progn, as follows:
#+somefeature
(progn
##traced
(defun ...))
But that's kind of ugly.
I would like to modify the #+ and #- reader macros, such that they may consume more than one token. Something like this:
(defun conditional-syntax-reader (stream subchar arg)
; If the conditional fails, consume subsequent tokens while they
; start with ##, then consume the next token.
)
(setf *readtable* (copy-readtable))
(set-dispatch-macro-character #\# #\+ #'conditional-syntax-reader)
(set-dispatch-macro-character #\# #\- #'conditional-syntax-reader)
The problem is, I don't know how to "delegate" to the original reader macros; and I don't understand enough about how they were implemented to re-implement them myself in their entirety.
A naive approach would be:
(defun consume-tokens-recursively (stream)
(let ((token (read stream t nil t)))
(when (string= "##" (subseq (symbol-string token) 0 2))
(consume-tokens-recursively stream)))) ; recurse
(defun conditional-syntax-reader (stream subchar arg)
(unless (member (read stream t nil t) *features*)
(consume-tokens-recursively stream)))
However, I'm given to believe that this wouldn't be sufficient:
The #+ syntax operates by first reading the feature specification and then skipping over the form if the feature is false. This skipping of a form is a bit tricky because of the possibility of user-defined macro characters and side effects caused by the #. and #, constructions. It is accomplished by binding the variable read-suppress to a non-nil value and then calling the read function.
This seems to imply that I can just let ((*read-suppress* t)) when using read to solve the issue. Is that right?
EDIT 1
Upon further analysis, it seems the problem is caused by not knowing how many tokens to consume. Consider the following attributes:
##export expects one argument: the (defun ...) to export.
##traced expects two arguments: the debug level and the (defun ...) to trace.
Example:
#+somefeature
##export
##traced 3
(defun ...)
It turns out that #+ and #- are capable of suppressing all these tokens; but there is a huge problem!
When under a suppressing #+ or #-, (read) returns NIL!
Example:
(defun annotation-syntax-reader (stream subchar arg)
(case (read stream t nil t)
('export
(let ((defun-form (read stream t nil t)))))
; do something
('traced
(let* ((debug-level (read stream t nil t))
(defun-form (read stream t nil t)))))))
; do something
(setf *readtable* (copy-readtable))
(set-dispatch-macro-character #\# #\# #'annotation-syntax-reader)
#+(or) ##traced 3 (defun ...)
The ##traced token is being suppressed by the #+. In this situation, all the (read) calls in (annotation-syntax-reader) consume real tokens but return NIL!
Therefore, the traced token is consumed, but the case fails. No additional tokens are thus consumed; and control leaves the scope of the #+.
The (defun ...) clause is executed as normal, and the function comes into being. Clearly not the desired outcome.
The standard readtable
Changing the macros for #+ and #- is a bit excessive solution I think, but in any case remember to not actually change the standard readtable (as you did, but its important to repeat in the answer)
The consequences are undefined if an attempt is made to modify the standard readtable. To achieve the effect of altering or extending standard syntax, a copy of the standard readtable can be created; see the function copy-readtable.
§2.1.1.2 The Standard Readtable
Now, maybe I'm missing something (please give us a hint about how your reader macro is defined if so), but I think it is possible to avoid that and write your custom macros in a way that works for your use case.
Reader macro
Let's define a simple macro as follows:
CL-USER> (defun my-reader (stream char)
(declare (ignore char))
(let ((name (read stream)
(form (read stream))
(unless *read-suppress*
`(with-decoration ,name ,form)))
MY-READER
[NB: This was edited to take into account *read-suppress*: the code always read two forms, but returns nil in case it is being ignored. In the comments you say that you may need to read an indefinite number of forms based on the name of the decoration, but with *read-suppress* the recursive calls to read return nil for symbols, so you don't know which decoration is being applied. In that case it might be better to wrap some arguments in a literal list, or parse the stream manually (read-char, etc.). Also, since you are using a dispatching macro, maybe you can add a numerical argument if you want the decoration to be applied to more than one form (#2#inline), but that could be a bad idea when later the decorated code is being modified.]
Here the reader does a minimal job, namely build a form that is intended to be macroexpanded later. I don't even need to define with-decoration for now, as I'm interested in the read step. The intent is to read the next token (presumably a symbol that indicates what decoration is being applied, and a form to decorate).
I'm binding this macro to a unused character:
CL-USER> (set-macro-character #\§ 'my-reader)
T
Here when I test the macro it wraps the following form:
CL-USER> (read-from-string "§test (defun)")
(WITH-DECORATION TEST (DEFUN))
13 (4 bits, #xD, #o15, #b1101)
And here it works with a preceding QUOTE too, the apostrophe reader grabs the next form, which recursively reads two forms:
CL-USER> '§test (defun)
(WITH-DECORATION TEST (DEFUN))
Likewise, a conditional reader macro will ignore all the next lines:
CL-USER> #+(or) t
; No values
CL-USER> #+(or) §test (defun)
; No values
CL-USER> #+(or) §one §two §three (defun)
; No values
Decoration macro
If you use this syntax, you'll have nested decorated forms:
CL-USER> '§one §two (defun test ())
(WITH-DECORATION ONE (WITH-DECORATION TWO (DEFUN TEST ())))
With respect to defun in toplevel positions, you can arrange for your macros to unwrap the nesting (not completely tested, there might be bugs):
(defun unwrap-decorations (form stack)
(etypecase form
(cons (destructuring-bind (head . tail) form
(case head
(with-decoration (destructuring-bind (token form) tail
(unwrap-decorations form (cons token stack))))
(t `(with-decorations ,(reverse stack) ,form)))))))
CL-USER> (unwrap-decorations ** nil)
(WITH-DECORATIONS (ONE TWO) (DEFUN TEST ()))
And in turn, with-decorations might know about DEFUN forms and how to annotate them as necessary.
For the moment, our original macro is only the following (it needs more error checking):
(defmacro with-decoration (&whole whole &rest args)
(unwrap-decorations whole nil))
For the sake of our example, let's define a generic annotation mechanism:
CL-USER> (defgeneric expand-decoration (type name rest))
#<STANDARD-GENERIC-FUNCTION COMMON-LISP-USER::EXPAND-DECORATION (0)>
It is used in with-decorations to dispatch on an appropriate expander for each decoration. Keep in mind that all the efforts here are to keep defun in a top-level positions (under a progn), a recursive annotation would let evaluation happens (in the case of defun, it would result in the name of the function being defined), and the annotation could be done on the result.
The main macro is then here, with a kind of fold (reduce) mechanism where the forms are decorated using the resulting expansion so far. This allows for expanders to place code before or after the main form (or do other fancy things):
(defmacro with-decorations ((&rest decorations) form)
(etypecase form
(cons (destructuring-bind (head . tail) form
(ecase head
(defun (destructuring-bind (name args . body) tail
`(progn
,#(loop
for b = `((defun ,name ,args ,#body)) then forms
for d in decorations
for forms = (expand-decoration d name b)
finally (return forms))))))))))
(nb. here above we only care about defun but the loop should probably be done outside of the dispatching thing, along with a way to indicate to expander methods that a function is being expanded; well, it could be better)
Say, for example, you want to declare a function as inline, then the declaration must happen before (so that the compiler can know the source code must be kept):
(defmethod expand-decoration ((_ (eql 'inline)) name rest)
`((declaim (inline ,name)) ,#rest))
Likewise, if you want to export the name of the function being defined, you can export it after the function is defined (order is not really important here):
(defmethod expand-decoration ((_ (eql 'export)) name rest)
`(,#rest (export ',name)))
The resulting code allows you to have a single (progn ...) form with a defun in toplevel position:
CL-USER> (macroexpand '§inline §export (defun my-test-fn () "hello"))
(PROGN
(DECLAIM (INLINE MY-TEST-FN))
(DEFUN MY-TEST-FN () "hello")
(EXPORT 'MY-TEST-FN))

How do I provide a list of functions in Racket?

If I have a function that I want to be available outside of the current module, I can do the following...
(provide my-function)
Can I do this for a list of functions?
I tried the following...
(define f1 ...) ; body omitted for clarity
(define f2 ...) ; ditto
(define my-funs '(f1 f2))
(provide my-funs)
...but this gave "Unbound identifier in: f1" when I tried it.
Can I do this? Thanks
Update: Just to clarify what I'm trying to do here, I am working my way through Beautiful Racket, and am doing the first tutorial. At the stage where he defines the expander, he adds a handle function to handle the operators...
(define (handle [arg #f])
(cond
[(number? arg) (push-stack! arg)]
[(or (equal? * arg) (equal? + arg))
(define op-result (arg (pop-stack!) (pop-stack!)))
(push-stack! op-result)]))
But then, in order to make this work, he provides both + and *...
(provide + *)
This means that these two operators are hard-coded twice. When adding support for other operators, you'd need to modify the handle function and the provide call. I am trying to work out if we can define a list of operators, and use that in both, so you'd only need to make one modification to support new operators.
No, you can't do this.
You can export a list of functions by using filtered-out and begin-for-syntax (as seen below), but this prevents you from using the list within your code.
Exporting a list
#lang racket
(module fns racket
(require racket/provide)
(define (f1 a) (+ a 1))
(define (f2 a) (+ a 2))
(begin-for-syntax
(define my-funs '(f1 f2)))
(provide
(filtered-out
(λ (name) (and (member (string->symbol name) my-funs) name))
(all-defined-out))))
(require 'fns)
(display (f1 2))
How this works
provide can take any number of provide-spec forms and specifying multiple provide-specs is equivalent to writing multiple provide forms. One of the available provide-spec forms is all-defined-out, which will export all defined symbols in the module (or file if a module isn't explicitly specified).
By requiring racket/provide, we get access to helper functions that can transform and operate on provide-spec forms; filtered-out in particular allows us to run arbitrary code over a provide-spec and returns a valid provide-spec. (The required proc-expr is a function that takes a string (the string value of the exported identifiers) and returns a string or a falsy value. That's why when using member, we wrap it in an and and return the raw name itself. This could also be accomplished with findf: (λ (name) (findf (λ (n) (equal? (string->symbol name) n)) my-funs)))
However, this isn't quite enough, as provide is executed at "compile time", meaning that our list my-funs isn't available yet. To handle that, we need to wrap that definition in begin-for-syntax, which makes the binding available at "compile time" as well. But, by moving my-funs to "compile time", you lose the ability to use my-funs in non-"compile time" code. This means, for instance, you couldn't say (cond ... [(member arg my-funs) ...]):
(define (handle [arg #f])
(cond
[(number? arg) (push-stack! arg)]
[(member arg my-funs)
;; ^--- Error here with "my-funs: unbound identifier"
(define op-result (arg (pop-stack!) (pop-stack!)))
(push-stack! op-result)]))

How can I check if a list is a list of lists?

I'm trying to check if a parameter before use it in a function with racket. This parameter must be a list of lists.
I have tried:
(andmap (lambda (x) (not (and (list? x) (not (pair? x))))) lst)
with:
(define lst '('(a) '(b) '(c)))
But it fails because (pair? '(a)) is true. With pair? I'm trying to avoid (a . 1) dotted pairs because (list? (a . 1)) is also true.
How can I check if a list is a list of lists and doesn't contains dotter pairs?
Three things:
To check if a list is a list of lists, you can simply write
(define (list-of-lists? v)
(and (list? v) (andmap list? v)))
which first checks if the value is a list, then checks if all its elements are lists.
If you are doing this because a function should only accept a list of lists, and other values are illegal, then you should make things easier for yourself by using Racket’s contract system instead of doing the validation yourself:
(require racket/contract)
(define/contract (f lst-of-lsts)
(-> (listof list?) any/c)
#| do something here |#)
You, like many people exposed to it for the first time, seem to have some confusion about how quote works. You probably mean to write '((a) (b) (c)), not '('(a) '(b) '(c)). Please read What is the difference between quote and list?, or just use the list function.

Lisp evaluate variable in macro expression

I have the following function (I am a very beginner at Lisp):
(defun my-fun (a b)
(my-commandsend-and-reply-macro (cmd)
(:reply (ok result)
(do-something a b result)))
)
where my-commandsend-and-reply-macro is a macro written by another programmer. I am unable to modify it.
my-commandsend-and-reply-macro sends a command (in this example cmd) to a server process (it is written in another programming language) and then waits for its answer.
The answer is processed then in the macro using the user-given ":reply part of the code". The list (ok result) is a kind of pattern, in the macro a destructuring-bind destructures and binds the proper parts of the answer to ok and result (ok is just a flag). After this the other user-given lines of the ":reply part" are excuted. (for result processing)
I would like to do the following:
1, send a command like to the other process (this is ok)
2, call a function (like do-something) using the result AND using some other parameters which are the actual parameters of my-fun (this part fails...)
How can I do this? I think the problem is that a and b are not evaluated before the macro expansion and when the macro is expanded Lisp searches for a local a and b but there is no a or b. Is there any way to evaluate a and b? (so the macro could treat them like concrete values)
This is the macro def: (written by another programmer)
(defmacro* my-commandsend-and-reply-macro ((cmd &rest args) &body body)
`(progn
(with-request-id ()
(setf (gethash *request-id* *my-callbacks*)
(lambda (status &rest status-args)
(case status
,#(loop for (kind . clause) in body when (eql kind :reply)
collect
(destructuring-bind
((status-flag &rest lambda-form-pattern)
&body action-given-by-user) clause
`(,status-flag
(destructuring-bind ,lambda-form-pattern status-args
,#action-given-by-user))))
((error)
(message "Error: %s" (elt (elt status-args 0) 1))))))
(apply #'send-command-to-process *request-id* cmd args)))))
Def of with-request-id:
(defmacro* with-request-id ((&rest vars) &body body)
"Send `getid' to the server, and call `body' once the response
with the new ID has arrived. By then, global variable `*request-id*'
is bound to the latest request ID."
`(progn
(when (not (server-is-running))
(error "Server isn't running!"))
(when *reqid-queue*
(error "Some internal error occured. Please, restart the program!"))
(lexical-let (,#(loop for var in vars
collect `(,var ,var)))
(setf *reqid-queue* (lambda ()
(unwind-protect
(progn ,#body)
(setf *reqid-queue* nil)))))
(get-id)))
And getting id from the other process:
(defun get-id ()
(send-command-to-process 'getid))
Without looking into your code at all (apologies -- no time) ---
a and b are evaluated by the function my-fun. All functions evaluate their arguments to begin with -- only macros and special forms do not necessarily evaluate all of their arguments.
But those a and b values are not passed to the macro -- the only thing passed to it is the unevaluated sexp that is bound to cmd. And you do not even define cmd in your function!
What you need to do is substitute the values of a and b into the cmd sexp. You have not shown how cmd is defined/constructed, at all. Construct it using the values of a and b, and you should be OK.
To construct the cmd sexp, remember that you can use backquote syntax to simplify things, using comma syntax to pass the values of a and b. E.g.
(let ((cmd `(some funny (expression) that ((uses)) ,a AND ,b)))
code-that-uses-CMD)
This assumes that the code you pass to the macro does not need the variables a and b, and it needs only their values.
When the function my-fun is called the arguments have already been evaluated so it's not clear to me what is the problem you are facing.
The only strange thing I see is that the macro is un-hygienic and so if your arguments are named instead of a and b for example status or status-args you're going to be in trouble because the expression
(do-something <a> <b> results)
will be compiled in a context where those names have been reused by the macro.

Merging symbols in common lisp

I want to insert a char into a list. However, I want to merge this char with the last symbol in the list. With appends and cons the result is always two different symbols. Well, I want one merged symbol to be my result.
Example:
(XXXX 'a '5) ====> (a5)
What I would like to have, instead of:
(XXXX 'a '5) ====> (a 5)
You cannot "merge symbols" in Lisp.
First of all, 5 is not a symbol, but a number. If you want a symbol named "5" you have to type it as |5| (for example).
If a function takes the symbol A and symbol |5|, and produces the symbol A5, it has not merged symbols. It has created a new symbol whose name is the catenation of the names of those input symbols.
Properly designed Lisp programs rarely depend on how a symbol is named. They depend on symbols being unique entities.
If you're using symbols to identify things, and both 5 and A identify some entity, the best answer isn't necessarily to create a new symbol which is, in name at least, is a mashup of these two symbols. For instance, a better design might be to accept that names are multi-faceted or compound in some way. Perhaps the list (A 5) can serve as a name.
Common Lisp functions themselves can have compound names. For instance (setf foo) is a function name. Aggregates like lists can be names.
If you simply need the machine to invent unique symbols at run-time, consider using the gensym function. You can pass your own prefix to it:
(gensym "FOO") -> #:FOO0042
Of course, the prefix can be the name of some existing symbol, pulled out via symbol-name. The symbol #:FOO0042 is not unique because of the 0042 but because it is a freshly allocated object in the address space. The #: means it is not interned in any package. The name of the symbol is FOO0042.
If you still really want to, a simple way to take the printed representation of a bunch of input objects and turn it into a symbol is this:
(defun mashup-symbol (&rest objects)
(intern (format nil "~{~a~}" objects)))
Examples:
(mashup-symbol 1 2 3) -> |123|
(mashup-symbol '(a b) 'c 3) -> |(A B)C3|
Define this:
(defun symbol-append (&rest symbols)
(intern (apply #'concatenate 'string
(mapcar #'symbol-name symbols))))
and then use it as:
* (symbol-append 'a 'b 'c)
ABC
* (apply #'symbol-append '(a b c))
ABC
If you expect your arguments to contain stuff besides symbols, then replace symbol-name with:
(lambda (x)
(typecase x ...))
or a pre-existing CL function (that I've forgotten :() that stringifies anything.
The answer to the question you ask is
(defun concatenate-objects-to-symbol (&rest objects)
(intern (apply #'concatenate 'string (mapcar #'princ-to-string objects))))
(concatenate-objects 'a 'b) ==> ab
Oh, if you want a list as the result:
(defun xxxx (s1 s2) (list (concatenate-objects-to-symbol s1 s2)))
However, I am pretty sure this is not the question you actually want to ask.
Creating new symbols programmatically is not something beginners should be doing...