Unpacking a list in Clojure - clojure

I am using the Analemma library to make some svg figures. To make more complicated figures I wanted to break up the svg into components that could be generated in a different function and passed to the main svg function. Simple enough idea, right?
Well I keep getting tripped up when I try to pass a list of values and am not really sure how to get around the issue. In python you would be able to unpack the list using *list and I am wondering what an equivalent would be in clojure.
If there is no equivalent I wold appreciate any pointers about how to accomplish the same goal.
(use 'analemma.svg)
;set a line
(def oneline (->
(line 0 0 100 100)
(style :stroke "#006600" :stroke-width 3)))
;create an SVG by passing one or more line elements works fine
; this works
(svg oneline)
; so does this
(svg oneline oneline)
; but if i have a list of lines created in a different function i have a problem
(def manylines (repeat 5 oneline))
; this will not work
(svg manylines)
;I've tried the following but this doensn't work eaither becasue it mushes the list all together
(svg (apply concat manylines))
thanks
zach cp

maybe you are looking for something like
(apply svg manylines)
this would produce same result as
(svg oneline oneline oneline oneline oneline)

Related

Clojure - Quoting a List Adds "quote" text to list - How Do I Remove This?

I have the scenario where I have a map that has a field that is going to be a series of nested lists to create a tree like structure. I've quoted the lists with ' so that it works, without that I get errors as it tries to execute it.
(def test-map
{:tree '("1" "2" "3" '("1" "2"))})
The problem is this seems to add the word "quote" to the actual list.
(:tree test-map)
;("1" "2" "3" (quote ("1" "2")))
(first (last (:tree test-map)))
;quote
My question is how can I get rid of this "quote" text. My goal is to be able to work through these types of list by a certain number and be able to output the strings in sequence at a given depth.
(for [text (second (last (:tree test-map)))]
text)
This is a basic idea, but it feels weird having to use second here when visually looking at it the list I'm working through is the first item.
Is there a way to do what I want with lists? Is it a better idea to use vectors?
Just don't quote the inner list. Quotation applies to an entire nested structure, so if you wish to build a particular data structure you can just put a quote at the front and then write out the data structure normally.

manipulate regexp-search matches using `query-regexp-replace` in a defun

Since version 22 of Emacs, we can use \,(function) for manipualting (parts of) the regex-search result before replacing it. But – this is mentioned often, but nonetheless still the truth – we can use this construct only in the standard interactive way. (Interactive like: By pressing C-M-% or calling query-replace-regexp with M-x.)
As an example:
If we have
[Foo Bar 1900]
and want to get
[Foo Bar \function{foo1900}{1900}]
we can use:
M-x query-replace-regexp <return>
\[\([A-Za-z-]+\)\([^0-9]*\) \([0-9]\{4\}\)\]
[\1\2 \\function{\,(downcase \1)\3}{\3}]
to get it done. So this can be done pretty easy.
In my own defun, I can use query only by replacing without freely modifying the match, or modify the prepared replaced string without any querying. The only way I see, is to serialize it in such a way:
(defun form-to-function ()
(interactive)
(goto-char (point-min))
(while (query-replace-regexp
"\\[\\([A-Za-z-]+\\)\\([^0-9]*\\) \\([0-9]\\{4\\}\\)\\]"
"[\\1\\2 \\\\function{\\1\\3}{\\3}]" ))
(goto-char (point-min))
(while (search-forward-regexp "\\([a-z0-9]\\)" nil t)
(replace-match (downcase (match-string 1)) t nil)
)
)
For me the query is important, because I can't be sure, what the buffer offers me (= I can't be sure, the author used this kind of string always in the same manner).
I want to use an elisp function, because it is not the only recurring replacement (and also not only one buffer (I know about dired-do-query-replace-regexp but I prefer working buffer-by-buffer with replace-defuns)).
At first I thought I only miss something like a query-replace-match to use instead of replace-match. But I fear, I am also missing the easy and flexible way of rearrange the string the the query-replace-regexp.
So I think, I need a \, for use in an defun. And I really wonder, if I am the only one, who is missing this feature.
If you want your rsearch&replace to prompt the user, that means you want it to be interactive, so it's perfectly OK to call query-replace-regexp (even if the byte-compiler will tell you that this is meant for interactive use only). If the warning bothers you, you can either wrap the call in with-no-warnings or call perform-replace instead.
The docstring of perform-replace sadly doesn't (or rather "didn't" until today) say what is the format of the replacements argument, but you can see it in the function's code:
;; REPLACEMENTS is either a string, a list of strings, or a cons cell
;; containing a function and its first argument. The function is
;; called to generate each replacement like this:
;; (funcall (car replacements) (cdr replacements) replace-count)
;; It must return a string.
The query-replace-function can handle replacement not only as a string, but as a list including the manipulating elements. The use of concat archives building an string from various elements.
So one who wants to manipulate the search match by a function before inserting the replacement can use query-replace-regexp also in a defun.
(defun form-to-function ()
(interactive)
(goto-char (point-min))
(query-replace-regexp
"\\[\\([A-Za-z-]+\\)\\([^0-9]*\\) \\([0-9]\\{4\\}\\)\\]"
(quote (replace-eval-replacement concat "[\\1\\2 \\\\function{"
(replace-quote (downcase (match-string 1))) "\\3}{\\3}]")) nil ))
match-string 1 returns the first expression of our regexp-search.
`replace-quote' helps us doublequoting the following expression.
concat forms a string from the following elements.
and
replace-eval-replacement is not documented.
Why it is in use here nevertheless, is because of emacs seems to use it internally, while performing the first »interactive« query-replace-regexp call. At least is it given by asking emacs with repeat-complex-command.
I came across repeat-complex-command (bound to [C-x M-:].) while searching for an answer in the source code of query-replace-regexp.
So an easy to create defun could be archieved by performing the standard search and replace way as told in the question and after first sucess pressing [C-x M-:] results in an already Lisp formed command, which can be copied and pasted in a defun.
Edit (perform-replace)
As Stefan mentioned, one can use perform-replace to avoid using query-replace-regexp.
Such a function could be:
(defun form-to-function ()
(interactive)
(goto-char (point-min))
(while (perform-replace
"\\[\\([A-Za-z-]+\\)\\([^0-9]*\\) \\([0-9]\\{4\\}\\)\\]"
(quote (replace-eval-replacement concat "[\\1\\2 \\\\function{"
(replace-quote (downcase (match-string 1))) "\\3}{\\3}]"))
t t nil)))
The first boolean (t) is a query flag, the second is the regexp switch. So it works also perfectly, but it didn't help finding the replacement expression as easy as in using \,.

How do I beautify lisp source code?

My code is a mess many long lines in this language like the following
(defn check-if-installed[x] (:exit(sh "sh" "-c" (str "command -v " x " >/dev/null 2>&1 || { echo >&2 \"\"; exit 1; }"))))
or
(def Open-Action (action :handler (fn [e] (choose-file :type :open :selection-mode :files-only :dir ListDir :success-fn (fn [fc file](setup-list file)))) :name "Open" :key "menu O" :tip "Open spelling list"))
which is terrible. I would like to format it like so
(if (= a something)
(if (= b otherthing)
(foo)))
How can I beautify the source code in a better way?
The real answer hinges on whether you're willing to insert the newlines yourself. Many systems
can indent the lines for you in an idiomatic way, once you've broken it up into lines.
If you don't want to insert them manually, Racket provides a "pretty-print" that does some of what you want:
#lang racket
(require racket/pretty)
(parameterize ([pretty-print-columns 20])
(pretty-print '(b aosentuh onethunoteh (nte huna) oehnatoe unathoe)))
==>
'(b
aosentuh
onethunoteh
(nte huna)
oehnatoe
unathoe)
... but I'd be the first to admit that inserting newlines in the right places is hard, because
the choice of line breaks has a lot to do with how you want people to read your code.
I use Clojure.pprint often for making generated code more palatable to humans.
it works well for reporting thought it is targeted at producing text. The formatting built into the clojure-mode emacs package produces very nicely formatted Clojure if you put the newlines in your self.
Now you can do it with Srefactor package.
Some demos:
Formatting whole buffer demo in Emacs Lisp (applicable in Common Lisp as well).
Transform between one line <--> Multiline demo
Available Commands:
srefactor-lisp-format-buffer: format whole buffer
srefactor-lisp-format-defun: format current defun cursor is in
srefactor-lisp-format-sexp: format the current sexp cursor is in.
srefactor-lisp-one-line: turn the current sexp of the same level into one line; with prefix argument, recursively turn all inner sexps into one line.
Scheme variants are not as polished as Emacs Lisp and Common Lisp yet but work for simple and small sexp. If there is any problem, please submit an issue report and I will be happy to fix it.

What is the difference between ; and ;; in Clojure code comments?

What is the difference between ; and ;; when starting a comment in Clojure? I see that my text editor colours them differently, so I'm assuming there is notionally some difference.
I also see that Marginalia treats them differently:
; Stripped entirely
;; Appears in text section of marginalia
(defn foobar []
; Appears in code section of marginalia output
;; Again, appears in code section of marginalia output
6)
There is no difference as far as the interpreter is concerned. Think of ; ;; ;;; and ;;;; as different heading levels.
Here is my personal use convention:
;;;; Top-of-file level comments, such as a description of the whole file/module/namespace
;;; Documentation for major code sections (i.e. groups of functions) within the file.
;; Documentation for single functions that extends beyond the doc string (e.g. an explanation of the algorithm within the function)
; In-line comments possibly on a single line, and possibly tailing a line of code
Check out the official description of the meaning of ; vs ;; in elisp: since the Clojure indenter is basically the same, it will treat them similarly. Basically, use ; if you are writing a long sentence/description "in the margins" that will span multiple lines but should be considered a single entity. Their example is:
(setq base-version-list ; there was a base
(assoc (substring fn 0 start-vn) ; version to which
file-version-assoc-list)) ; this looks like
; a subversion
The indenter will make sure those stay lined up next to each other. If, instead, you want to make several unrelated single-line comments next to each other, use ;;.
(let [x 99 ;; as per ticket #425
y "test"] ;; remember to test this
(str x y)) ;; TODO actually write this function
Emacs ; to be used for end-of-line comments and will indent in surprising ways if that is not your intent. ;; does not so I usually use ;;.
Clojure doesn't care - any line is ignored from the ; to EOL.
I believe there is a tradition in CL of using increasing numbers of ; to indicate more important comments/sections.
no meaning for the language. ; is a reader macro for comment
perhaps other tools parse them but "within clojure" they are the same.
There is no difference from a Clojure-perspective. I find that ;; stands out a little better than ;, but that's only my opinion.
Marginalia on the other hand treats them differently because there are times when a comment should remain in the code section (e.g. license) and those are flagged with ;. This is an arbitrary decision and may change in the future.
In emacs lisp modes including clojure-mode, ;; is formatted with the convention of being at the beginning of a line, and indented as as any other line, based on the context. ; is expected to be used at the end of a line, so emacs will not do what you want it to if you put a single-semicolon comment at the beginning of a line expecting it to tab to the indentation for the present context.
Example:
(let [foo 1]
;; a comment
foo) ; a comment
I'm not sure (not used Clojure and never heard of this before), but this thread might help.

in emacs-lisp, how do I correctly use replace-regexp-in-string?

Given a string, I want to replace all links within it with the link's description. For example, given
this is a [[http://link][description]]
I would like to return
this is a description
I used re-builder to construct this regexp for a link:
\\[\\[[^\\[]+\\]\\[[^\\[]+\\]\\]
This is my function:
(defun flatten-string-with-links (string)
(replace-regexp-in-string "\\[\\[[^\\[]+\\]\\[[^\\[]+\\]\\]"
(lambda(s) (nth 2 (split-string s "[\]\[]+"))) string))
Instead of replacing the entire regexp sequence, it only replaces the trailing "]]". This is what it produces:
this is a [[http://link][descriptiondescription
I don't understand what's going wrong. Any help would be much appreciated.
UPDATE: I've improved the regex for the link. It's irrelevant to the question but if someone's gonna copy it they may as well get the better version.
Your problem is that split-string is clobbering the match data, which
replace-regexp-in-string is relying on being unchanged, since it is going to
go use that match data to decide which sections of the string to cut out. This
is arguably a doc bug in that replace-regexp-in-string does not mention that
your replacement function must preserve the match data.
You can work around by using save-match-data, which is a macro provided for
exactly this purpose:
(defun flatten-string-with-links (string)
(replace-regexp-in-string "\\[\\[[a-zA-Z:%#/\.]+\\]\\[[a-zA-Z:%#/\.]+\\]\\]"
(lambda (s) (save-match-data
(nth 2 (split-string s "[\]\[]+")))) string))