arity mismatch using Racket - scheme

I'm studying scheme for my degree and written this code using racket 6.10:
(require rsound)
(define (arpeggio n fs q) (if(eq? 0 n) (stop)
((signal-play (mysound fs))(sleep q)(stop)(arpeggio (- n 1) (+ fs 100) q))))
where fs is the starting frequency updated in the recursive pass, q is the time offset and n is the number of sounds played.
mysound is defined as:
(define mysound (network ()
[a <= sine-wave 500]
[out = a])
code works well, but at the end of the playing I get the following error:
; stream-time: arity mismatch;
; the expected number of arguments does not match the given number
; expected: 0
; given: 3
; [,bt for context]
and even if I've tried ,bt for context as it says I genuinely don't get where's the error. The error accours whether the (stop) procedure is called or not in the else clause.
sample call is (arpeggio 10 500 0.1)
what's going on?

Related

how to use the if statement in scheme programming?

I just started learning the scheme language and below is a question that I stuck a little bit(Is there anything wrong with my code cuz the error message is kinda weird)
Prompt: Define a procedure over-or-under which takes in a number x and a number y and returns the following:
-1 if x is less than y
0 if x is equal to y
1 if x is greater than y
What I've tried so far is :
(define (over-or-under x y)
(if (< x y)
-1)
(if (= x y)
0)
(if (> x y)
1)
)
The error message is :
scm> (load-all ".")
Traceback (most recent call last):
0 (adder 8)
Error: str is not callable: your-code-here
scm> (over-or-under 5 5)
# Error: expected
# 0
# but got
The syntax of if is:
(if condition expression1 expression2)
and its value is the value of expression1 when the condition is true, otherwise it is the value of expression2.
In your function instead you use:
(if condition expression1)
and this is not allowed. Note, moreover that the three ifs one after the other are executed sequentially and only the value of the last one is actually used, as the value returned by the function call.
A way of solving this problem is using a “cascade” of if:
(define (over-or-under x y)
(if (< x y)
-1
(if (= x y)
0
1)))
Note that the proper alignment make clear the order of execution of the different expressions. If (< x y) is true than the value -1 is the result of the if, but, since it is the last expression of the function, it is also the value of the function call. If this is not true, we execute the “inner” if, checking if x is equal to y, and so on. Note also that in the third case is not necessary to check if x is greater than y, since it is surely true, given that x is not less than y, neither equal to y.
Finally, note that the “cascade” of x is so common that in scheme exists a more syntactically convient way of expressing it with the specific cond expression:
(cond (condition1 expression1)
(condition2 expression2)
...
(else expressionN))
so you could rewrite the function is this way:
(define (over-or-under x y)
(cond ((< x y) -1)
((= x y) 0)
(else 1)))

How to write functions of functions in Scheme

I am supposed to write a function called (nth-filtered f n), where f is a function of one variable and n is a natural number, which evaluates to the nth natural number such that f applied to that number is #t.
If we called
(nth-filtered even? 1) we would get 2
(nth-filtered prime? 10) we would get 29
How do I make it so that it works for any sequential function? What should I think about when approaching this type of problem?
A variable is a variable and + is also a variable. The main difference between a function and some other data type is that you can wrap a function name in parentheses with arguments and it will become a new value.
eg.
(define (double fun)
(lambda (value)
(fun (fun value))))
(define (add1 v)
(+ 1 v))
(define add2 (double add1))
(add2 1) ; ==> 3
Now the contract doesn't say so you deduct by looking that you do (fun ...) that fun needs to be a function. Imagine this:
(define test (double 5)) ; probably works OK
(test 1)
The last one fails since you get application: 5 is not a procedure or something similar. The error message is not standardized.
How to attack your task is by making a helper that has the same arguments as your function but in addition the current number that I guess starts at 1. As I demonstrated you use the function variable as a function and recurse by always increasing the number and reducing n when the f call was #t. The actual function will just use the helper by passing all the parameters in addition to your state variable.
Your problem requires a fold, which is the standard way to iterate other a list while keeping a record of things done so far.
Here a very rackety method using for/fold:
(define (nth-filtered predicate index)
(for/fold ([count 0]
[current #f] #:result current)
([n (in-naturals 1)]) ; we start at 1 but we could start at 0
#:break (= count index)
(values (if (predicate n) (add1 count) count)
n)))
for/fold takes a list of initial state. Here we define count as the number of times the given predicate returned #t and current as the currently tested value.
Then it takes a list of iterators, in this case we only iterate infinitely over (in-naturals).
To make it stop, we provide a #:break condition, which is "when the number of truthy predicates (count) is equal to the requested amount (index)".
for/fold requests that it's body finishes with a list of values for each "state" variable, in order to update them for the next iteration. Here we provide two values: one is the new count, the other is just the current n.
You can try it out, it works as you requested:
> (nth-filtered even? 1)
2
> (require math/number-theory)
> (nth-filtered prime? 10)
29
> (nth-filtered prime? 5)
11

Scheme - syntax with if statements

Can anyone explain why this isn't working? I am following the documentation and I cannot understand why I get an error:
(define (functionName n)
(if (n < 10) ;;if condition
1 ;; then condition
3)) ;; else condition
I get the error:
application: not a procedure;
expected a procedure that can be applied to arguments
given: 5
arguments...:
#<procedure:<>
10
You can see this in two ways. Your code is correct and you just called it wrong (bad type for n) or your code was accidentally written in infix notation. I'll illustrate both:
Passed wrong argument
n can be any data type and it can even be a procedure and if it is there is nothing wrong with your code:
(define (compare-15 predicate-procedure argument)
(predicate-procedure 15 argument))
(define (compare-2 predicate-procedure argument)
(predicate-procedure 2 argument))
(functionName compare-15) ; ==> 3
(functionName compare-2) ; ==> 1
What happens is that your procedure is calling the supplied procedure with a procedure for comparing < and an argument.
Accidental infix
Algol programmers are used to prefix fun( expr ) and infix x cmp y while in LISP dialects all those have one common form and that is prefix all the way: (fun expr) and (cmd x y).
(define (function-name n)
(if (< n 10) ;; predicate expression
1 ;; consequent expression
3)) ;; alternative expression
(function-name 15) ; ==> 3
(function-name 2) ; ==> 1
Since Scheme can have functions as argument, meaning every argument can be put in the first position, it might be exactly what you wanted and Scheme doesn't know until it gets a number to be called as a procedure that something is wrong.
The error message is quite clear when you know that every procedure call is called application. It expected to call a procedure but behind the variable n there was a number. "expected a procedure that can be applied to arguments. given: 5" probably makes more sense now?
Try this:
(define (functionName n)
(if (< n 10)
1
3))
Remember: Scheme uses prefix notation, meaning that all operators must go before the operands. In other words, this is wrong: (n < 10), and this is correct: (< n 10).
The function should be the first thing in the if (scheme uses prefix notation, not infix).
(define (functionName n)
(if (< n 10) ;;if condition
1 ;; then condition
3)) ;; else condition
Then
(functionName 2)
Outputs
1
when I run it in Chicken Scheme.

Iterative tree calculation in scheme

I'm trying to implement a function defined as such:
f(n) = n if n < 4
f(n) = f(n - 1) + 2f(n - 2) + 3f(n - 3) + 4f(n - 4) if n >= 4
The iterative way to do this would be to start at the bottom until I hit n, so if n = 6:
f(4) = (3) + 2(2) + 3(1) + 4(0) | 10
f(5) = f(4) + 2(3) + 3(2) + 4(1) | 10 + 16 = 26
f(6) = f(5) + 2f(4) + 3(3) + 4(2) | 26 + 2(10) + 17 = 63
Implementation attempt:
; m1...m4 | The results of the previous calculations (eg. f(n-1), f(n-2), etc.)
; result | The result thus far
; counter | The current iteration of the loop--starts at 4 and ends at n
(define (fourf-iter n)
(cond [(< n 4) n]
[else
(define (helper m1 m2 m3 m4 result counter)
(cond [(= counter n) result]
[(helper result m1 m2 m3 (+ result m1 (* 2 m2) (* 3 m3) (* 4 m4)) (+ counter 1))]))
(helper 3 2 1 0 10 4)]))
Several problems:
The returned result is one iteration less than what it's supposed to be, because the actual calculations don't take place until the recursive call
Instead of using the defined algorithm to calculate f(4), I'm just putting it right in there that f(4) = 10
Ideally I want to start result at 0 and counter at 3 so that the calculations are applied to m1 through m4 (and so that f(4) will actually be calculated out instead of being preset), but then 0 gets used for m1 in the next iteration when it should be the result of f(4) instead (10)
tl;dr either the result calculation is delayed, or the result itself is delayed. How can I write this properly?
I think the appropriately "Scheme-ish" way to write a function that's defined recursively like that is to use memoization. If a function f is memoized, then when you call f(4) first it looks up 4 in a key-value table and if it finds it, returns the stored value. Otherwise, it simply calculates normally and then stores whatever it calculates in the table. Therefore, f will never evaluate the same computation twice. This is similar to the pattern of making an array of size n and filling in values starting from 0, building up a solution for n. That method is called dynamic programming, and memoization and dynamic programming are really different ways of looking at the same optimization strategy - avoiding computing the same thing twice. Here's a simple Racket function memo that takes a function and returns a memoized version of it:
(define (memo f)
(let ([table (make-hash)])
(lambda args
(hash-ref! table
args
(thunk (apply f args))))))
Now, we can write your function f recursively without having to worry about the performance problems of ever calculating the same result twice, thus going from an exponential time algorithm down to a linear one while keeping the implementation straightforward:
(define f
(memo
(lambda (n)
(if (< n 4)
n
(+ (f (- n 1))
(* 2 (f (- n 2)))
(* 3 (f (- n 3)))
(* 4 (f (- n 4))))))))
Note that as long as the function f exists, it will keep in memory a table containing the result of every time it's ever been called.
If you want a properly tail-recursive solution, your best approach is probably to use the named let construct. If you do (let name ([id val] ...) body ...) then calling (name val ...) anywhere in body ... will jump back to the beginning of the let with the new values val ... for the bindings. An example:
(define (display-n string n)
(let loop ([i 0])
(when (< i n)
(display string)
(loop (add1 i)))))
Using this makes a tail-recursive solution for your problem much less wordy than defining a helper function and calling it:
(define (f n)
(if (< n 4)
n
(let loop ([a 3] [b 2] [c 1] [d 0] [i 4])
(if (<= i n)
(loop (fn+1 a b c d) a b c (add1 i))
a))))
(define (fn+1 a b c d)
(+ a (* 2 b) (* 3 c) (* 4 d)))
This version of the function keeps track of four values for f, then uses them to compute the next value and ditches the oldest value. This builds up a solution while only keeping four values in memory, and it doesn't keep a huge table stored between calls. The fn+1 helper function is for combining the four previous results of the function into the next result, it's just there for readability. This might be a function to use if you want to optimize for memory usage. Using the memoized version has two advantages however:
The memoized version is much easier to understand, the recursive logic is preserved.
The memoized version stores results between calls, so if you call f(10) and then f(4), the second call will only be a table lookup in constant time because calling f(10) stored all the results for calling f with n from 0 to 10.

Unable to evaluate a lambda expression as argument in SICP ex-1.37

The problem can be found at http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-12.html#%_thm_1.37
The problem is to expand a continuing fraction in order to approximate phi. It suggests that your procedure should be able to calculate phi by evaluating:
(cont-frac (lambda (i) 1.0)
(lambda (i) 1.0)
k)
My solution is as follows:
(define (cont-frac n d k)
(if (= k 1) d
(/ n (+ d (cont-frac n d (- k 1))))))
This solution works when calling (cont-frac 1 1 k), but not when using the lambda expressions as the problem suggests. I get what looks like a type error
;ERROR: "ex-1.37.scm": +: Wrong type in arg1 #<CLOSURE <anon> (x) 1.0>
; in expression: (##+ ##d (##cont-frac ##n ##d (##- ##k 1)))
; in scope:
; (n d k) procedure cont-frac
; defined by load: "ex-1.37.scm"
;STACK TRACE
1; ((##if (##= ##k 1) ##d (##/ ##n (##+ ##d (##cont-frac ##n ##d ...
My question is two-part:
Question 1. Why am I getting this error when using the lambda arguments? I (mistakenly, for sure) thought that (lambda (x) 1) should evaluate to 1. It clearly does not. I'm not sure I understand what it DOES evaluate to: I presume that it doesn't evaluate to anything (i.e., "return a value" -- maybe the wrong term for it) without being passed an argument for x.
It still leaves unanswered why you would have a lambda that returns a constant. If I understand correctly, (lambda (x) 1.0) will always evaluate to 1.0, regardless of what the x is. So why not just put 1.0? This leads to:
Question 2. Why should I use them? I suspect that this will be useful in ex-1.38, which I've glanced at, but I can't understand why using (lambda (x) 1.0) is any different that using 1.0.
In Scheme lambda expression creates a function, therefore expression such as:
(lambda (i) 1.0)
really does have result, it is a function object.
But if you add parentheses around that expression, it will indeed be evaluated to 1.0 as you expected:
((lambda (i) 1.0))
Using of lambdas in that exercise is necessary for building general solution, as you've correctly noticed in exercise 1.38, you'll be using the same implementation of cont-frac function but with different numerator and denominator functions, and you'll see an example, where you should calculate one of them in runtime using loop counter.
You could compare your exercise solutions with mine, e.g. 1.37 and 1.38
(/ n (+ d (cont-frac n d (- k 1))))))
In this case 'd' being the lambda statement, it doesn't make any sense to '+' it, same for 'n' and '/' try something like
(/ (n k) (+ (d k) (cont-frac n d (- k 1))))))
you'll see why in the next exercise you can also make this tail-recursive
I named my variables F-d and F-n instead of d and n, becuase they accept a function that calculates the numerator and denominator terms. (lambda (i) 1.0) is a function that accepts one argument and returns 1.0, 1.0 is just a number. In other continued fractions, the value may vary with the depth (thus why you need to pass k to the numerator and denomenator function to calculate the proper term.

Resources