I need to read through a string (which is a sequence) 3 characters at a time. I know of take-while and of take 3 and since take returns nil when there is no more input it seems like the perfect predicate for take-while but I cannot figure out how to wrap the string sequence so that it returns string of the next 3 characters at a time. If this was an object oriented language I'd wrap the sequence's read call or something, but with Clojure I have no idea how to proceed further.
You can use partition or partition-all
(partition 3 "abcdef")
user=> ((\a \b \c) (\d \e \f))
The docs for both are
clojure.core/partition
([n coll] [n step coll] [n step pad coll])
Returns a lazy sequence of lists of n items each, at offsets step
apart. If step is not supplied, defaults to n, i.e. the partitions
do not overlap. If a pad collection is supplied, use its elements as
necessary to complete last partition upto n items. In case there are
not enough padding elements, return a partition with less than n items.
nil
clojure.core/partition-all
([n coll] [n step coll])
Returns a lazy sequence of lists like partition, but may include
partitions with fewer than n items at the end.
nil
If your string is not guaranteed to be of length that is multiple of three, then you should probably use partition-all. The last partition will contain less than 3 elements though. If you want to use partition instead, then to avoid having characters from the string chopped off, you should use step=3, and a padding collection to fill in the holes in the last partition.
To turn every tuple to a string, you can use apply str on every tuple. So you'd want to use map here.
(map (partial apply str) (partition-all 3 "abcdef"))
user=> ("abc" "def")
You can do this without boxing every character:
(re-seq #"..." "Some words to split")
;("Som" "e w" "ord" "s t" "o s" "pli")
If, as your comment on #turingcomplete's answer indicates, you want every other triple,
(take-nth 2 (re-seq #"..." "Some words to split"))
;("Som" "ord" "o s")
Related
I am a clojure newbie. I am trying to play around repl and i see the following as output. And I don't quite understand why each of them behave so differently
(def a (list 1 2 3)) =>#'test.core/a
(list* 4 5 a) =>(4 5 1 2 3)
(list* a 4 5) =>IllegalArgumentException Don't know how to create ISeq from: java.lang.Long clojure.lang.RT.seqFrom (RT.java:542)
why does the above 2 statements behave the same way in the above 2 statements?
(list* 4 5 [1 2 3]) =>(4 5 1 2 3)
(list* 4 5 [a]) =>(4 5 (1 2 3))
(list* 4 5 (1 2)) =>ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn test.core/eval3837 (form-init633779145118520639.clj:1)
Could someone explain why each of the above statement has a different output?
If you look at the definition and docstring, it'll make sense.
The docs say:
"Creates a new seq containing the items prepended to the rest, the last of which will be treated as a sequence."
Emphasis mine.
In the first block, the last expression fails because 5 is the last argument, but isn't a sequence.
(list* 4 5 [1 2 3]) works for the same reason that (list* 4 5 a) works. The last argument is a sequence, as it's expecting. It just cons onto the last argument as you can see in the definition.
(list* 4 5 [a]) gives different results because you've wrapped the collection a in another collection. It just adds onto the outer collection, leaving the inner one untouched.
The failure of (list* 4 5 (1 2)) isn't really a related problem. Remember, any time you have (...) unquoted, it will attempt to evaluate it, and is expecting that the first element in the list is callable. 1 however isn't callable, thus the error. You need to quote it to treat it as a list literal and not code that you want evaluated.
See the doc string for list*:
Creates a new seq containing the items prepended to the rest, the last
of which will be treated as a sequence.
Note a seq is not a list but lists and vectors and other things can be treated as sequences. Also a seq when output at the repl looks like a list - it is printed within parens.
So in the first case your last argument is a literal vector and it is treated as a sequence and you get an unnested sequence.
In the second case you have the list 'a' as a single element within a literal vector so the vector is treated as a sequence but the inner list is not, your returned sequence is three elements long: 4, 5, and the list a.
In the last case you are tripping up on the function call syntax in lisps being very similar to the list syntax. (1 2) is trying to call the number 1 as if it in a function (with the argument 2). A literal number can not be interpreted as a function.
If you want a list literal not a function call you have to quote it:
(list* 4 5 '(1 2)) => (4 5 1 2)
Can anyone explain why sort-by is reacting like this with these keyfunctions?
user=> (sort-by number? [1 2 13 4 "s" 0 "a"])
("s" "a" 1 2 13 4 0)
user=> (sort-by str [1 2 3 4 "s" 0 "a"])
(0 1 2 3 4 "a" "s")
My idea is its dividing the args of the vector into strings and numbers? Is there anything more about what's happening here?
And my second question does sort-by travel through every item of the vector and then returning the result?
number? returns true or false depending on whether the input is a number. false is apparently less than true for comparisons.
str returns a string whose value depends on the input. e.g. (str 1) => "1". String comparison is somewhat complicated, but, in general, numerals are less than uppercase letters are less than lowercase letters and letters are sorted in alphabetical order.
I'm not sure exactly the behavior you're wanting, but it would seem that (sort-by number? ...) did indeed "divide the vector into strings and numbers" by giving you strings at the start of the list and numbers at the end.
If you're wanting to separate strings from numbers, use (group-by number? ...)
As for your second question, sort-by uses the keyfn for comparisons during a merge sort.
I would like to add sentence number to a text file:
Put [1][2][3]... in front of each sentence.
[1] Sentence one. [2] Sentence two. ...
And a sentence ended with one of .!?.
I have no clue how to do it in Clojure. Here is my attempt:
(def text "Martin Luther King, Jr.
I Have a Dream
delivered 28 August 1963, at the Lincoln Memorial, Washington D.C.
I am happy to join with you today in what will go down in history as the greatest demonstration for freedom in the history of our nation.
Five score years ago, a great American, in whose symbolic shadow we stand today, signed the Emancipation Proclamation. This momentous decree came as a great beacon light of hope to millions of Negro slaves who had been seared in the flames of withering injustice. It came as a joyous daybreak to end the long night of their captivity.
But one hundred years later, the Negro still is not free. One hundred years later, the life of the Negro is still sadly crippled by the manacles of segregation and the chains of discrimination. One hundred years later, the Negro lives on a lonely island of poverty in the midst of a vast ocean of material prosperity. One hundred years later, the Negro is still languished in the corners of American society and finds himself an exile in his own land. And so we've come here today to dramatize a shameful condition.")
Define sentence ending:
(def sentence-ending #"[.!?]")
Use replace function:
(require '[clojure.string :as str])
(str/replace text sentence-ending "[number]")
I know this is logically wrong! I got replace all the .!? with a string. Perhaps string replace is not the right way. How to tackle this problem?
You can split the text into sequence of sentences. Then map each sentence to prepend [number], and join the sentences again to make one string.
(->> (clojure.string/split text #"[.?!]") ; split text
(map-indexed #(str "[" (inc %1) "] " %2)) ; prepend number
(apply str)) ; join to one string
But the condition for splitting the text into string is naive. As you can see, some of words contains . which are not the end of sentence. You should refine the sentence termination condition.
One way to get the full sentence (including the punctuation) is to regex out the whole thing and use a matcher. I don't know if this is the best way. But it works.
After that, I think interleave works nicely for this kind of problem.
(let [matcher (re-matcher #"[^.!?]*[.!?]" text)
sentences (take-while seq (repeatedly #(re-find matcher)))
numbers (map #(str "[" % "] ") (range))]
(apply str (interleave numbers sentences)))
I'm trying to use the lines function to plot a graph, but I can't seem to figure out the exact syntax.
Here's some code I tried:
(require plot)
(define lst '(1 2 3 4 5 6 7 8 9))
(define f (plot-frame (lines lst)))
(send f show #t)
But it gives me the following error message:
lines: contract violation
expected: sequence of length >= 2
given: #<sequence>
The lines function's first argument is supposed to be a sequence of sequences of real numbers (as opposed to just a sequence of real numbers). That's what this contract shown in the documentation means: (sequence/c (sequence/c real?))
For example, this is a valid input: (lines '((1 2) (3 4)))
There's also a full example in the docs: http://www.cs.utah.edu/plt/snapshots/current/doc/plot/renderer2d.html?q=lines#%28def._%28%28lib._plot%2Fmain..rkt%29._lines%29%29
I know that in Lisp a list must end with nil, but expression like
(print (cons 1 (cons 3 2)))
does not throw any errors. It prints:
(1 3 . 2)
Is it correct?
I'm using GNU Clisp.
In Lisp, a proper list ends with NIL, but you also have improper lists. One kind of improper list is a list where the last cons cell has an atom other than NIL in its CDR. (1 3 . 2) is exactly such an improper list.
You can even have improper lists where it doesn't have a last cell at all. CARs and CDRs are basically just pointers, so you can have circular lists!
In Common Lisp (which is the language CLISP implements), many standard functions won't work with improper lists as arguments.
What you have is a dotted list, which is a kind of improper list.
A chain of CONS cells where the last CDR is NIL is a proper list.
It's also interesting to note what happens when evaluating proper lists:
;; A proper list
(cons '+ (cons 5 (cons 10 '())))
⇒ (+ 5 10)
(eval (+ 5 10))
⇒ 15
versus evaluating dotted lists:
;; A dotted list
(cons '+ (cons 5 (cons 10 5000)))
⇒ (+ 5 10 . 5000)
(eval (+ 5 10 . 5000))
⇒ 15
It ignores the terminating atom.
When you iterate over a list you know you reached the end when you hit nil.
What you have is a list with a car and a point pair.