Is it possible to have autocompletion of defprotocol methods in Emacs?
An example:
(defprotocol Foo
(bar [this])
(baz [this])
(deftype Qux [a b c]
Foo
(bar [this] a)
(baz [this] b))
(bar (Qux. 1 2 3))
(baz (Qux. 1 2 3))
I was looking for something like this(in pseudocode):
;; (1)
(`M-Tab` (Qux. 1 2 3))
;;
;; or (2):
(-> (Qux. 1 2 3) `M-Tab`)
to trigger a dropdown with bar & baz options.
As a workaround I'm currently using (2) but it needs to have at least 1st character to be present(autocomplete all options doesn't work).
Is there a better way to do it?
Thanks
For me auto-completion also works in case (1) when one character is present. It does not seem to specifically be aware of the functions belonging to the protocol, CIDER is just aware of the functions in scope. The completion-at-point does not seem to toggle without a first character. Maybe you can try asking on #cider of clojurians.slack.org?
😄
Related
If I want to define a function that accepts an unknown number of args I can easily do something like this:
(defn foo
[& args]
args)
It returns a value of type clojure.lang.ArraySeq which contains the value given in the function.
In macro, using ~# is unquote-splicing, which flattens the argument given:
(defmacro foo
[bar & baz]
`(println ~#baz))
If I use the macro like this:
(foo "foo" 1 2 3 4)
It will print out 1 2 3 4. But, I want to get the args unflattened. Doing ~baz (without #) gives me an exception. Any idea how to do it?
If you macroexpand-1 the version using ~baz, the cause of the problem becomes apparent:
(macroexpand-1 '(foo "foo" 1 2 3 4)) ; NB. using ~baz in foo's body
;= (println (1 2 3 4))
; ^
So here we're attempting to call 1 as a function. (NB. this call takes place and the exception is thrown at run time.)
The right way to fix this depends on what you want to achieve. For example, you could pour the rest arg into a vector and print that:
(defmacro foo [bar & baz]
`(println ~(vec baz)))
A comment on Michał Marczyk's answer ...
You can also see what's happening by turning the macro into a function:
(defn foo [bar & baz]
`(println ~#baz))
=> (foo "foo" 1 2 3 4)
(clojure.core/println (1 2 3 4))
Syntax quoting, unquoting, and unquote splicing still work. Aha! Macros differ from functions in how they are invoked, not in what they do.
You can always do
(defmacro foo
[bar & baz]
`(println (list ~#baz)))
to construct a seq or
(defmacro foo
[bar & baz]
`(println [~#baz]))
to construct a vector.
I am trying define symbols a and b in following way
a + 1 1 b
2
I am trying to do this by using define-symbol-macro
(define-symbol-macro a '( )
(define-symbol-macro b ') )
but this way is not working.
What Lisp does with source code
Common Lisp is an incredibly flexible language, in part because its source code can be easily represented using the same data structures that are used in the language. The most common form of macro expansion transforms the these structures into other structures. These are the kind of macros that you can define with define-symbol-macro, define-compiler-macro, defmacro, and macrolet. Before any of those kind of macroexpansions can be performed, however, the system first needs to read the source from an input stream (typically a file, or an interactive prompt). That's the reader's responsibility. The reader also is capable of executing some special actions when it encounters certain characters, such ( and '. What you're trying to do probably needs to be happening down at the reader level, if you want to have, e.g., (read-from-string "a + 1 1 b") return the list (+ 1 1), which is what you want if you want (eval (read-from-string "a + 1 1 b")) to return 2. That said, you could also define a special custom language (like loop does) where a and b are treated specially.
Use set-macro-character, not define-symbol-macro
This isn't something that you would do using symbol-macros, but rather with macro characters. You can set macro characters using the aptly named set-macro-character. For instance, in the following, I set the macro character for % to be a function that reads a list, using read-delimited-list that should be terminated by ^. (Using the characters a and b here will prove very difficult, because you won't be able to write things like (set-macro-character ...) afterwards; it would be like writing (set-m(cro-ch(r(cter ...), which is not good.)
CL-USER> (set-macro-character #\% (lambda (stream ignore)
(declare (ignore ignore))
(read-delimited-list #\^ stream)))
T
CL-USER> % + 1 1 ^
2
The related set-syntax-from-char
There's a related function that almost does what you want here, set-syntax-from-char. You can use it to make one character behave like another. For instance, you can make % behave like (
CL-USER> (set-syntax-from-char #\% #\()
T
CL-USER> % + 1 1 )
2
However, since the macro character associated with ( isn't looking for a character that has the same syntax as ), but an actual ) character, you can't simply replace ) with ^ in the same way:
CL-USER> (set-syntax-from-char #\^ #\))
T
CL-USER> % + 1 1 ^
; Evaluation aborted on #<SB-INT:SIMPLE-READER-ERROR "unmatched close parenthesis" {1002C66031}>.
set-syntax-from-char is more useful when there's an existing character that, by itself does something that you want to imitate. For instance, if you wanted to make ! an additional quotation character:
CL-USER> (set-syntax-from-char #\! #\')
T
CL-USER> (list !a !(1 2 3))
(A (1 2 3))
or make % be a comment character, like it is in LaTeX:
CL-USER> (set-syntax-from-char #\% #\;)
T
CL-USER> (list 1 2 % 3 4
5 6)
(1 2 5 6)
But consider why you're doing this at all…
Now, even though you can do all of this, it seems like something that would be utterly surprising to anyone who ran into it. (Perhaps you're entering an obfuscated coding competition? ;)) For the reasons shown above, doing this with commonly used characters such as a and b will also make it very difficult to write any more source code. It's probably a better bet to define an entirely new readtable that does what you want, or even write a new parser. even though (Common) Lisp lets you redefine the language, there are still things that it probably makes sense to leave alone.
A symbol-macro is a symbol that stands for another form. Seems like you want to look at reader macros.
http://clhs.lisp.se/Body/f_set__1.htm
http://dorophone.blogspot.no/2008/03/common-lisp-reader-macros-simple.html
I would second Rainer's comment though, what are you trying to make?
Ok so I love your comment on the reason for this and now I know this is for 'Just because it's lisp' then I am totally on board!
Ok so you are right about lisp being great to use to make new languages because we only have to 'compile' to valid lisp code and it will run. So while we cant use the normal compiler to do the transformation of the symbols 'a and 'b to brackets we can write this ourselves.
Ok so lets get started!
(defun symbol-name-equal (a b)
(and (symbolp a) (symbolp b) (equal (symbol-name a) (symbol-name b))))
(defun find-matching-weird (start-pos open-symbol close-symbol code)
(unless (symbol-name-equal open-symbol (nth start-pos code))
(error "start-pos does not point to a weird open-symbol"))
(let ((nest-index 0))
(loop :for item :in (nthcdr start-pos code)
:for i :from start-pos :do
(cond ((symbol-name-equal item open-symbol) (incf nest-index 1))
((symbol-name-equal item close-symbol) (incf nest-index -1)))
(when (eql nest-index 0)
(return i))
:finally (return nil))))
(defun weird-forms (open-symbol close-symbol body)
(cond ((null body) nil)
((listp body)
(let ((open-pos (position open-symbol body :test #'symbol-name-equal)))
(if open-pos
(let ((close-pos (find-matching-weird open-pos open-symbol close-symbol body)))
(if close-pos
(weird-forms open-symbol close-symbol
`(,#(subseq body 0 open-pos)
(,#(subseq body (1+ open-pos) close-pos))
,#(subseq body (1+ close-pos))))
(error "unmatched weird brackets")))
(if (find close-symbol body :test #'symbol-name-equal)
(error "unmatched weird brackets")
(loop for item in body collect
(weird-forms open-symbol close-symbol item))))))
(t body)))
(defmacro with-weird-forms ((open-symbol close-symbol) &body body)
`(progn
,#(weird-forms open-symbol close-symbol body)))
So there are a few parts to this.
First we have (symbol-name-equal), this is a helper function because we are now using symbols and symbols belong to packages. symbol-name-equal gives us a way of checking if the symbols have the same name ignoring what package they reside in.
Second we have (find-matching-weird). This is a function that takes a list and and index to an opening weird bracket and returns the index to the closing weird bracket. This makes sure we get the correct bracket even with nesting
Next we have (weird-forms). This is the juicy bit and what it does is to recursively walk through the list passed as the 'body' argument and do the following:
If body is an empty list just return it
if body is a list then
find the positions of our open and close symbols.
if only one of them is found then we have unmatched brackets.
if we find both symbols then make a new list with the bit between the start and end positions inside a nested list.
we then call weird forms on this result in case there are more weird-symbol-forms inside.
there are no weird symbols then just loop over the items in the list and call weird-form on them to keep the search going.
OK so that function transforms a list. For example try:
(weird-forms 'a 'b '(1 2 3 a 4 5 b 6 7))
But we want this to be proper lisp code that executes so we need to use a simple macro.
(with-weird-forms) is a macro that takes calls the weird-forms function and puts the result into our source code to be compiled by lisp. So if we have this:
(with-weird-forms (a b)
(+ 1 2 3 a - a + 1 2 3 b 10 5 b 11 23))
Then it macroexpands into:
(PROGN (+ 1 2 3 (- (+ 1 2 3) 10 5) 11 23))
Which is totally valid lisp code, so it will run!
CL-USER> (with-weird-forms (a b)
(+ 1 2 3 a - a + 1 2 3 b 10 5 b 11 23))
31
Finally if you have settled on the 'a' and 'b' brackets you could write another little macro:
(defmacro ab-lang (&rest code)
`(with-weird-forms (a b) ,#code))
Now try this:
(ab-lang a let* a a d 1 b a e a * d 5 b b b a format t "this stupid test gives: ~a" e b b)
Cheers mate, this was great fun to write. Sorry for dismissing the problem earlier on.
This kind of coding is very important as ultimately this is a tiny compiler for our weird language where symbols can be punctuation. Compilers are awesome and no language makes it as effortless to write them as lisp does.
Peace!
I am using Dr. Racket, version 5.3.1. I am trying to use the Macro Stepper feature, and am having problems with "nested" macros. (By "nested" macros, I mean macros that expand to a form which contains more (used-defined) macros. I don't know if this is the correct terminology). The macro stepper only expands these macros once, and then doesn't bother to continue expanding.
For example, I type the following into the Dr. Racket definitions area:
#lang racket
(define-syntax foo
(syntax-rules ()
((foo a) 1)
((foo a stuff ...) (+ 1 (foo stuff ...)))))
(foo a b c d e)
Running this returns 5, as expected. Furthermore, typing (expand '(foo a b c d e)) in the Interactions window yields the syntax '(#%app + '1 (#%app + '1 (#%app + '1 (#%app + '1 '1)))), also as expected. However, going into the Macro Stepper (with standard macro hiding) and pressing the End button, I only see (+ 1 (foo b c d e)). If I disable macro hiding, I get the expected result, but also a whole lot of line noise that I'd rather not see.
Is this a bug, or expected behaviour? I swear that Dr. Racket didn't used to behave like this...
I actual submitted a bug report about this a month ago (http://bugs.racket-lang.org/query/?cmd=view&pr=13203), but then I started having second thoughts about whether it was a bug or not, so I decided to ask here.
PS - other random notes about this:
It seems to depend on whether or not the nested macro is the outer-most expression in the expanded form. For example, if I define (in addition to foo):
(define-syntax bar
(syntax-rules ()
((bar xs ...) (foo xs ...))))
(define-syntax baz
(syntax-rules ()
((baz xs ...) (bar xs ...))))
(baz a b c d e)
Then the macro stepper shows me that (baz a b c d e) expands to (bar a b c d e) to (foo a b c d e) to (+ 1 (foo b c d e)), but then it stops.
The previous example might make you think it has something to do with macros that expand to themselves, but this doesn't appear to be the case. For example, if I redefine foo as follows:
(define-syntax foo
(syntax-rules ()
((foo a) 1)
((foo a stuff ...) (+ 1 (blah stuff ...)))))
With
(define-syntax blah
(syntax-rules ()
((blah xs ...) 10)))
Then (foo a b c d e) expands to (+ 1 (blah b c d e)) and then stops.
I'm not sure if this is a bug or not, although the foo in the expanded code is a different color then the original foo, so I'm inclined to think that is what is confusing it.
By default, the macro stepper tries to simplify the expanded macro to show only macros defined in the module, and files required with strings (i.e. files from your 'project'). This is the feature that seems to be throwing it off.
One way you can work around this (at least in smallish files) is to disable this feature. To do this, go to the bottom left of the window where it says: Macro hiding:, click the drop down menu and select Disable.
Macro hiding: -> Disable
From there, you should see the entire expansion of your module, including the expansion of foo.
In Python, I can do this:
>>> def foo(x,y,z=1):
return x+y*z
>>> foo.func_code.co_varnames
('x', 'y', 'z')
>>> foo.func_defaults
(1,)
And from it, know how many parameters I must have in order to call foo(). How can I do this in Common Lisp?
Most implementations provide a way of doing this, but none is standardized. If you absolutely need it, Swank (the Common Lisp part of SLIME) has a function called swank-backend:arglist that, as far as I can see, does what you want:
CCL> (swank-backend:arglist 'if)
(TEST TRUE &OPTIONAL FALSE)
CCL> (swank-backend:arglist 'cons)
(X Y)
CCL> (swank-backend:arglist (lambda (a b c &rest args)))
(A B C &REST ARGS)
I'm not sure you can rely on it remaining available in the future, though.
Usually most Lisps have a function called ARGLIST in some package. LispWorks calls it FUNCTION-LAMBDA-LIST.
For information purposes in LispWorks, if one has the cursor on a function symbol, then control-shift-a displays the arglist. In LispWorks there is also an 'arglist-on-space' functionality that can be loaded. After typing a symbol and a space, the IDE displays the arglist.
There is also the CL:DESCRIBE function. It describes various objects. In most CL implementations it also should display the arglist of a function.
The following example is for Clozure Common Lisp:
Welcome to Clozure Common Lisp Version 1.6-r14468M (DarwinX8664)!
? (defun foo (x y &optional (z 1)) (+ x (* y z)))
FOO
? (arglist #'foo)
(X Y &OPTIONAL Z)
:ANALYSIS
? (describe #'foo)
#<Compiled-function FOO #x302000550F8F>
Name: FOO
Arglist (analysis): (X Y &OPTIONAL Z)
Bits: 8405508
...
If you want to know this just when editing, SLIME+emacs will take care of that for you.
e.g. In emacs lisp-mode + slime, typing
(format
will display the arguments of format in the minibuffer on the bottom.
At the moment I'm working through "Practical Common Lisp" from Peter Seibel.
In the chapter "Practical: A Simple Database" (http://www.gigamonkeys.com/book/practical-a-simple-database.html) Seibel explains keyword parameters and the usage of a supplied-parameter with the following example:
(defun foo (&key a (b 20) (c 30 c-p)) (list a b c c-p))
Results:
(foo :a 1 :b 2 :c 3) ==> (1 2 3 T)
(foo :c 3 :b 2 :a 1) ==> (1 2 3 T)
(foo :a 1 :c 3) ==> (1 20 3 T)
(foo) ==> (NIL 20 30 NIL)
So if I use &key at the beginning of my parameter list, I have the possibility to use a list of 3 parameters name, default value and the third if the parameter as been supplied or not. Ok.
But looking at the code in the above example:
(list a b c c-p)
How does the lisp interpreter know that c-p is my "supplied parameter"?
Let's reindent the function foo:
(defun foo (&key a
(b 20)
(c 30 c-p))
(list a b c c-p))
If you indent it like this you will see that the function has three keyword parameters: a, b and c. These are available in the body of the function.
For the keyword parameter c there is a variable declared c-p that will be T or NIL depending whether c has been passed when foo gets called.
A keyword parameter generally can be declared as one of the following options:
as a single variable name
a list of a variable name and a default value
a list of a variable name, a default value and a variable that will show whether the parameter has been passed or not when the function gets called
The supplied-p is particularly interesting when one wants to see whether the value comes from the call or the default value:
(defun make-my-array (size &key (init-value nil init-value-supplied-p))
(if init-value-supplied-p
(make-array size :initial-element init-value)
(make-array size)))
Now the user can init the elements to NIL:
(make-my-array 10 :init-value nil)
Here the default value and the supplied value can both be NIL, but we need to make a difference. The variable init-value-supplied-p makes it possible to see whether the NIL value of the variable init-value comes from the default or from the function call.
It's difficult to tell what you are asking. c-p is bound to T or NIL, depending on whether c is supplied as a parameter. This binding is then available to the body of the function.