Unwanted quote mark when dealing with the simply-scheme package - scheme

Following the answer in this question I installed the simply-scheme package and ran the follwing code:
#lang simply-scheme
(se (butlast (bf "this"))
"world")
But what I got is '(hi "world") rather than (hi "world"). Why is there an quote mark and how to fix it?

I think this is just question of settings. In DrRacket, choose Language settings, Choose Language, Show Details, set Output Style to print or write, run your code again and compare outputs.
For #lang simply-scheme it seems to work like this:
print:
> (se (butlast (bf "this"))
"world")
'(hi "world")
write:
> (se (butlast (bf "this"))
"world")
(hi "world")
See also Output Printing Styles.

Related

Use variable padding in iteration directive in FORMAT

Is there a way to do something like the following?
(format t "~{~va~}" '("aa" "bb" "cc") 4)
I need to iterate through a list. Each element of that list should be padded with a variable number of spaces (specified at runtime, so I cannot use "~4a").
Or more generally, is there a way to refer to a specific argument in the argument list of FORMAT?
By nesting format function, you can do what you want.
(format t (format nil "~~{~~~Aa~~}" 4) '("aa" "bb" "cc"))
;; returns: aa bb cc
Here the inner format directive:
The nil as first argument, format returns a string.
(format nil "~~{~~~Aa~~}" 4)
;; returns: "~{~4a~}" - and this is exactly what you want to give
;; to the outer `format` as second argument!
You can of course write a function for this:
(defun format-by-padding-over (lst padding)
(format t (format nil "~~{~~~Aa~~}" padding) lst))
And then:
(format-by-padding-over '("aa" "bb" "cc") 4)
;; aa bb cc
;; NIL
I learned this trick here from #Sylwester (many thanks!).
You could also interleave the list with repetitions of the padding:
(format t "~{~va~}"
(mapcan (lambda (element)
(list 4 element))
list))
You can build the format control string using nested format functions, but then you have to take care about escaping tildes. When working with regular expressions (using CL-PPCRE), one can define regular expressions using trees, like (:alternation #\\ #\*), which helps preventing bugs and headaches related to escaping special characters. The same can be done with format strings, using format-string-builder, available in Quicklisp:
(lambda (v)
(make-format-string `((:map () (:str ,v)))))
Returns a closure, which can be used to build format strings:
(funcall * 10)
=> "~{~10a~}"

string-set! not working in Racket

Following code is giving error:
(define s "test")
(string-set! s 0 #\T)
The error is:
string-set!: contract violation
expected: (and/c string? (not/c immutable?))
given: "test"
argument position: 1st
other arguments...:
How can I change a character of 's' using string-set! function? I think it has to be made "mutable". How can that be done?
That's because a string defined using the default reader is immutable; it's literally the first thing stated in the documentation. For example, to turn it into a mutable string:
(define s (string-append "test"))
(string-set! s 0 #\T)
It works as expected:
s
=> "Test"

How to extract the last character of a string of unknown length?

I am writing a function that takes stringA and stringB as parameters and compares the first character of stringB with the last character of StringA. If they are equal, then the function returns true, else false is returned.
I have nearly the whole function ready, however I can't find a way to take the last character of stringA because its length is unknown. I checked the documentation and I found nothing. Any suggestions?
(cond
[(string=? (substring stringA ???) (substring stringB 0 2))"True"]
[else "False"])
You can get the last character position of a string using string-length (or rather one less than):
(string-ref str (sub1 (string-length str)))
Note that a character is different from a string of length 1. Thus the correct way to extract a character is with string-ref or the like, rather than substring.
It seems Chris answered your question. Just a reminder, to use the string-ref, which returns a character, you should use the comparison function char=? (or equal?).
I'd like to add another solution which I find more elaborate, but requires to download a collection from the planet racket (after installing package collections). Using the collections package, you can use the same function with any collection rather then just strings, using the (last ..) and (first ..) functions of the module.
(require data/collection)
(let ([stringA "abcd"]
[stringB "dcba"])
(cond
[(equal? (last stringA)
(first stringB)) "True"]
[else "False"]))
You could also use the SRFI-13 function string-take-right, which returns the last n characters of the argument string as a string.
every language has a length function for a string. in Racket I found this :
https://docs.racket-lang.org/reference/strings.html#%28def.%28%28quote.~23~25kernel%29._string-length%29%29
there is this : string-length str
so just run that it will give you the length and then you can extract the last character

Scheme - Optional arguments and default values

I'm currently looking into Scheme, and the way I have understood it, procedures can take an arbitrary number of arguments.
I have been trying to play around with this, but I'm struggling to grasp the concept.
For instance, say I want to write a welcome message, based on information provided by the user.
If user provides a first and last name, the program shout write:
Welcome, <FIRST> <LAST>!
;; <FIRST> = "Julius", <LAST>= "Caesar"
Welcome, Julius Caesar!
Otherwise, the program should refer to a default value, specified as:
Welcome, Anonymous Person!
I have the following outline for my code, but struggling with how to finalise this.
(define (welcome . args)
(let (('first <user_first>/"Anonymous")
('last <user_last>/"Person"))
(display (string-append "Welcome, " first " " last "!"))))
Example usage:
(welcome) ;;no arguments
--> Welcome, Anonymous Person!
(welcome 'first "John") ;;one argument
--> Welcome, John Person!
(welcome 'first "John" 'last "Doe") ;;two arguments
--> Welcome, John Doe!
Any help is highly appreciated!
In Racket, the way to do this would be using keyword arguments. You can define a function with keyword arguments my writing #:keyword argument-id when declaring the arguments:
(define (welcome #:first first-name #:last last-name)
(display (string-append "Welcome, " first-name " " last-name "!")))
Which you can call like this:
> (welcome #:first "John" #:last "Doe")
Welcome, John Doe!
However, what you want is to make them optional. To do that, you can write #:keyword [argument-id default-value] in the argument declaration.
(define (welcome #:first [first-name "Anonymous"] #:last [last-name "Person"])
(display (string-append "Welcome, " first-name " " last-name "!")))
So that if you don't use that keyword in a certain function call, it is filled with the default value.
> (welcome)
Welcome, Anonymous Person!
> (welcome #:first "John")
Welcome, John Person!
> (welcome #:first "John" #:last "Doe")
Welcome, John Doe!
> (welcome #:last "Doe" #:first "John")
Welcome, John Doe!
#Alex Knauth's answer is great. That's something I didn't know about.
Here's an alternative, though it's not quite as flexible
(define (welcome (first "Anonymous") (last "Person"))
(displayln (string-append "Welcome, " first " " last "!")))
This works pretty nicely with your basic requirements
> (welcome)
Welcome, Anonymous Person!
> (welcome "John")
Welcome, John Person!
> (welcome "John" "Doe")
Welcome, John Doe!
However, Alex's solution has two distinct advantages.
The arguments can be called in either order
The last name can be specified without the first name

how do i write a string to a file without quote marks in scheme

I'm trying to write a string to a file, but every time i do it has quotes around it.
I've tried
(call-with-output-file file-path
(lambda(output-port)(write "some text" output-port)))
and
(let ((p (open-output-file file-path)))
(write "some text" p)
(close-output-port p))
but in both cases i expected "some text" but got "\"some text\""
I'm currently working in chicken-scheme but I don't think that matters.
write is for serializing S-expressions to a file. It is the opposite of read, which will read a serialized S-expression back into lists, symbols, strings and so on. That means write will output everything like it would occur in source code.
If you just want to output a string to a port, use display:
(call-with-output-file file-path
(lambda(output-port)
(display "some text" output-port)))
Or in CHICKEN, you can use printf or fprintf:
(call-with-output-file file-path
(lambda(output-port)
(fprintf output-port
"Printing as s-expression: ~S, as plain string: ~A"
"some text"
"some other test")))
This will print the following to the file:
Printing as s-expression: "some text", as plain string: some other text

Resources