When I read from user input from the console in scheme, what is the type that I need to use if i'm converting from that type into something I want?
For example
(string->number "20") converts the string into a number, what is the syntax for this regarding a read?
FOR EXAMPLE
(define input(read)
(let ((r read))
(????->number r)))
If we look at the Racket documentation for read we see as signature : (read [in]) → any.
So in your case if the user inputs a number it will return a number.
But explicitly check that it is a number because you can't be sure the user won't input something else!
An example :
(define (read-number)
(let ((inpt (read)))
(if (number? inpt)
inpt
(begin (display "Please input a number!")
(newline)
(read-number)))))
EDIT : If you want to test if the inputted number was zero, you should replace the if-statement by a conditional.
(cond ((and (number? inpt)
(= inpt 0)) ; Works because of lazy evalutation
; User inputted 0
...)
((number? inpt)
; User inputted a number other then zero
...)
(else
; User did not entered a number!
(display "Please input a number!")
(newline)
(read-number)))
read doesn't return anything of a specific type – it reads the textual representation of a Scheme object and returns such an object.
Example (input indicated with <-) :
> (read)
<- 23
23
> (read)
<- "hello"
"hello"
> (read)
<- (1 2 3)
'(1 2 3)
> (number? (read))
<- 23
#t
> (number? (read))
<- "hello"
#f
> (define x (read))
<- 4
> x
4
> (number? x)
#t
> (eqv? x 4)
#t
> (+ x 1)
5
> (let ((y (read))) (* y 2))
<- 4
8
So if you want a number, and the user inputs a number, you don't need to do anything.
You may want to check that the input actually is a number and ask for a new value in that case, though.
Related
I'm trying to take in user input and add it to a list but I have not been able to get it working. I'm still new to scheme and have been browsing around to try to figure it out but I haven't had any luck.
(display "Continue to enter numbers until satisfied then enter e to end")
(newline)
(define (intlist number)
(define number(read-line))
(cond (number? number)
(cons lst (number))
(else
(display lst)
done')))
this is what I have so far. Any help or direction to where I can learn a bit more is appreciated.
Your solution is almost correct, but it doesn't work, because:
Variable lst doesn't exist and with this expression (number), you are calling some undefined function number.
done' is badly written 'done.
Function cons expects element as first argument and other element or list as second argument.
See these examples:
> (cons 1 2)
'(1 . 2)
> (cons 1 '())
'(1)
> (cons 1 (cons 2 (cons 3 '())))
'(1 2 3)
Last example is important here- your function will be recursive and it will return a cons cell in each step. If I will follow your solution, this can be enough:
(define (list-from-user)
(let ((number (read)))
(if (number? number)
(cons number (list-from-user))
'())))
(Note that I used read instead of read-line, because read-line returns string, and let instead of define.)
If you really want to wait for e, you must decide, what happens if user enters something that isn't number and isn't e- maybe just ignore it?
(define (list-from-user)
(let ((user-input (read)))
(cond ((number? user-input) (cons user-input (list-from-user)))
((eq? user-input 'e) '())
(else (list-from-user)))))
Then just add some wrapping function with output:
(define (my-fn)
(begin (display "Continue to enter numbers until satisfied then enter e to end")
(newline)
(list-from-user)))
and call it
> (my-fn)
Note that my function returns list with numbers, instead of some useless 'done, so I can use that function in other functions.
(define (sum-of-list)
(let ((lst (my-fn)))
(format "Sum of given list is ~a." (apply + lst))))
> (sum-of-list)
In the Chez Scheme REPL, is it possible to get the previous result? For example in ruby's irb repl, underscore can be used.
For example can I do the following?
> (+ 2 3)
5
> (+ 1 <something>)
And get 6?
Chez Scheme does not have a built in way to do this, but being scheme, we can roll our own:
(define repl
(let ([n 1])
(lambda (expr)
(let-values ([vals (eval expr)])
(for-each (lambda (v)
(unless (eq? (void) v)
(let ([sym (string->symbol (format "$~a" n))])
(set! n (+ n 1))
(printf "~a = " sym)
(pretty-print v)
(set-top-level-value! sym v))))
vals)))))
(new-cafe repl)
repl is now a function that takes an expression, evaluates it, stores the non-void results into ids of the form $N where N is monotonically increasing, and prints out the results. new-cafe is a standard chez function that manages the Reading, Printing, and Looping parts of REPL. It takes a function that manages the Evaluation part. In this case, repl also needs to manage printing since it shows the ids associated with the values.
Edit:
I found a slightly better way to do this. Instead of having a custom repl, we can customize only the printer. Now this function is no longer responsible for also evaluating the input.
(define write-and-store
(let ([n 1])
(lambda (x)
(unless (eq? (void) x)
(let ([sym (string->symbol (format "$~a" n))])
(set! n (+ n 1))
(set-top-level-value! sym x)
(printf "~a = " sym)
(pretty-print x)
(flush-output-port (console-output-port)))))))
(waiter-write write-and-store)
A simple usage example:
> (values 1 2 3 4)
$1 = 1
$2 = 2
$3 = 3
$4 = 4
> (+ $1 $2 $3 $4)
$5 = 10
I'm fairly new to Scheme and I'm using DrRacket as my IDE.
If i have a small program, for example - a program that's given a number, would generate a list from 0 to that number:
(define (helper num mylist)
(cond [(zero? num) (append (list 0) mylist)]
[else (helper (- num 1) (append (list num) mylist))]))
(define (genlist num)
(helper num '()))
(genlist 10) => '(0 1 2 3 4 5 6 7 8 9 10)
I'm coming from a Java background, and there is obviously no print statement here. So how does it "decide" to output mylist to the console? What "tells" it to do so?
genlist doesn't print the list, it only returns it. It's the REPL that prints it because it prints the return value of whichever expression you enter.
It also prints the values of any non-void expressions that are written at the top level of your file when you load it.
The interpreter (REPL) always prints the value of the expression you entered.
If we define
(define (foo a)
(display a)
a)
(define (bar a)
(display a))
we get the output
> (bar "hello")
hello
> (foo "hello")
hello"hello"
where the hellos (without quotation marks) are output by the procedures, and then the REPL prints the result of the procedure calls, which is nothing for the first, and "hello" for the second.
In DrRacket, the outputs also have different colours.
(Also note that a string that is a value is printed differently from a string that is a procedure's output.)
I am a beginner to functional programming and I want to be able to read values from a console into a list, pass that list as a parameter, and then return the sum of the list in Scheme.
I want to get this result: (display (sum-list-members '(1 2 3 4 5))) but the user must enter these values at the console.
This is what I am working on:
(begin
(define count 0)
(define sum-list-members
(lambda (lst)
(if (null? lst)
0
(+ (car lst) (sum-list-members (cdr lst))))))
(display "Enter a integer [press -1 to quit]: ")
(newline)
(let loop ((i 0))
(define n(read))
(sum-list-members (list n))
(set! count i)
(if (not(= n -1))
(loop (+ i 1)))
)
(newline)
)
Using chicken-scheme, I'd do it like this:
(define (read-number-list)
(map string->number (string-tokenize (read-line))))
Define your sum-list-members as such:
(define (sum-list-members lst)
(fold + 0 lst))
To get string-tokenize to work, you might have to use a certain srfi. Fold is pretty much the same thing as you wrote, except that it's a function that takes a function and initial value as parameters.
The function has to receive 2 parameters, the first parameter is the current value and the second parameter is the value returned by the previous call or the initial value.
(do ((mlist () (cons n mlist))(n (read)(read)))
((= n -1) (display (apply + mlist))))
the format can turn any type into a string, e.g
(define lam-form (list `lambda (list `x ) (list `when (list `> `x 0) (list `* 100 `x ))))
(format "~s" lam-form)
result will be: "(lambda (x) (when (> x 0) (* 100 x)))"
Then my question is: how to do the reverse? meaning, turn "(lambda (x) (when (> x 0) (* 100 x)))" back to '(lambda (x) (when (> x 0) (* 100 x)))
Use read.
Welcome to Racket v5.1.3.1.
-> (read (open-input-string "(lambda (x) (when (> x 0) (* 100 x)))"))
'(lambda (x) (when (> x 0) (* 100 x)))
If you're referring only to the use of the "~s" formatting directive, then "read" is the right choice. See the docs for racket's "printf", then click through on the definition of "write" for more information.
If, on the other hand, you want to reverse any use of format, then there may be no unique answer; e.g., undoing (format "~a~a" "abc" "def") is not possible (in the sense that there are multiple possible calls that produce abcdef ).