I want to create a json representation of one known key and variable amount of unknown:
(defn test1 [var1 & var2]
(print json/write-str :key1 var1 var2))
(defn -main [& args]
(test1 "key1_val" {:key2 "val2" :key3 "val3"}))
It returns this:
:key1 key1_val ({:key2 val2, :key3 val3})
I want it to be a single dictionary. I wonder, is what the method returned really what I'm looking for? I think not because the 2nd part is in the parentheses.
(print json/write-str :key1 var1 var2)
This prints the function value of json/write-str, followed by the value of each of the keys. In clojure if you want a function to run, you must apply it, this is usually done by wrapping it in parenthesis.
Next, write-str takes multiple args, but the only arg that is turned into json is the first, so you need to wrap your data in a data structure.
I'm not sure how you really want the data structured, but something like this is closer I think:
(json/write-str {:key1 [var1 var2]})
Also, as a minor note, the code did not return :key1 key1_val ({:key2 val2, :key3 val3}), it printed the string ":key1 key1_val ({:key2 val2, :key3 val3})", and returned nil, because println always returns nil.
Related
Why does the following Clojure program throw a NullPointerException?
user=> (defn x []
"Do two things if the expression is true."
(if true ((println "first expr") (println "second expr")) false))
user=> (x)
first expr
java.lang.NullPointerException (NO_SOURCE_FILE:0)
second expr
This is a simplified version of my actual use case, where I want to execute maybe three statements (pull values from the DB) before returning a map - {:status 200, :body "Hello World"} inside of the branch.
It is trying to treat the result of the first println as a function to call on the second println function.
You need a do.
(defn x []
"Do two things if the expression is true."
(if true (do (println "first expr") (println "second expr")) false))
(x)
The do special form (progn in CL, begin in Scheme) executes each of its arguments in sequence and returns the result of the last one.
If nil is ok as a return value in the else case, consider using when which has an implicit do block:
(defn x []
"Do two things if the expression is true."
(when true
(println "first expr")
(println "second expr")))
Not that it matters in your particular case, but do know the difference between (do ...) which will load each form in its own classloader, and an empty let form (let [] ...) which evaluates the whole form in a single classloader.
I am trying to save data into a collection of some sort, but the program that I have is saving everything into a separate map. I want to make it one map.
(defn readFile []
(map (fn [line] (clojure.string/split line #";"))
(with-open [rdr (reader "C:/Users/Rohil/Desktop/textfile.txt")]
(doseq [[idx line] (map-indexed vector(line-seq rdr))]
(if(.contains line "201609")
(if(not(.contains line "TBA"))
(println(assoc table :code(nth(clojure.string/split line #";")3) :instructor(nth(clojure.string/split line #";")19)))
)
)
)
)
)
)
)
Any help will be appreciated.
Looks like you are adapting to clojure :-) I went to the same process. Hang on, it will be worth it!
First: it is important to realize that map will save the result of the function into a new collection. Like cfrick mentions, println returns nil and assoc does not change a map.
I'm guessing a bit here what you are trying to do: You want to have a collection of dicts, where every dict has two keys, like so:
[
{ :code 1 :instructor "blah"}
{ :code 2 :instructor "boo" }
]
You need these values to come from a file, but you only want to save the lines where the line contains "201609" but not "TBA"
First some general remarks:
You probably want to split this function into smaller parts. One could be the check for lines (contains 201609 but not tba ), another could read the file...
I know it is the title of your question, but most likely there is a better way than to change a global variable. Maybe you could make the function readFile return the table?
try if you can pass in arguments to your function.
I'm not sure what you are trying to do with the line (doseq [[... Please give us more context there. I will ignore it
Here is a possible solution:
(ns test
(:require [clojure.string :as s]
[clojure.java.io :as io]))
(defn line-filter [include exclude line]
(and (not (s/includes? line exclude))
(s/includes? line include)))
(defn process-line [line]
(let [line-parts (s/split line #";")
code (nth line-parts 3)
instructor (nth line-parts 19)]
{:code code :instructor instructor}))
(defn read-file [file-name]
(s/split (slurp (io/resource file-name)) #"\n"))
(defn parse-lines [lines]
(map process-line lines))
(defn read-file-and-parse
"This function will read a file, process the lines, and output a collection of maps"
[filename search-for exclude]
(parse-lines
(filter #(line-filter search-for exclude %)
(read-file filename))))
you could now call this function like this: (read-file-and-parse "test.txt" "201609" "TBA")
If you want to add the result of this function into your table, you can use concat. But again, this will return a new version of your list (with new entries added) and not change the one you defined earlier.
Welcome to functional programming :-)))
I am trying to reduce a list and add some data into a map.
The code is something like this:
map = Enum.reduce(1..1000, %{}, fn(x, accumalator) ->(
calculate a hash of a string
if condition is fulfilled do
Map.put(accumalator, string, hash)
end
)end)
This is giving me a bad map error saying that Map.put() is receiving a nil value for the put function.
What I want to do is this: For all the iterations calculate the hash and if some condition is fulfilled regarding the hash add the hash and the nonce into the map. So I want the map to be persistent. Where am I going wrong?
This answer also suggests the same thing, but is failing.
The value returned by the function becomes the accumulator in the next iteration. In the function you've defined, if the condition is false, the if returns nil and in the next iteration accumulator is nil. What you need to do is add an else block and return the unmodified accumulator value from that.
Enum.reduce(1..1000, %{}, fn(x, accumulator) ->
...
if condition do
Map.put(accumulator, string, hash)
else
accumulator
end
end)
I've got a recursive function (scavenged from github):
(defn delete-recursively [fname]
(let [func (fn [func f]
(when (.isDirectory f)
(doseq [f2 (.listFiles f)]
(func func f2)))
(clojure.java.io/delete-file f))]
(func func (clojure.java.io/file fname))))
I can't figure out this func thing. I need help :)
Why is it possible to use the same symbol func for
the name the function is bound to,
the name of an argument in the fn form,
the called function and
the first parameter of the call?
Or is something else going on?
Written from my phone so I apologize.
This function seems needlessly obfuscated.
"func"is a function that delete normal files if given a file and apply a function "f" passed as parameter to all files in a directory if given a directory.
Now "func"is given to "func" as "f" parameter so it does its job recursively.
Easy :3
Using #x... like below one obtains the decimal of hex value
> #xB1
177
> #xA5
165
> #xFF
255
Say we have a list of hex, what is the correct syntax using mapcar #x... over the list? Below doesn't work:
> (mapcar #'(lambda (hex) `(#x,hex)) '(B1 A5 FF))
Reader error: Malformed number in a #b/#o/#x/#r macro.
[Condition of type SIMPLE-ERROR]
Thanks.
The #x is what's called a "reader macro". It is very similar to using quotations (ie "") to represent strings. They are executed when the code is read/compiled. What you actually want is a procedure which can convert from hexadecimal strings at run time. The procedure you are looking for is parse-integer, which takes a string and returns the value it represents. The mapcar with it should look something like this:
(mapcar (lambda (hex)
(parse-integer hex :radix 16))
'("B1" "A5" "FF"))
Note that this is using strings, if you want to use symbols as in your suggestion you would have to do something like this:
(mapcar (lambda (hex)
(parse-integer (symbol-name hex) :radix 16))
'(B1 A5 FF))
If you don't know the difference between a symbol and a string, I would suggest reading this: What exactly is a symbol in lisp/scheme?
It occurs to me that while the best solution for this problem is probably one using parse-integer as mentioned in malisper's answer, there is a sense in which this could be solved with a mapping based approach.
When we write something like #xB1, we're not explicitly invoking a function. Instead, we're using the fact that # is a dispatching read macro character, and that there's a function installed for the subcharacter x that reads numbers written in hexadecimal. That means that by the time the evaluator or compiler gets a form, the number is already there. However, we do have access to the function that is doing the processing of the hexadecimal string, using get-dispatch-macro-character. Viz.:
CL-USER> (get-dispatch-macro-character #\# #\x)
#<FUNCTION SB-IMPL::SHARP-X> ; in SBCL
CL-USER> (get-dispatch-macro-character #\# #\x)
#<SYSTEM-FUNCTION SYSTEM::HEXADECIMAL-READER> ; in CLISP
What can we do with that function? How would we use it?
2.1.4.4 Macro Characters
… If a character is a dispatching macro character C1, its reader macro
function is a function supplied by the implementation. This function
reads decimal digit characters until a non-digit C2 is read. If any
digits were read, they are converted into a corresponding integer
infix parameter P; otherwise, the infix parameter P is nil. The
terminating non-digit C2 is a character (sometimes called a
``sub-character'' to emphasize its subordinate role in the
dispatching) that is looked up in the dispatch table associated with
the dispatching macro character C1. The reader macro function
associated with the sub-character C2 is invoked with three arguments:
the stream, the sub-character C2, and the infix parameter P. For more
information about dispatch characters, see the function
set-dispatch-macro-character.
That means that when we write something like #xB1, the function above is getting called with a stream from which it can read B1, the character x, and nil. We can try calling that function with arguments like that, although we can't be quite sure what will happen, because implementations might make different assumptions about where the function will be called from.
For instance, this works without a problem in CLISP, but SBCL assumes that the function should be called recursively from read (which we're not doing):
CL-USER> (funcall (get-dispatch-macro-character #\# #\x)
(make-string-input-stream "B1")
#\x
nil)
177 ; in CLISP
CL-USER> (funcall (get-dispatch-macro-character #\# #\x)
(make-string-input-stream "B1")
#\x
nil)
; Evaluation aborted on #<SB-INT:SIMPLE-READER-ERROR "~A was invoked
; with RECURSIVE-P being true outside of a recursive read operation."
; {1005F245B3}>. ; in SBCL
That said, for implementations where this will work, we can easily write a mapcar-like function to extract a dispatch macro character function and map it over some strings. Thus, in an implementation where this works:
(defun map-dispatch-macro-character (disp-char
sub-char
list
&optional (readtable *readtable*))
"Retrieve the dispatch macro character for DISP-CHAR and SUB-CHAR and
map it over the elements in LIST. Each element in LIST is either a
string designator or a two-element list of a string-designator and a
prefix argument."
(flet ((to-list (x)
(if (listp x) x
(list x))))
(let ((fn (get-dispatch-macro-character disp-char sub-char readtable)))
(mapcar (lambda (x)
(destructuring-bind (str &optional prefix) (to-list x)
(with-input-from-string (in (string str))
(funcall fn in sub-char prefix))))
list))))
CL-USER> (map-dispatch-macro-character #\# #\x '(B1 "A5" (FF nil)))
(177 165 255)
And of course, if you really want to be able to write #x, you could of course define a version that just extracts the characters from a string of length two, so that you could do:
CL-USER> (map-dispatch-macro-character* "#x" '(B1 A5 FF))
(177 165 255)