in scheme (I'm using racket R5RS) when I call this procedure
(map display '(1 2 3 4 5))
it returns
12345(#<void> #<void> #<void> #<void> #<void>)
Why is that? What's up with the void?
You said:
"it returns 12345(#<void> #<void> #<void> #<void> #<void>)"
which isn't precisely correct. That is what it prints/displays; not what it returns. You get the return value with:
> (define test (map display '(1 2 3 4 5)))
12345> test
(#<void> #<void> #<void> #<void> #<void>)
>
Here it is clearer: '12345' was printed; the return value, bound to test, is your 'void' list.
The reason for the 'void' values is that map applies its function to each element in the list and constructs a new list with the value returned by function. For display the return value is 'void'. As such:
> (define test2 (display 1))
1> (list test2)
(#<void>)
>
You need to use for-each instead of map, in your case. for-each is non-collecting, unlike map.
Also, for-each is guaranteed to pass the list items from left to right to your function. map makes no such guarantee, and is allowed to pass the list items in any order. (Although, in the specific case of Racket, map does use a left-to-right order. But you cannot depend on this in other Scheme implementations; some use a right-to-left order, and theoretically, other orderings are possible.)
map collects the results of each invocation of the function on each element of the list and returns the list of these results.
display returns an unspecified value. #<void> is just something that Racket is using. It could have returned 42 as well.
You probably have a typo. It should have returned
12345(#<void> #<void> #<void> #<void> #<void>)
without the leading open parenthesis. I.e. the five values are isplayed, and then the return value.
Related
I want to understand what and and or represent in Racket when used with lists. When I do something like this -
> (or `(1 2) `(1 3))
'(1 2)
What is the result representing? I thought when we use or with two lists we would get a union of the lists. That is clearly not what is happening here. So, I thought it is interpreted as boolean values and that is why `(1 2) is not a false value. Hence, the result is `(1 2). But what about this? -
> (and `(1 2) `(1 3))
'(1 3)
How can I justify this?
or is looking for the first truthy value, checking arguments from left to right. Every value other than #false is truthy. If any is found, it's returned. In your example, '(1 2) is the first truthy value from the left, so it's returned.
Or called with no arguments returns #false, because no truthy values were found:
> (or)
#f
And checks whether all values are truthy, so it has to examine all of them, going from left to the right, and it can return #false (if any #false is found) or, if all values are truthy, last of them. In your example, '(1 3) is the last truthy value, so it's returned.
And called with no arguments returns #true, because no #false was found:
> (and)
#t
Read also the docs about or and and.
By the way, there is a difference between ' and `. First one is quote, the second one is quasiquote. In this very example, it doesn't matter, but you should know the difference between them.
And if you were really looking for union function, check racket/set library:
(require racket/set)
(set-union (set 1 2) (set 1 3))
=> (set 1 3 2)
I am currently just starting out working through Structure and Interpretation of Computer Programming, and in a section it is going over the creation of an absolute value function in Scheme (takes a value, and returns its absolute value).
I am following exactly how the book does the function:
(define (abs x)
(cond ((< x 0) (- x))
(else x)))
Unfortunately, this is not providing the desired result as the book says. Instead of returning the absolute value, it just returns the value. For example, I type in -5, the function returns -5.
If it is of any help, I am using the BiwaScheme Interpreter (0.6.4).
Any help is greatly appreciated, thanks.
To call a function, enclose its name in parentheses together with any arguments you wish to supply it with. Example,
> (abs -5)
5
Of course if you just type -5 you are not calling any functions, abs in particular, with it:
> -5
-5
The numeric value is just returned as is, as no function call is indicated.
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
I am working on a scheme project and I encountered with a problem with quotes.
When I use (apply + '(1 2 '3)) racket gives an error, on the other hand (+ 1 2 '3) works fine. At some point in the project I need to be able to do something like (apply + '(1 2 '3)) since I am taking the values from a given file and I have no freedom to use (+ 1 2 '3). I tried to write an add function that adds all the values in the list but it didn't work either. How can I solve this problem?
Thanks.
'x is an abbreviation for (quote x). In early lisps it was a reader macro and today some print routines will actually print (quote x) as 'x for convenience. Even when the printer chooses to print it as an abbriavtion it still a list with two elements so (car ''x) is quote.
(+ '1 '2 '3) works fine because all arguments are being evaluated. + gets evaluated to a procedural object #<+> (just a procedural representation of an implementation of global variable +), '1 evaluates to it's data, the number 1 and so on. In the end application of the procedure happens on the arguments (1 2 3). Numbers are self evaluating so if you were not to quote them 1 would evaluate to 1 and so on and you get the same result. Not all values are self evaluating.
With (apply + '(1 2 3)) all 3 arguments get evaluate. apply and + both to procedural objects and '(1 2 3) to the list (1 2 3). The procedure #<+> gets applied with the arguments (1 2 3)
With (apply + '(1 2 '3)) all 3 arguments gets evaluated. apply and + both to procedural objects and '(1 2 '3) to the list (1 2 (quote 3)). The evaluator only looks at the outer quote so the 3 is still quoted and now it's part of the data. The procedure #<+> gets applied with the arguments (1 2 (quote 3)). It won't work since #<+> only knows how to add numbers and not lists. You can expect a contract violation, an error of some kind.
When evaluated the result is data. If you have more quotes besides the outer one it isn't a language command any more but a list with the symbol quote and a second value. It's not handled specially like qith outer quotes.
The problem here is the meaning of the quote '.
The expression ' means "produce a value that prints as ".
For example '3 produces the value 3 since the value 3 is printed as 3.
In '(1 b) you get a list whose first element is the number 1 and whose second element is the symbol b.
Now you need to know one more thing about the quote. The quote is a reader abbreviation. When '<something> is read, the reader produces the form (quote <something>). This means that'(1 'b)produces the list(1 (quote b)). This is a list whose second element is the list(quote b), wherequote` is the symbol quote.
In your example you tried to (apply + '(1 2 '3)). The value produced by '(1 2 '3) is the list (1 2 (quote 3)). Since + adds only numbers, you got an error message.
If you want to read in numbers from a file, then read them as numbers and everything ought to be fine.
In Structure and Interpretation of Computer Programs (SICP) Section 2.2.3 several functions are defined using:
(accumulate cons nil
(filter pred
(map op sequence)))
Two examples that make use of this operate on a list of the fibonacci numbers, even-fibs and list-fib-squares.
The accumulate, filter and map functions are defined in section 2.2 as well. The part that's confusing me is why the authors included the accumulate here. accumulate takes 3 parameters:
A binary function to be applied
An initial value, used as the rightmost parameter to the function
A list to which the function will be applied
An example of applying accumulate to a list using the definition in the book:
(accumulate cons nil (list 1 2 3))
=> (cons 1 (cons 2 (cons 3 nil)))
=> (1 2 3)
Since the third parameter is a list, (accumulate cons nil some-list) will just return some-list, and in this case the result of (filter pred (map op sequence)) is a list.
Is there a reason for this use of accumulate other than consistency with other similarly structured functions in the section?
I'm certain that those two uses of accumulate are merely illustrative of the fact that "consing elements to construct a list" can be treated as an accumulative process in the same way that "multiplying numbers to obtain a product" or "summing numbers to obtain a total" can. You're correct that the accumulation is effectively a no-op.
(Aside: Note that this could obviously be a more useful operation if the output of filter and input of accumulate was not a list; for example, if it represented a lazily generated sequence.)