Function argument as part of path to a file in Clojure - csv

Suppose I have the same file name, placed in five different sub-folders. The file in question has the same name in all folders but otherwise has different values.
Suppose my file is called something like test.csv. My folder are A1,A2,A3,A4 and A5.
My data-read structure looks as so:
(defn my-data [folder]
(loop [SUB-FOLDER (str 'folder)
X []
data (with-open [file (clojure.java.io/reader "./resources/SUB-FOLDER/test.csv")]
(doall (csv/read-csv file)))]
(def row (first data))
(if (nil? row)
[(lazy-seq X)]
(recur (conj X (map #(Float/parseFloat %) row))
(rest data)))))
I would call this function as so
(def Y (map vec (get (my-data A1) 0)))
Where I am trying to access the file test.csv in the sub-folder A1 which I am passing as an argument to my csv-read function.
Now obviously the above code does not work, but it provides an overview of what I am trying to achieve.
How could one make the minimal example work?
Thanks.

Something like this should put your data from one folder into a sequence of sequences:
(defn read-data [folder]
(let [data (csv/read-csv (slurp (str "./resources/" folder "/test.csv")))]
(for [line data]
(map #(Float/parseFloat %) line))))
Change map to mapv if you want to have vectors, and wrap the for with into [] if you want a vector of vectors. This assumes folder is a string. Because your files are very small you don't need to open them with a reader, it's easier to slurp them and then parse them.
A fe issues with your original code:
You're always trying to read a file called "./resources/SUB-FOLDER/test.csv" instead of replacing the name of your folder.
You don't want to use def inside a function. See let.
Calling lazy-seq on an already realized sequence doesn't do anything.
By calling doall on your reader you're forcing all your data into memory instead of reading it and processing it as you go (that's why I replaced it with slurp). If you're going to process it in a loop as you read it, you want the with-open outside the loop (and no doall).

Related

ELISP interactive function with both prefix argument and user input as optional arguments

In ELISP, the documentation for interactive codes mentions:
P -- Prefix arg in raw form. Does not do I/O.
...
s -- Arbitrary text, read in the minibuffer and returned as a string ... Prompt.
I presumed that I could write a function with an optional prefix argument, as in:
(defun some-function (&optional prefix)
(interactive "P")
...
)
or a function with user input, as in:
(defun some-function (user-argument)
(interactive "sProvide an argument: ")
...
)
but not both. Then I found the Org-mode function org-match-sparse-tree, which I can call with C-u C-c \, where the prefix argument restricts the match to open org-mode headings and I am still prompted for a match. The source code is below and I cannot find how the variable match is assigned:
(defun org-match-sparse-tree (&optional todo-only match)
"..."
(interactive "P")
(org-agenda-prepare-buffers (list (current-buffer)))
(let ((org--matcher-tags-todo-only todo-only))
(org-scan-tags 'sparse-tree (cdr (org-make-tags-matcher match))
org--matcher-tags-todo-only)))
How does this function take both prefix argument and user input?
How does this function [interactively] take both prefix argument and user input?
It doesn't -- the match argument is not obtained, and is therefore nil. What you're seeing is the effect of the subsequent call to (org-make-tags-matcher match) with that nil value as the argument:
(defun org-make-tags-matcher (match)
"..."
(unless match
;; Get a new match request, with completion against the global
;; tags table and the local tags in current buffer.
(let ((org-last-tags-completion-table
(org-tag-add-to-alist
(org-get-buffer-tags)
(org-global-tags-completion-table))))
(setq match
(completing-read
"Match: "
'org-tags-completion-function nil nil nil 'org-tags-history))))
...)
Functions can take multiple interactive arguments, though.
See C-hf interactive
To pass several arguments to the command, concatenate the individual strings, separating them by newline characters.
The very first example in that help demonstrates this:
(defun foo (arg buf) "Doc string" (interactive "P\nbbuffer: ") .... )
This is elaborated upon at (elisp)Using Interactive -- up one level in the documentation you'd linked to:
It may be a string; its contents are a sequence of elements
separated by newlines, one for each argument(1). Each element
consists of a code character (*note Interactive Codes::) optionally
followed by a prompt (which some code characters use and some
ignore). Here is an example:
(interactive "P\nbFrobnicate buffer: ")
The code letter ‘P’ sets the command’s first argument to the raw
command prefix (*note Prefix Command Arguments::). ‘bFrobnicate
buffer: ’ prompts the user with ‘Frobnicate buffer: ’ to enter the
name of an existing buffer, which becomes the second and final
argument.
You should read that documentation fully, though -- there are more sophisticated things you can do, including writing arbitrary elisp to produce the interactive arguments (which may or may not involve prompting the user).

Run Lisp functions on load

Whenever I (load "program.lisp") using the following code I get the error: "Error: Unexpected end of #input stream "program.lisp"
(defun theProgram ()
(reset)
(print "Hello Kappa")
(setentries)
(startloop)
(loop for x in mylist collect (splitremove))
(loop for x in numlist collect (getgrades))
(loop for x in namelist collect (getprint))
(loop for x in printlist collect (andprint)))
(theProgram)
I know the last line is the problem and it will work fine if it is not included however I need the program to startup on load, how can I achieve this?
Edit: I should note that setentries calls a (read) and so does startloop. I am using GNU common lisp 2.6 with gcl interpreter.
The actual error was that the (read) part in the functions did not have stream declared so it was reading the input from the script as it was running rather than from the terminal.

Emacs function automaticly accepting prompt

I am trying to find a way to automatically accept the first proposal from the minibuffer.
(defun find-file-at-point-without-prompt ()
(interactive )
(find-file-at-point)
)
Calling results in the prompt: "Find file or URL: ......". I just want an automatic "yes".
Passing arguments does not work. It might be interesting for other cases as well. I used a macro before that would just call find-file-at-point followed by a RET.
It seems there is no variable to automatically accept the prompt.
You can redefine a function ffap-read-file-or-url by removing a part which is doing the prompt. It remains something like this
(defun ffap-read-file-or-url (prompt guess)
"Read file or URL from minibuffer, with PROMPT and initial GUESS."
(or guess (setq guess default-directory))
(let (dir)
;; Tricky: guess may have or be a local directory, like "w3/w3.elc"
;; or "w3/" or "../el/ffap.el" or "../../../"
(or (ffap-url-p guess)
(progn
(or (ffap-file-remote-p guess)
(setq guess
(abbreviate-file-name (expand-file-name guess))
))
(setq dir (file-name-directory guess))))
;; Do file substitution like (interactive "F"), suggested by MCOOK.
(or (ffap-url-p guess) (setq guess (substitute-in-file-name guess)))
;; Should not do it on url's, where $ is a common (VMS?) character.
;; Note: upcoming url.el package ought to handle this automatically.
guess))

Clojure : missing namespace errors when running "use" at the REPL

I have a .clj file that starts like this :
(ns clojure_crawl.core)
(require '[clj-http.client :as client])
(use 'clojure.contrib.json)
Followed by several function definitions :
(defn f1 [] "" (+ 1 1))
(defn f2 [] "" (+ 2 2))
etc...
However, when I run the command "(use 'myfile.core :reload)"
Some of my functions , although visible at the REPL, cannot run do to "missing namespace" errors.
How do I add the dependencies so that the REPL can run any of the functions defined in my file ?
If your code is in "clojure_crawl/core.clj", its namespace should be clojure-crawl.core (note the hyphen). See http://clojure.org/libs
As Joost already said, you have to be careful with hyphens and underscores: wherever you use a hyphen in your namespace names, replace it with an underscore in the corresponding file/directory names (and vice versa).
Also, the use of the require and use functions in clj source files is discouraged. Instead, declare the libraries you need directly in the ns macro:
(ns clojure-crawl.core
(:require [clj-http.client :as client])
(:use clojure.contrib.json))
This also takes the burden of properly quoting the required namespaces from you.

Compojure HTML Formatting

I'm relatively new to Clojure and a complete HTML/Compojure virgin. I'm trying to use Compojure to create static pages of HTML using a function similar to this:
(defn fake-write-html
[dir args]
(let [file (str dir *file-separator* *index-file*)
my-html (html
(doctype :html4)
[:html
[:head
[:title "Docs and Dirs:"]]
[:body
[:div
[:h2 "A nice title"]]
[:div
[:ul
[:li "One"]
[:li "Two"]]]]])]
(clojure.contrib.duck-streams/spit file my-html)))
The function just writes HTML to a file. (The args argument is irrelevant here. Just there to assure the example compiles and runs in my program.)
"Programming Clojure" indicated that the call to the html function would produce formatted HTML -- multiple lines with indentation. All I get is the doc type as expected followed by all of the HTML on a single line. HTML Tidy doesn't find any issues with the content of the output file. It comes out as a single line if I println it at the REPL too.
Is there something else needed to get formatted output?
The formatting of HTML output in Compojure was removed for performance and complexity reasons. To get formatted output you will probably have to write your own printer function.
I usually output HTML as Compojure sees fit and use Firebug to view it live in my browser. Firebug will display it nicely formatted no matter if it's really all on one line or not. This works well enough most of the time. If you need to serialize this HTML in a readable form, you could keep it as Clojure vectors and sexps and serialize it that way.
Although Brian's answer pointed me to Firebug, enabling the debugging I wanted, I was just to obsessive-compulsive to leave it alone. Following up on kwertii's pointer to JTidy, I included the following code in my program.
Edit: Simplified the code somewhat
(ns net.dneclark.someprogram
(:gen-class)
...
(:import (org.w3c.tidy Tidy))
)
...
(defn configure-pretty-printer
"Configure the pretty-printer (an instance of a JTidy Tidy class) to
generate output the way we want -- formatted and without sending warnings.
Return the configured pretty-printer."
[]
(doto (new Tidy)
(.setSmartIndent true)
(.setTrimEmptyElements true)
(.setShowWarnings false)
(.setQuiet true)))
(defn pretty-print-html
"Pretty-print the html and return it as a string."
[html]
(let [swrtr (new StringWriter)]
(.parse (configure-pretty-printer) (new StringReader (str html)) swrtr)
(str swrtr)))
I added the jtidy-r938.jar to my project (NetBeans using the enclojure plugin) and imported it. The configuration function tells the parser to output formatted, indented HTML and skip the warnings. The return value from the pretty-printer function is now nicely formatted whether I open it with Firebug or a simple text editor.
There are tons of HTML pretty printers available for Java, notably JTidy, a Java port of HTML Tidy. You can easily feed Clojure's output through this library programatically and get neatly indented and formatted HTML back.
HTML Tidy is also available as a command-line program for Unix if you'd care to go that route -- you can just pipe your HTML through it like any other shell program.
The above did not work for me.
I changed this a bit.
add this [jtidy "4aug2000r7-dev"] to project.clj
(:use clojure.core)
(:import (org.w3c.tidy Tidy))
(:import (java.io ByteArrayInputStream ByteArrayOutputStream)))
(defn configure-pretty-printer
"Configure the pretty-printer (an instance of a JTidy Tidy class) to
generate output the way we want -- formatted and without sending warnings.
Return the configured pretty-printer."
[]
(doto (new Tidy)
(.setSmartIndent true)
;(.setTrimEmptyElements true)
(.setShowWarnings false)
(.setQuiet true)))
(defn pretty-print-html
"Pretty-print the html and return it as a string."
[html]
(let [swrtr ( ByteArrayOutputStream.)]
(.parse (configure-pretty-printer) (ByteArrayInputStream. (.getBytes (str html))) swrtr)
(str swrtr)))
If anyone is still looking at this query, you need the hiccup library. If formats HTML from exactly the Clojure data structure shown.
So
(require '[hiccup.core :refer [html]])
(defn fake-write-html
[dir args]
(let [file (str dir *file-separator* *index-file*)
my-html (html
[:html
[:head
[:title "Docs and Dirs:"]]
[:body
[:div
[:h2 "A nice title"]]
[:div
[:ul
[:li "One"]
[:li "Two"]]]]])]
(clojure.contrib.duck-streams/spit file my-html)))
will work exactly as the original poster intended. Strongly recommended.