Convert a string to list - racket

Calling all racket developers, I am a newbie in the language of racket. I want to convert a string to a list.
I have a string like this:
"(1 2 3 4 5)"
I want to converted to:
'(1 2 3 4 5)
I tried using string-> list but this is the result:
(#\(
#\1
#\space
#\2
#\space
#\3
#\space
#\4
#\space
#\5
#\))

Here's one possible way, using Racket's read.
#lang racket
(define (convert str)
(with-input-from-string str
read))
(convert "(1 2 3 4 5)") ;=> '(1 2 3 4 5)
Normally, (read) will read an input from standard input. However, I use with-input-from-string to redirect the read operation on a string instead.

Here we split the string while ignoring the non-digits, then convert the digits to numbers:
#lang racket
(define (convert str)
(map string->number (string-split str #px"[ )()]")))
(convert "(1 2 3 4 5)")
; => '(1 2 3 4 5)

Related

Introducing new symbols into Common-Lisp Function/Macro

I want to define a functionality in common lisp which uses some words/symbols not known to lisp, for example having such a function/macro:
(my-func-or-macro lst key-word idx)
which returns items in the lst upto the idx if the key-word is to and from the idx to the end if the key-word is from.
So practically it should work like:
(my-func-or-macro '(1 2 3 4 5 6) from 3) => '(4 5 6)
and
(my-func-or-macro '(1 2 3 4 5 6) to 3) => '(1 2 3)
Since macros don't evaluate their arguments i think i should be using a macro which doesn't care about from and to (note i don't want to pass quoted args like 'from 'to).
Since every argument to a function is evaluated before the function is executed, you need a symbol that evaluates to itself.
Such symbols are already part of the language: all symbols in the special KEYWORD package evaluate to themselves. Symbols that are written with a leading colon, e. g. :foo are interned into that package.
Also part of the language are keyword arguments that use such keywords to identify parameters:
(defun my-func (list &key from)
(subseq list from))
(my-func '(0 1 2 3 4 5) :from 3)
=> (3 4 5)
You can give default values to such parameters:
(defun my-func (list &key (from 0) (to (length list)))
(subseq list from to))
(my-func '(0 1 2 3 4 5) :from 3)
=> (3 4 5)
(my-func '(0 1 2 3 4 5) :to 3)
=> (0 1 2)
(my-func '(0 1 2 3 4 5) :from 1 :to 4)
=> (1 2 3)
Keyword arguments can be given in any order:
(my-func '(0 1 2 3 4 5) :to 4 :from 1)
=> (1 2 3)

How can I add a value stored in a variable to a list?

For example:
(setf s 2)
s => 2
(setf list1 '(1 s 3 4))
list1 => (1 s 3 4)
How do i get it to add the value stored in s to the list?
For this example I would want to use s to generate a list (1 2 3 4)
I have a lisp book I'm reading and I can't seem to find any mention of how to do this so I thought i'd ask.
Thanks
So quoted data in Scheme are like String constants.. If I wrote "1 s 3 4" in Java I wouldn't be able to get s replaced with the variable contents. I 'd have to write "1 " + s + " 3 4". In Lisp we have backquote to do this in list structures:
`(1 ,s 3 4)
; ==> (1 2 3 4)
Note that this is a trick.. It's like "1 $s 3 4" in PHP as it's representing code that creates the list with the unquoted variables evaluated and return a new list structure. Under the hood it's very similar to writing:
(list 1 s 3 4)
; ==> (1 2 3 4)
And of course list is not a primitive since it just uses cons. What it does is this:
(cons 1 (cons s (cons 3 (cons 4 '()))))
; ==> (1 2 3 4)
I would want to use s to generate a list (1 2 3 4)
The function list can be handy:
CL-USER 14 > (let ((s '2))
(list 1 s 3 4))
(1 2 3 4)
The function LIST creates a fresh new list from its arguments.

Apparent 'eval' of quote symbol in CLISP

Some output from the CLISP REPL:
[1]> (list 'list 1 2 3)
(LIST 1 2 3)
[2]> (list 'list '(1 2 3))
(LIST (1 2 3))
[3]> (list 'quote 1 2 3)
(QUOTE 1 2 3)
[4]> (list 'quote '(1 2 3))
'(1 2 3)
The first three, I understand exactly what's going on: The list function is passed a symbol ('list or 'quote) and so the result is a list that begins with the list or quote symbol. It's the fourth that confuses me. Why doesn't it return (QUOTE (1 2 3))?
I realise that if you enter (QUOTE '(1 2 3)) into the REPL, you get '(1 2 3) back, so the expression are equivalent in that sense. But (LIST 1 2 3) is equivalent to (1 2 3), and yet the first expression doesn't return that.
It seems inconsitent that (list 'quote 1 2 3) returns a list with the first item being a quote symbol, but (list 'quote (1 2 3)) returns a quoted list. Especially since expressions like (list 'list ...) seem to always return a list beginning with the symbol - so far, at least, quote is the only 'special case' like this.
It's not the easiest question to articulate, so I'm hoping I've managed to get my confusion across. Can anyone explain why quote gets treated in this seemingly-unique way?
'something is the same as (quote something) for the lisp reader. Even when nested it will be the case. The next expressions I will double quote so that after evaluation one of the quotes are still in there.
When printing the implementations can choose what to output where there are several possible representations, so some implementations would print the evaluation of ''something as
(quote something) while others may use the abbreviation 'something.
'(quote 1 2 3) cannot be abbreviated since a quoted form only has one argument. Thus here both lisp systems would print (quote 1 2 3).
Here is a way to look at your last expression:
(let ((data (list 'quote '(1 2 3))))
(format nil
"whole thing: ~a first element: ~a second-element: ~a"
data
(car data)
(cadr data)))
This will either evaluate to "whole thing: '(1 2 3) first element: QUOTE second-element: (1 2 3)" or "whole thing: (QUOTE (1 2 3)) first element: QUOTE second-element: (1 2 3)".
Since the printer never sees if the input is abbreviated and the data has the same structure in memory the output is never affected by how you input the data. Thus (quote (quote (1 2 3))) will print the same as ''(1 2 3).
You have the same behaviour with cons cells but the standard dictates how the rules are. (cons 1 (cons 2 (cons 3 '()))) would be (1 . (2 . (3 . ()))) but is actually just printed (1 2 3) However if you (cons 1 2) you get (1 . 2) showing that print treats the output differently based on the cdr. However the reader can read any of these and they will all print the same eg. '(1 . (2 . (3 . ()))) ==> (1 2 3) and (+ . (2 . ( 3 . ()))) ; ==> 5
Numbers can have as many visual forms as there are bases below the number in question.
(let ((*print-base* 16))
(print 255)) ; prints FF (255 in hexadecimal)
list does not have any abbreviation or specialness in Lisp. It's not even a primitive function but it's very helpful as it removes the inconvenience of having to cons by hand everytime. It can be defined like this:
(defun my-list (&rest lst)
lst)
(my-list 1 2 3 4) ; ==> (1 2 3 4)
Note that a REPL (the READ-EVAL-PRINT-LOOP) does three things:
reading using the function READ
evaluating using the function EVAL
and printing the result using something like the function PRINT
To understand what is going on you have to look at all three functions.
Let's look at the third form:
(list 'quote 1 2 3)
This is read as a list of five elements:
LIST
(QUOTE QUOTE)
1
2
3
EVAL then evaluates the arguments, and calls the function list with the four results and returns a new result, a list of four elements:
QUOTE
1
2
3
PRINT then takes this list and writes it as: (QUOTE 1 2 3). There is no abbreviated way to print it.
Let's look at the fourth form:
(list 'quote '(1 2 3))
This is read as a list of three elements:
LIST
(QUOTE QUOTE)
(QUOTE (1 2 3))
eval calls list with two arguments:
QUOTE
(1 2 3)
eval then returns a list of length two:
QUOTE
(1 2 3)
print now can print this list in two different ways:
(QUOTE (1 2 3)) or the abbreviated form '(1 2 3). Here a quote character is in front of a single expression.
Your implementation used the first version.

mcons in dr racket

I'm having trouble reading output from dr racket. By default it displays lists using mcons. For example, sicp exercise 2.32 produces:
> (subsets (list 1 2 3))
(mcons
(mcons
'()
(mcons
(mcons 3 '())
(mcons
(mcons 2 '())
(mcons
(mcons 2 (mcons 3 '()))
(mcons
(mcons 1 '())
(mcons
(mcons 1 (mcons 3 '()))
(mcons
(mcons 1 (mcons 2 '()))
(mcons (mcons 1 (mcons 2 (mcons 3 '()))) '()))))))))
'())
I'm having trouble reading this. Is there a way to make the output look like:
(() (3) (2) (2 3) (1) (1 3) (1 2) (1 2 3))
Thanks!
Do you know what language are you using in your #lang line? The rest of the instructions below are assuming that you're using a #lang line.
If you are in #lang r5rs and you display or write the values, you should see the output you expect.
> (define p (list 1 2))
> (display p)
(1 2)
> (set-car! p 'one)
> (display p)
(one 2)
If you just type the values bare in Interactions, DrRacket will print them, and that uses the representation you're seeing. In DrRacket, you can customize the way that values print. Here's the process, step-by-step:
Go to the Language menu, and select Choose Language. You should see the language dialog pop up.
If the button on the lower left says Show Details, click it, and the dialog window should expand to include customizations.
Look for the Output Style option. There should be four choices: Constructor, Quasiquote, write, and print. Select write style, and then press Ok to confirm the customization.
Once you do this, then:
> (display (list 1 2))
(1 2)
> (write (list 1 2))
(1 2)
> (list 1 2)
{1 2}
It will still print slightly differently than you expect, using curly braces, because it's trying to notate that the list structure is mutable.
If this bothers you, we can fix that. Add the following line near the top of your program (but after the #lang line).
(#%require r5rs/init)
This line pulls in a Racket-specific module called r5rs/init that tries to improve r5rs compliance; in particular, the braces should finally print as round ones for mutable pairs.
> (display (list 1 2))
(1 2)
> (write (list 1 2))
(1 2)
> (list 1 2)
(1 2)

How to convert a string to list using clisp?

How can i convert the string "1 2 3 4 5 6 7" into the list (1 2 3 4 5 6 7) elegantly? I am using CLISP.
Here is a recursive solution.
;Turns a string into a stream so it can be read into a list
(defun string-to-list (str)
(if (not (streamp str))
(string-to-list (make-string-input-stream str))
(if (listen str)
(cons (read str) (string-to-list str))
nil)))
You should use parse-integer in a loop.
For example, using loop:
(let ((string "1 2 3"))
(loop :for (integer position) := (multiple-value-list
(parse-integer string
:start (or position 0)
:junk-allowed t))
:while integer
:collect integer))
⇒ (1 2 3)
If you need better control about the splitting, use the split-sequence or cl-ppcre library.
If you need to parse more general number formats, use the parse-number library.
Libraries are available from Quicklisp.
Hint: Take a look at with-input-from-string.
(with-input-from-string (s "1 2 3 4 5 6 7" :index i :start 0 :end 13)
(list (read s) (read s) (read s) (read s) (read s) (read s)))
(1 2 3 4 5 6 7)
it works however i feel it is not so elegant as there are many read call .
thanks again!
I think this might work:
(setf s "1 2 3 4 5 6 7")
(setf L-temp (coerce s 'list))
This makes a list with spaces as elements. Remove spaces:
(setf L-final (remove #\Space L-temp))
I see that Svante is right. My previous attempt did not work. Here is another attempt. I use concatenate to change the string into a list representation. Then I use read-from-string to convert the string (s-2) into an actual list.
(setf s-0 "1 2 3 4 5 6 7")
(setf s-1 (concatenate 'string "(" s ")" ))
(setf s-2 (read-from-string s-1))
I roll it into a function like this:
(defun from-string-to-list (s)
(let ((L (read-from-string
(concatenate 'string "(" s ")"))))
L))
The only purpose of "let" and "L" is to make the function from-string-to-list return only the list and not return multiple values. read-from-string returns two values: The list and the size of the string, I think.
That would do,
(with-input-from-string (s "1 2 3 4 5")
(let ((r nil))
(do ((line (read s nil 'eof)
(read s nil 'eof)))
((eql line 'eof))
(push line r))
(reverse r)))