I have a problem with concatenation and spaces in Scheme.
The result of the command:
(append '(%procedure:) (list '+) '(%))** //with spaces
is:
%procedure: + % //without spaces
How can I make the same result without space between the lists, so the result will be:
%procedure:+%
You're trying to use symbols, which aren't the same thing as strings in Scheme. If you want to have control over your printed output, you should use strings, which are arrays of characters.
> (append '(hello) '(world))
(hello world)
> (string-append "hello " "world")
"hello world"
> (symbol->string 'hello)
"hello"
> (apply string-append (map symbol->string '(a b c d e f g)))
"abcdefg"
append returns a list, and the evaluator prints the result like (a b c), where spaces are inserted to make the representation clear. If you need %procedure:+%, you may create a new symbol or use strings instead of symbols.
Related
I'm running into an odd issue with Common Lisp's format directive that only shows itself in GNU CLISP, which leads me to wonder if it's a bug in the implementation.
Consider the following code
(defun f (s args)
(format nil "~A~{~A~%~}" s args))
The function f produces a string consisting of the s argument, followed by each argument, where each argument (but not the header) is followed by a newline. So, for instance, I would expect
(format t "~A" (f "foo" '("arg1" "arg2")))
to produce
fooarg1
arg2
which it does, correctly. Now, consider the following calls
(format t "~A" (f "a" ()))
(format t "~A" (f "b" ()))
(format t "~A" (f "c" '("d")))
Given that the only newlines I ever print out are following elements from the second argument of f, and the first two calls pass an empty list for the second f argument, I expect to see no newlines until the very end, i.e. I expect this to print
abcd
It does exactly this in SBCL. However, in GNU CLISP, I get
ab
cd
Note the newline between b and c.
Changing the code to
(format t "~S" (f "a" ()))
(format t "~S" (f "b" ()))
(format t "~S" (f "c" '("d")))
shows the following, even less illuminating, results
"a""b"
"cd
"
So the newline between b and c is not part of either of the strings. Why is CLISP deciding to print a newline in between these format statements? And how can I prevent it from doing so?
This is a feature of GNU CLISP. See the documentation of *pprint-first-newline*.
If you want a different output than that, bind either *print-pretty* or *pprint-first-newline* to nil during your format invocation.
I have to combine a list of words to produce a para. I managed following:
(define (wordlist2para wl)
(define str " ")
(for ((w wl))
(set! str (string-append str w " ")))
(string-trim str))
(wordlist2para '("this" "is" "a" "test"))
Output:
"this is a test"
It works but it is not functional. How can I write functional code for this?
If I wanted to do it explicitly and not use string-join, I would recurse and use three cases:
The empty list produces the empty string
A one-element list produces its sole element (this avoids having a trailing separator)
Otherwise, append the car and a space to the recursion on the cdr.
Like this:
(define (wordlist2para ws)
(cond ((null? ws) "")
((null? (cdr ws)) (car ws))
(else (string-append (car ws) " " (wordlist2para (cdr ws))))))
No need of recursion or loop, there is the primitive function string-join for this (see the manual):
(define (wordlist2para wl)
(string-join wl " "))
(wordlist2para '("this" "is" "a" "test"))
;; -> "this is a test"
We have standard procedures that does this:
;; racket library or srfi/13
(string-join '("this" "is" "it")) ; ==> "this is it"
There is a way to always rewrite these that are quite simple. I'd like to step away from rackets great feature set and just focus on simple scheme with recursive procedures. Notice that in your loop you are changing 2 things wl gets smaller, str gets longer, so lets make that:
; all things that change as arguments
(define (wordlist2para-loop wl str)
(if (null? wl)
str
(wordlist2para-loop (cdr wl)
(string-append str (car wl) " "))))
Now for we just replace the loop:
(define (wordlist2para wl)
(wordlist2para-loop wl ""))
From here on you can move the helper to become local or perhaps make it a named let or any other refactoring, but it doesn't really change the resulting compiled result in an implementation much, just how it looks.
Notice I haven't fixed the bug where there is only one word. (wordlist2para '("this")) ; ==> "this " The result is actually exactly the same as in your, only that it's tail recursive and functional.
I am not sure if following can be called functional but it does use some higher order functions:
(define (wordlist2para wl)
(string-trim
(apply string-append
(map (lambda(x) (string-append x " ")) wl))))
(wordlist2para '("this" "is" "a" "test"))
Output:
"this is a test"
I hope this hasn't been asked already. I saw a bunch of single vs double quotes for other languages (html, javascript, python) but can't find scheme
In scheme at the interpreter, if I type:
(something 'x)
I understand that the x will be treated as an x, not evaluated to something as if it is a variable
On the other hand, if I use
(something x)
x is evaluated as if its a variable
I know that ' is a short hand for quote (ie (quote x)) but what I don't get is how that differs from a double quote.
If I type
"hello"
at the prompt, I get back "hello"
Is the only difference that the double quote keeps the quotes around the data? I've heard the double quote is like a char array, but it doesn't get evaluated and neither does the single quote, so that is the difference and when/why would I use one over the other?
Thanks all.
In Scheme, single quotes and double quotes are entirely different constructs. Double quotes produce a string:
> (string? "foo")
#t
Whereas the prefix operator single quote prevents an expression from being evaluated. E.g. (+ 1 2) evaluates to 3, but when you single-quote it, you get a list consisting of +, 1 and 2:
> (define three '(+ 1 2))
> three
(+ 1 2)
> (car three)
+
> (cadr three)
1
> (caddr three)
2
It's actually syntactic sugar for an operator called quote, which you can verify by quoting twice:
> ''foo
(quote foo)
The important thing is that 'not evaluated' doesn't mean 'not parsed'.
Compare:
>'(+ a b)
(mcons '+ (mcons 'a (mcons 'b '())))
>(string->symbol "(+ 1 2)")
'|(+ 1 2)|
repeat takes in a number and a string, and returns the string repeated n times, separated by a space.
;; repeat: number string -> string
(define (repeat n str)
(replicate n str))
(repeat 2 "home")
gives me:
"homehome"
How would I add a space so it can give me "home home"?
Add a space to the string str at the end, before passing it to replicate:
(replicate n (string-append str " "))
That'll leave an extra space at the end, if you want to get rid of it do as #Tobia suggests:
(string-trim (replicate n (string-append str " ")))
Racket has a build-in function string-join for this, so in plain Racket this would be
> (string-join (build-list 2 (lambda (i) "home")))
"home home"
if I have something like this
(define s (hi,there))
then how can I write in match
like
(match s [(,h , ,t)] ...)
But it is not working, because match needs the , so how can I do this?
First note that the comma , is a special reader abbreviation.
The (hi,there) is a read as (hi (unquote there)). This is
difficult to spot - since the default printer prints lists
whose first element is an unquote in a special way.
Welcome to DrRacket, version 5.3.0.14--2012-07-24(f8f24ff2/d) [3m].
Language: racket.
> (list 'hi (list 'unquote 'there))
'(hi ,there)
Therefore the pattern you need is '(list h (list 'unquote t))'.
> (define s '(hi,there))
> (match s [(list h (list 'unquote t)) (list h t)])
(list 'hi 'there)
Use a backslash if you want to use comma as a symbol inside of a quoted section:
> (define s '(hi \, there))
> (match s [(list h c t) (symbol->string c)])
","
And use '|,| for the standalone comma symbol.
> (match s [(list h '|,| t) (list h t)])
'(hi there)
In either case, you really should use whitespace to separate things, and use lists.
(define s (hi,there)) is not valid Racket.
I think you might be confused about where you need commas. In Racket, you do not use commas to separate elements in a list. Instead, you just use whitespace. Tell me if this is wrong, but what I imagine is that you are trying to match an expression like (define s '(hi there)). To do that, you would use
(match s
[`(,h ,t) ...])
Then, in the area where the elipses is, the variable h has the value 'hi, and the variable t has the value 'there