Racket: argument is non-null error - eval

At first I defined HALF, QUARTER and EIGHT to their values with define and with it the quoted symbols would get introduced as arguments in the note function thus making an error. Then I used let and now I get the error
stream-rec->C: argument is not non-null `stream-rec' pointer
argument: #f
My theory is that stream still processes HALF as 'HALF instead of 30000. I tried putting it into an eval list in note , in random-length in let bindings and in random-note and neither worked. What can I do?
#lang racket
(require rsound
rsound/piano-tones)
;Where notes are made.
(define stream (make-pstream))
(define count 10000)
(define (note y x)
(pstream-queue stream (clip (piano-tone y) 0 20000) count)
(set! count (+ count x)))
;Defining length of notes.
(let ([HALF 30000]) 30000)
(let ([QUARTER 15000]) 15000)
(let ([EIGHT 7500]) 7500)
(define (random-element list)
(list-ref list (random (length list))))
;Getting a random note length.
(define (random-length)
(random-element '(HALF QUARTER QUARTER EIGHT)))
;Getting a random note and note length.
(define (random-note)
(note (random-element '(40 42 43 45 47 48 50 52 54 55 57 59 60 62 64)) (random-length)))
;Main loop for creating the notes.
(for ([i (in-range 32)])
(random-note))
;For the program not to close itself before runing loop, only after pstream- queue is emptied.
(define ok-to-exit? #f)
(pstream-queue-callback stream (lambda () (set! ok-to-exit? #t)) count)
(let loop ()
(sleep 0.1)
(unless ok-to-exit?
(loop)))

Related

Printing each number in new line in Scheme

I need a help to convert this Pascal code to Scheme code:
program reverseorder;
type
arraytype = array [1..5] of integer;
var
arr:arraytype;
i:integer;
begin
for i:=1 to 5 do
arr[i]:=i;
for i:=5 downto 1 do
writeln(arr[i]);
end.
I want to accesses to a specific atom and its seems there aren't iteration method in Scheme.
There are many ways to tackle this problem. With the online interpreter you're using you'll be limited to vanilla Scheme, and the solution will be more verbose than needed, using recursion:
(define lst '(1 2 3 4 5))
(let loop ((rev (reverse lst)))
(when (not (null? rev))
(display (car rev))
(newline)
(loop (cdr rev))))
With Racket, which is aimed at beginners, you can write a much simpler (albeit non-standard) solution:
(define lst (range 1 6))
(for ([e (reverse lst)])
(displayln e))
Either way, notice that the procedure for reversing a list is already built in the language, and you don't need to reimplement it - naturally, it's called reverse. And if it wasn't obvious already, in Scheme we prefer to use lists, not arrays to represent a sequence of elements - it's recommended to stop thinking in terms of indexes, array lengths, etc. because that's not how things are done in Scheme.
If you don't care about returned value (it's #<undef>) and just want to produce output, you can use for-each:
(for-each print (reverse (list 1 2 3 4 5)))
Output:
5
4
3
2
1
Not idiomatic Scheme, but a literal translation of the Pascal code would be:
(let ([arr (make-vector 5)])
(do ([i 0 (+ i 1)]) ((= i 5)) (vector-set! arr i i))
(do ([i 4 (- i 1)]) ((negative? i))
(display (vector-ref arr i))
(newline)))

Take an array of numbers from standard input in Common Lisp

I realise this is a pretty basic question, but I'm just starting out in CL and I was wondering how to take input from standard input like:
1 2 3 4 5
And store it in an array.
I tried this:
(setq array (read-line))
Then checking the type gives cons.
I also tried constructing an array first like this:
(setf array (make-array n :element-type 'number))
Where n is the number of values I'll enter as input, but I'm lost after this. Do I need to use a loop or is there a way to do this without one?
Thanks.
You need to do these steps:
read the line
split into numbers
parse the numbers
It could look like this:
(defun read-array (stream)
(let* ((line (read-line stream))
(items (split-sequence #\Space line))
(numbers (map 'vector #'parse-integer items)))
numbers))
(Split-sequence is from the library of the same name.)
This is just the basic implementation, you likely want to sanitize your input, and split on any run of whitespace.
I advise against using read for reading user input, in any way, because the reader can do much more and you need to be very careful with user input.
The predefined function read-line returns a string (see the manual).
A simple way of obtaining from that string an array (assuming that the numbers are on a single line) is for instance to manipulate the returned string by adding the necessary syntax for reading it as a literal array through the function read-from-string. Here is a simple function adapted from one presented for lists in the excellent On Lisp book by Paul Graham:
CL-USER> (defun readarray (&rest args)
(values (read-from-string
(concatenate 'string "#("
(apply #'read-line args)
")"))))
READARRAY
CL-USER> (readarray)
1 2 3 4
#(1 2 3 4)
CL-USER> (type-of *)
(SIMPLE-VECTOR 4)
Of course if the numbers are on multiple lines some kind of iteration is required.
One can read from a string, by using a stream. Then one calls read as long as there are numbers, collects it into a list and converts the list to a vector.
CL-USER 36 > (coerce (with-input-from-string (stream "1 2 3 4 5")
(loop for n = (read stream nil nil)
while (numberp n)
collect n))
'vector)
#(1 2 3 4 5)
or: one creates a vector, which can grow - in Common Lisp the vector should be adjustable (when the size is unknown) and have a fill pointer. Then read from the string stream and push the numbers onto the vector.
CL-USER 40 > (let ((vector (make-array 0 :adjustable t :fill-pointer t)))
(with-input-from-string (stream "1 2 3 4 5")
(loop for n = (read stream nil nil)
while (numberp n)
do (vector-push-extend n vector)))
vector)
#(1 2 3 4 5)
The syntax for a literal array in Common Lisp like the one you're describing is #(1 2 3 4 5). You can simply type that instead of 1 2 3 4 5, and read it in:
CL-USER> (read)
; type "#(1 2 3 4 5)" (no quotes)
#(1 2 3 4 5) ; return value
CL-USER> (let ((array (read)))
(type-of array))
; type "#(1 2 3)" (no quotes)
(SIMPLE-VECTOR 3)

Generate lazy seq with recursion in Clojure?

I am new to clojure and currently struggling with loop / recur. The question basically is why my 'custom' range func. does not return a lazy sequence. Is there something wrong with my implementation or you are not supposed to use recursion in this case?
(defn my-range
[nr]
(loop [l nr acc '()]
(if (< l 1)
acc
(recur (dec l) (conj acc l)))))
When I run it:
> (time (take 10 (my-range 100000))) ;; "Elapsed time: 85.443 msecs"
> (time (take 10 (range 100000))) ;; "Elapsed time: 0.095 msecs"
The very big time difference leads me to belive the list is first constructed and then 10 taken.
You do not use any lazy constructs in my-range. Since you assemble the list by starting at the end and working your way toward the beginning, the only way to access the first ten elements is to first realize all the other elements.
Lazy sequences start at the beginning and work toward the end, like this:
(defn my-range
([end]
(my-range 1 end))
([start end]
(when (<= start end)
(lazy-seq (cons start (my-range (inc' start) end))))))
The trick here is that you don't return a realized sequence. Rather, you return an object that stores this function:
#(cons start (my-range (inc' start) end))
When someone calls seq on that object, it will call the above function, cache its result, and return that result. Future calls to seq will simply return the cached result. Note, though, that the second parameter you pass to cons is also a lazy sequence (because a call to my-range returns a lazy-seq), so it, in turn, will only be realized when necessary.
Just for completeness, another way to write this function is as follows:
(defn my-range
[end]
(take end (iterate inc' 1)))
This works because iterate and take both return lazy sequences.

Clojure: How do I have a for loop stop when the value of the current variable matches that of my input?

Preface
Firstly, I'm new to Clojure and programming, so I thought I'd try to create a function that solves a non-trivial equation using my natural instincts. What resulted is the desire to find a square root.
The question
What's the most efficient way to stop my square-n-map-maker function from iterating past a certain point? I'd like to fix square-n-map-maker so that I can comment out the square-maker function which provides me with the results and format I currently want to see but not the ability to recall the square-root answer (insofar as I know).
I.e. I want it to stop when it is greater than or equal to my input value
My initial thought was that instead of a keyword list, I would want it to be a map. But I'm having a very difficult time getting my function to give me a map. The whole reason I wanted a map where one member of a pair is n and another is n^2 so that I could extract the actual square root from it and it give it back to the user as the answer.
Any ideas on the best way to accomplish this? (below is the function I want to fix)
;; attempting to make a map so that I can comb over the
;; map later and recall a value that meets
;; my criteria to terminate and return result if (<= temp-var input)
(defn square-n-map-maker [input] (for [temp-var {remainder-culler input}]
(map list(temp-var) (* temp-var temp-var))
)
)
(square-n-map-maker 100) => clojure.lang.ArityException: Wrong number of args (0) passed to: MapEntry
AFn.java:437 clojure.lang.AFn.throwArity
AFn.java:35 clojure.lang.AFn.invoke
/Users/dbennett/Dropbox/Clojure Files/SquareRoot.clj:40 sqrt-range-high-end/square-n-map-maker[fn]
The following is the rest of my code
;; My idea on the best way to find a square root is simple.
;; If I want to find the square root of n, divide n in half
;; Then find all numbers in 0...n that return only a remainder of 0.
;; Then find the number that can divide by itself with a result of 1.
;; First I'll develop a function that works with evens and then odds
(defn sqrt-range-high-end [input] (/ input 2))
(sqrt-range-high-end 100) => 50
(defn make-sqrt-range [input] (range (sqrt-range-high-end (+ 1 input))))
(make-sqrt-range 100) =>(0 1 2 3 4 5 6 ... 50)
(defn zero-culler [input] (remove zero? (make-sqrt-range input)))
(zero-culler 100) =>(1 2 3 4 5 6 ... 50)
(defn odd-culler [input] (remove odd? (zero-culler input)))
(odd-culler 100) => (2 4 6 8 10...50)
(defn even-culler [input] (remove even? (zero-culler input)))
(even-culler 100) => (1 3 5 7...49)
(defn remainder-culler [input] (filter #(zero? (rem input %)) (odd-culler input)))
(remainder-culler 100) => (2 4 6 12 18)
(defn square-maker [input] (for [temp-var (remainder-culler input)]
(list (keyword (str
temp-var" "
(* temp-var temp-var)
)
)
)
)
(square-maker 100) => ((:2 4) (:4 16) (:10 100) (:20 400) (:50 2500))
Read the Error Messages!
You're getting a little ahead of yourself! Your bug has nothing to do with getting for to stop "looping."
(defn square-n-map-maker [input] (for [temp-var {remainder-culler input}]
(map list(temp-var) (* temp-var temp-var))))
(square-n-map-maker 100) => clojure.lang.ArityException: Wrong number of args (0) passed to: MapEntry
AFn.java:437 clojure.lang.AFn.throwArity
AFn.java:35 clojure.lang.AFn.invoke
Pay attention to error messages. They are your friend. In this case, it's telling you that you are passing the wrong number of arguments to MapEntry (search for IPersistentMap). What is that?
{} creates a map literal. {:key :value :key2 :value2} is a map. Maps can be used as if they were functions:
> ({:key :value} :key)
:value
That accesses the entry in the map associated with key. Now, you created a map in your first line: {remainder-culler input}. You just mapped the function remainder-culler to the input. If you grab an item out of the map, it's a MapEntry. Every MapEntry can be used as a function, accepting an index as an argument, just like a Vector:
> ([:a :b :c :d] 2)
:c
Your for is iterating over all MapEntries in {remainder-culler input}, but there's only one: [remainder-culler input]. This MapEntry gets assigned to temp-var.
Then in the next line, you wrapped this map in parentheses: (temp-var). This forms an S-expression, and expressions are evaluated assuming that the first item in the expression is a function/procedure. So it expects an index (valid indices here would be 0 and 1). But you pass no arguments to temp-var. Therefore: clojure.lang.ArityException: Wrong number of args.
Also, note that map is not a constructor for a Map.
Constructing a map
Now, on to your problem. Your square-maker is returning a list nicely formatted for a map, but it's made up of nested lists.
Try this:
(apply hash-map (flatten (square-maker 100)))
Read this page and this page to see how it works.
If you don't mind switching the order of the keys and values, you can use the group-by that I mentioned before:
(defn square-maker [input]
(group-by #(* % %) (remainder-culler input)))
(square-maker 100) => {4 [2], 16 [4], 100 [10], 400 [20], 2500 [50]}
Then you can snag the value you need like so: (first ((square-maker 100) 100)). This uses the map-as-function feature I mentioned above.
Loops
If you really want to stick with the intuitive looping concept, I would use loop, not for. for is lazy, which means that there is neither means nor reason (if you use it correctly) to "stop" it -- it doesn't actually do any work unless you ask for a value from it, and it only does the work it must to give you the value you asked for.
(defn square-root [input]
(let [candidates (remainder-culler input)]
(loop [i 0]
(if (= input (#(* % %) (nth candidates i)))
(nth candidates i)
(recur (inc i))))))
The embedded if determines when the looping will cease.
But notice that loop only returns its final value (acquaint yourself with loop's documentation if that sentence doesn't make sense to you). If you want to build up a hash-map for later analysis, you'd have to do something like (loop [i 0, mymap {}] .... But why analyze later if it can be done right away? :-)
Now, that's a pretty fragile square-root function, and it wouldn't be too hard to get it caught in an infinite loop (feed it 101). I leave it as an exercise to you to fix it (this is all an academic exercise anyway, right?).
I hope that helps you along your way, once again. I think this is a great problem for learning a new language. I should say, for the record, though, that once you are feeling comfortable with your solution, you should search for other Clojure solutions to the problem and see if you can understand how they work -- this one may be "intuitive," but it is not well-suited to Clojure's tools and capabilities. Looking at other solutions will help you grasp Clojure's world a bit better.
For more reading:
Imperative looping with side-effects.
How to position recur with loop
The handy into
Finally, this "not constructive" list of common Clojure mistakes
for is not a loop, and it's not iterating. It lazily creates a list comprehension, and it only realizes values when required (in this case, when the repl tries to print the result of the evaluation). There are two usual ways to do what you want: one is to wrap square-maker in
(first (filter some-predicate (square-maker number))) to obtain the first element in the sequence that complies with some-predicate. E.g.
(first (filter #(and (odd? %) (< 50 %)) (range)))
=> 51
The above won't realize the infinite range, obviously.
The other one is not to use a list comprehension and do it in a more imperative way: run an actual loop with a termination condition (see loop and recur).
Example:
(loop [x 0]
(if (and (odd? x) (> x 50))
x
(recur (inc x))))

Set-Difference for strings and arrays

set-difference works as a filter function, but only for lists. What's about arrays and strings? Are there analogous functions for these types of data? If there are no such functions, what is the proper way to implement them?
For now I use this macro to process any sequence as a list (sometimes it's useful):
(defmacro treat-as-lists (vars &body body)
(let ((type (gensym)))
`(let ((,type (etypecase ,(car vars)
(string 'string)
(vector 'vector)
(list 'list)))
,#(mapcar (lambda (x) `(,x (coerce ,x 'list)))
vars))
(coerce (progn ,#body) ,type))))
My filter:
(defun filter (what where &key key (test #'eql))
(treat-as-lists (what where)
(set-difference where what :key key :test test)))
Examples:
CL-USER> (filter "cat" "can you take this cat away?")
"n you ke his wy?"
CL-USER> (filter #(0 1) #(1 5 0 1 9 8 3 0))
#(5 9 8 3)
Since writing functions that works on all sequences types often means writing separate versions for lists and vectors, it's worthwhile to use standard functions that operate on sequences where you can. In this case, we can use position and remove-if. I've reversed the order of your arguments, in order to make this sequence-difference more like set-difference where the second argument is subtracted from the first.
(defun sequence-difference (seq1 seq2 &key (start1 0) end1 (start2 0) end2
key (key1 key) (key2 key)
test test-not)
"Returns a new sequence of the same type of seq1 that contains the
elements of the subsequence of seq1 designated by start1 and end1, and
in the same order, except for those that appear in the subsequence of
seq2 designated by start2 and end2. Test and test-not are used in the
usual way to elements produced by applying key1 (which defaults to
key) to elements from seq1 and by applying key2 (which defaults to
key) to elements from seq2."
(flet ((in-seq2 (x)
(not (null (position x seq2
:start start2 :end end2
:key key2
:test test :test-not test-not)))))
(remove-if #'in-seq2
(subseq seq1 start1 end1)
:key key1)))
(sequence-difference "can you take this cat away?" #(#\c #\a #\t))
;=> "n you ke his wy?"
(sequence-difference "can you take this cat away?" #(#\c #\a #\t) :start1 3 :start2 1)
" you ke his c wy?"
Note that the standard also includes find, which works on arbitrary sequences, but find returns "an element of the sequence, or nil." This leads to ambiguity if nil is a member of the sequence. Position, on the other hand, returns either an index (which will be a number, and thus not nil) or null, so we can reliably determine whether an element is a in sequence.
There is one important difference here in that you're always getting a copy back here. The reason for that is subjective: Since sequence functions often take start and end index arguments, it's nice to include that functionality here. But, if we ask for (sequence-difference "foobar" "boa" :start1 2) then we want to remove the characters b, o, and a from the "foobar"'s subsequence "obar". What should we return though? "for" or "r"? That is, do we include the portion of seq1 that's outside the indices? In this solution, I've made the decision not to, and thus I'm doing (remove-if … (subseq seq1 …) …), and subseq always makes a copy. Set-difference, on the other hand, may return its list-1 or list-2 argument, if appropriate. This implementation generally won't return seq1 or seq2, except in some pathological cases (e.g., the empty list).

Resources