Is there a way to check if a symbol is quoted? - elisp

I'm trying to create a macro on Emacs Lisp and I'm struggling to see if a user may pass a symbol quoted or not quoted.
Actually I need something like quote-only-if-is-not-quoted macro. Is there anything like that? I didn't found nothing about that on any Lisp dialect. Macro example:
(quote-only-if-is-not-quoted 'q) => (quote q)
(quote-only-if-is-not-quoted q) => (quote q)
Thanks in advance.

Macro arguments are unevaluated, so yes, you can check to see whether an argument is quoted and, if not, quote it. Something like this?
(defmacro quote-only-if-is-not-quoted (arg)
(if (and (consp arg)
(eq (car arg) 'quote))
arg
`(quote ,arg)))

Related

How to `apply` a macro/syntax in Racket?

Suppose I have a list of arguments args and a macro/syntax f that takes a variable number of arguments. How do I apply f to args? Apparently apply doesn't work here.
For example, suppose I have a list of values bs and I want to know if they're all true, so I try (apply and bs) but I get the error "and: bad syntax". The workaround I came up with is (eval `(and . ,bs)) but I'm wondering if there is some standard way to achieve this sort of thing.
Update
A bunch of possible duplicates have been suggested, but most of them are just about the and example. This suggested question seems to be the same as mine, but the answer there is not very helpful: it basically says "don't do this!".
So maybe the point is that in practice this "apply + macro" question only comes up for macros like and and or, and there is no useful general question? I certainly ran into this issue with and, and don't have much Scheme experience, certainly no other examples of this phenomenon.
This is an XY problem. Macros are part of the syntax of the language: they're not functions and you can't apply them to arguments. Conceptually, macros are like functions which map source code to other source code, and which are called at compile time, not run time: trying to use them at run time is a category error. (In Common Lisp macros are, quite literally, functions which map source code to other source code: in Scheme I'm not quite so clear about that).
So if you have a list and you want to know if all its elements are true, you call a function on the list to do that.
It's easy to write such a function:
(define (all-true? things)
(cond [(null? things)
#t]
[(first things)
(all-true? (rest things))]
[else #f]))
However Racket provides a more general function: andmap: (andmap identity things) will either return false if one of things is not true, or it will return the value of the last thing in the list (or #t if the list is empty). (andmap (lambda (x) (and (integer? x) (even? x))) ...) will tell you if all the elements in a list are even integers, for instance.
There is also every which comes from SRFI 1 and which you can use in Racket after (require srfi/1). It is mostly (exactly?) the same as andmap.
One thing people sometimes try to do (and which you seem to be tempted to do) is to use eval. It may not be immediately clear how awful the eval 'solution; is. It is awful because
it doesn't, in fact, work at all;
insofar as it does work it prevents any kind of compilation and optimisation;
last but not least, it's a pathway to code injection attacks.
Let's see how bad it is. Start with this:
> (let ([args '(#t #t #f)])
(eval `(and ,#args)))
#f
OK, that looks good, right? Well, what if I have a list which is (a a a b): none of the elements in that are false, so, let's try that:
> (let ([args '(a a b)])
(eval `(and ,#args)))
; a: undefined;
; cannot reference an identifier before its definition
Oh, well, can I fix that?
> (let ([args '(a a b)]
[a 1] [b 2])
(eval `(and ,#args)))
; a: undefined;
; cannot reference an identifier before its definition
No, I can't. To make that work, I'd need this:
> (define a 1)
> (define b 2)
> (let ([args '(a a b)])
(eval `(and ,#args)))
2
or this
> (let ([args '('a 'a 'b)])
(eval `(and ,#args)))
'b
Yes, those are quotes inside the quoted list.
So that's horrible: the only two cases it's going to work for is where everything is either defined at the top level as eval has no access to the lexical scope where it is called, or a literal within the object which may already be a literal as it is here, because everything is now getting evaluated twice.
So that's just horrible. To make things worse, eval evaluates Scheme source code. So forget about compiling, performance, or any of that good stuff: it's all gone (maybe if you have a JIT compiler, maybe it might not be so awful).
Oh, yes, and eval evaluates Scheme source code, and it evaluates all of it.
So I have this convenient list:
(define args
'((begin (delete-all-my-files)
(publish-all-my-passwords-on-the-internet)
(give-all-my-money-to-tfb)
#t)
(launch-all-the-nuclear-missiles)))
It's just a list of lists of symbols and #t, right? So
> (eval `(and #,args)
; Error: you are not authorized to launch all the missiles
; (but all your files are gone, your passwords are now public,
; and tfb thanks you for your kind donation of all your money)
Oops.
It would be nice to be able to say, if I have a list that I want to check some property of that doing so would not send all my money to some person on the internet. Indeed, it would be nice to know that checking the property of the list would simply halt, at all. But if I use eval I can't know that: checking that every element of the list is (evaluates to) true may simply never terminate, or may launch nuclear weapons, and I can generally never know in advance whether it will terminate, or whether it will launch nuclear weapons. That's an ... undesirable property.
At the very least I would need to do something like this to heavily restrict what can appear in the list:
(define (safely-and-list l)
(for ([e (in-list l)])
(unless
(or (number? e)
(boolean? e))
(error 'safely-and-list "bad list")))
(eval `(and ,#l)))
But ... wait: I've just checked every element of the list: why didn't I just, you know, check they were all true then?
This is why eval is never the right solution for this problem. The thing eval is the right solution for is, well, evaluating Scheme. If you want to write some program that reads user input and evaluates, it, well, eval is good for that:
(define (repl (exit 'exit))
(display "feed me> ")
(flush-output)
(let ([r (read)])
(unless (eqv? r exit)
(writeln (eval r))
(repl exit))))
But if you think you want to apply a macro to some arguments then you almost certainly have an XY problem: you want to do something else, and you likely don't understand macros.

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

Can syntax parameters be used to replace syntax?

I'm trying to use syntax parameters in order to inject new syntax where I need it to be injected. The result of this is then used in other syntax.
However, it's not working as I expect it to. Here's a minimal working example:
(require racket/stxparam)
(require (for-syntax racket/stxparam))
;; declare parameter to be replaced with code
(define-syntax-parameter placeholder
(lambda (stx)
(raise-syntax-error
(syntax-e stx)
"can only be used inside declare-many-commands")))
;; this is just to print what 'arg' looks like
(define-syntax (print-syntax stx)
(syntax-case stx ()
[(_ arg)
#'(displayln 'arg)]))
;; this is the top-level entity invoked to produce many commands
(define-syntax-rule (declare-many-commands cmds)
(begin
(let ([X 10])
(syntax-parameterize
([placeholder (make-rename-transformer #'X)])
cmds))
(let ([X 20])
(syntax-parameterize
([placeholder (make-rename-transformer #'X)])
cmds))))
(declare-many-commands
(print-syntax placeholder))
What I would like to get as result when running this is:
10
20
but what I get is:
placeholder
placeholder
EDIT:
Posted a new question to refine the problem: Injecting syntax at compile time using Racket's syntax parameters?
The problem here is that your print-syntax macro quotes its input, and inputs to macro transformers are unexpanded syntax. This means that the expansion of (print-syntax placeholder) will always be (displayln 'placeholder), and no macroexpansion ever occurs under quote, so the placeholder binding in scope is irrelevant.
If you want to use the syntax parameter, you need to actually produce a reference to the placeholder binding. In this case, you just need to remove the use of quote. You could change print-syntax to (displayln arg), but at that point, there’s really no reason for print-syntax to be a macro, since it’s equivalent to the displayln function. Just use that instead:
(declare-many-commands
(displayln placeholder))
This will print 10 and 20 as you expect.
It’s possible you really do want the quote, and I don’t understand your question. In that case, though, I think it’s difficult for me to understand what you’re getting at without some additional context.

Define in scheme

I was trying to run this command on drracket:
(define #t #f)
and I get the following error messege:
define: bad syntax in: #t
I want to know what's the reason for that error, and why I can do: (define + 12) and not this.
Thanks a lot!
The syntax of define is:
(define <variable> <expression>)
A variable is a special kind of identifier, and the format of identifiers is described here. As you can see from the description, #t (and more generally, anything that starts with a #) is not an identifier.
define expects an identifier as it's first argument. In this case you are supplying #t which evaluates to the boolean value true. Hence the bad syntax error message.
First argument to define must be a symbol. + is a symbol. foo is a symbol. #t is #t, not a symbol. 1 is not a symbol.

Emacs ruby symbol word completion

Quite often I define a ruby symbol (eg. :some_value), then I want to create a method with the same name def some_value.
Unfortunately, the autocompletion(M + /) for the second occurrence of some_value string does not work, being slightly different (:some_value vs some_value).
How can I setup emacs to handle such events?
Assuming that M-/ is bound to dabbrev-expand, you can configure dabbrev-mode to ignore certain prefixes when expanding strings. To make a single colon a prefix to be ignored, type
M-x customize-group
and then
dabbrev
This will take you to the customization page for dabbrev-mode. Go to the point Dabbrev Abbrev Skip Leading Regexp and click on Value menu. From the menu, pick "Regexp".
Now you see a textfield labeled "Regexp: " next to the value menu in which you enter a single colon.
:
Then click on the button State in the next line and choose the value "Save for Future Sessions".
First, my results! I typed :some_crazy_symbol in my model. On a newline, I typed def so, hit M-/ twice, and ended up with
def some_crazy_symbol
end
(Rinari supplied the end.)
I got this to work quite well by using hippie-expand. If you want to test it out, bind hippie-expand to M-/ like so:
(global-set-key (kbd "M-/") 'hippie-expand)
Heres' the documentation. Hippie expand works by trying out a number of different expansions on the current point. These expansions are stored in the hippie-expand-try-functions-list variable. On my system (and be default), this variable is set to:
(try-complete-file-name-partially try-complete-file-name try-expand-all-abbrevs try-expand-list try-expand-line try-expand-dabbrev try-expand-dabbrev-all-buffers try-expand-dabbrev-from-kill try-complete-lisp-symbol-partially try-complete-lisp-symbol)
The minibuffer readout showed that this particular expansion was accomplished using the try-expand-dabbrev function.
Not a direct answer to your question, but you should get more intelligent Ruby autocompletion by using auto complete mode paired with rsense.
If Dabbrev Abbrev Skip Leading Regexp and hippie-expand doesn't do exactly what you want and you've got some elisp skills, you could create a custom function for hippie-expand.
See the section about "substring expansion" on the hippie-expand page on the emacs-wiki. There's a function you could use there you could tailor to customize..
Substring Expansion
When doing lisp programming standard dabbrev is less useful, because Emacs has no namespaces, so in a package symbols begin with the same prefix, therefore the same prefix has to be typed again and again if one wants to complete symbols from the package. As with IswitchBuffers it is much more effective if a unique substring can be typed to get to the desired symbol.
Dabbrev offers nothing in this regard, so I turned to Hippie Expand which I had never used before.
Here’s a function based on hippie expand dabbrev expansion which performs substring expansion:
(defun try-my-dabbrev-substring (old)
(let ((old-fun (symbol-function 'he-dabbrev-search)))
(fset 'he-dabbrev-search (symbol-function 'my-dabbrev-substring-search))
(unwind-protect
(try-expand-dabbrev old)
(fset 'he-dabbrev-search old-fun))))
(defun my-dabbrev-substring-search (pattern &optional reverse limit)
(let ((result ())
(regpat (cond ((not hippie-expand-dabbrev-as-symbol)
(concat (regexp-quote pattern) "\\sw+"))
((eq (char-syntax (aref pattern 0)) ?_)
(concat (regexp-quote pattern) "\\(\\sw\\|\\s_\\)+"))
(t
(concat (regexp-quote pattern)
"\\(\\sw\\|\\s_\\)+")))))
(while (and (not result)
(if reverse
(re-search-backward regpat limit t)
(re-search-forward regpat limit t)))
(setq result (buffer-substring-no-properties (save-excursion
(goto-char (match-beginning 0))
(skip-syntax-backward "w_")
(point))
(match-end 0)))
(if (he-string-member result he-tried-table t)
(setq result nil))) ; ignore if bad prefix or already in table
result))
I figured I'd share the solution I came up with that works for hippie-expand.
To summarize:
(defun hippie-expand-ruby-symbols (orig-fun &rest args)
(if (eq major-mode 'ruby-mode)
(let ((table (make-syntax-table ruby-mode-syntax-table)))
(modify-syntax-entry ?: "." table)
(with-syntax-table table (apply orig-fun args)))
(apply orig-fun args)))
(advice-add 'hippie-expand :around #'hippie-expand-ruby-symbols)
hippie-expand will expand symbols in ruby-mode when : is considered a punctuation character, so this advice creates a temporary syntax table where : is a punctuation character and calls hippie-expand with it.

Resources