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.
Related
I want to store a function like print in a variable so that I can just type something short like p, e.g:
In Scheme:
(define print display)
(print "Hello world\n")
;; alternate way
(define print 'display)
((eval print) "Hello world\n")
The same approach does not seem to work in Common Lisp:
(defvar p 'print)
;;(print (type-of p))
(p "Hello world") ;; Attempt 1
((eval p) "Hello world") ;; >> Attempt 2
((eval (environment) p) "Hello world") ;; Attempt 3
I'm getting this error with Attempt 1 above:
*** - EVAL: undefined function P
And this with Attempt 2 and 3 in Clisp:
*** - EVAL: (EVAL (ENVIRONMENT) P) is not a function name; try using a
symbol instead
*** - EVAL: (EVAL P) is not a function name; try using a symbol instead
And with gcl:
Error: (EVAL P) is invalid as a function.
Error: (EVAL (ENVIRONMENT) P) is invalid as a function.
So:
What does try using a symbol mean? p is definitely a symbol; false positive?
What's up with eval? Doesn't the evaluation of p yield the procedure print?
I thought Lisp procedures were first class objects. Why is Attempt 1 not working like in Scheme?
EDIT
(Moved from a comment below)
I was wondering why (setf (symbol-function 'p) #'print) won't work this way
(setf (symbol-function 'p) 'print). I get the following(not so helpful) error:
*** - SYSTEM::%PUTD: PRINT is not a function ;; CLisp
Error: PRINT is not of type LIST. ;; Gcl
I know that the sharp sign(#) is supposed to disambiguate between a function and a variable
with the same name but in this case, there's only one print, the function.
Also, why won't it work with defvar instead of setf like so:
(defvar (symbol-function 'p) #'print)
yet defvar and setf both assign values to a variable.
The associated error is:
*** - DEFVAR: non-symbol (SYMBOL-FUNCTION 'P) cannot be a variable ;; Clisp
Error: (SYMBOL-FUNCTION (QUOTE P)) is not of type SYMBOL. ;; Gcl
Common Lisp is a "Lisp-2". Among other things, the first position in a function call is evaluated in the "function namespace". In your case, the symbol p names a variable, not a function.
This works better:
(defvar p 'print)
(funcall p "Hello world")
Or possibly, but you probably don't want to do this:
(setf (symbol-function 'p) #'print)
(p "Hello world")
Common Lisp has a separate namespace for functions, which makes operation like this more verbose than with Scheme. If you would like similar to top level (define p display) in CL you should make a macro:
(defmacro defun-alias (name original-name)
`(setf (symbol-function ',name) #',original-name))
Which works as this:
(defun-alias pc princ)
(pc "Hello") ; prints hello
Unlike Scheme define this will only overwrite a global binding. Thus:
(flet ((test (x) (+ x x)))
(defun-alias test +)
(test 10))
will set global definition of #'test to #'+ and return 20. eg. it works like defun.
To complement the other good answers with direct answers to your questions:
What does try using a symbol mean? p is definitely a symbol; false positive?
Read the error messages literally: (EVAL (ENVIRONMENT) P) and (EVAL P) (unevaluated) are not symbols, but lists. In Common Lisp, the car of a form is not evaluated.
What's up with eval? Doesn't the evaluation of p yield the procedure print?
eval is never called by your code (see previous answer). Even if it were, the result would be the symbol-value of the symbol print, not the symbol-function/fdefinition.
I thought Lisp procedures were first class objects. Why is Attempt 1 not working like in Scheme?
This has nothing to do with functions (I think the Common Lisp standard does not use the term "procedures" as the Scheme standards do.) being first class objects. This works in Common Lisp:
(let ((p #'print))
(funcall p "hello world"))
Edit:
Answers to the extra questions:
I was wondering why (setf (symbol-function 'p) #'print) won't work this way
(setf (symbol-function 'p) 'print).
It's not really true that "the sharp sign(#) is supposed to disambiguate between a function and a variable with the same name", as you write later. 'print expands to (quote print), so it evaluates to the symbol print instead of its value as a variable. #'print expands to (function print), so it evaluates to the value of the function cell of the symbol print instead. Whether print currently has a value as a variable is completely irrelevant to what #'print evaluates to.
Setting (symbol-function 'p) to the symbol print obviously won't make p call the function print because the symbol print is not the same as the function bound to the symbol print.
Also, why won't it work with defvar instead of setf like so:
(defvar (symbol-function 'p) #'print)
yet defvar and setf both assign values to a variable.
setf assigns values to places. The term (symbol-function 'p) denotes the place that is the function cell of the symbol p.
defvar defines new global variables. Its first argument needs to be a symbol that names the variable and can not be any kind of place.
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
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.
What's the best way to read input from stdin in racket?
In particular I'd like something like cin from c++ or scanf from c where I specify the types of things I want read and they are returned.
read-line is easy. To be portable across Unix and Windows, additional option is required.
(read-line (current-input-port) 'any)
Return and linefeed characters are detected after the conversions that
are automatically performed when reading a file in text mode. For
example, reading a file in text mode on Windows automatically changes
return-linefeed combinations to a linefeed. Thus, when a file is
opened in text mode, 'linefeed is usually the appropriate read-line
mode.
So, 'any is required to be portable when the input port is not a file (standard input).
Test program:
#lang racket
(let loop ()
(display "Input: ")
(define a (read-line (current-input-port) 'any))
(printf "input: ~a, length: ~a, last character: ~a\n"
a
(string-length a)
(char->integer (string-ref a (- (string-length a) 1))))
(loop))
In Windows, replace (read-line (current-input-port) 'any) with (read-line) and see what happens.
You can do pretty much everything you want to... at the low level, I would suggest (read-line) and (read-bytes). For higher-level processing (as e.g. scanf does), I would suggest a regexp-match on the input. For instance
(regexp-match #px" *([0-9]+)" (current-input-port))
I'd use the read procedure for the general case. If the data type to be read is known beforehand, use read-char, read-string, read-bytes.
Also, take a look at this implemenation for reading formatted input - a scanf in Scheme.
Here's a basis for line-by-line processing in Racket Scheme. It doesn't split an input line into multiple words, or do typed input, but this seems like a good place to put it.
(define (get)
(read-line (current-input-port)))
(define (put . vs)
(for-each display vs)
(displayln ""))
(define (sed fn)
(let ((line (get)))
(if (not (eof-object? line))
(begin
(fn line)
(sed fn))
'true)))
(sed (lambda (line)
(put "Hello, " line)))
Here's one that does split input, also encodes CSV for good measure.
(define (get)
(read-line (current-input-port)))
(define split string-split)
(define sep ",")
(define enc identity)
(define (enc-csv s)
(string-append "\"" (string-replace s "\"" "\"\"") "\""))
(define enc enc-csv)
(define (put . vs)
(displayln (string-join (map enc vs) sep)))
(define (sed fn)
(let ((line (get)))
(if (not (eof-object? line))
(begin
(fn line)
(sed fn))
'true)))
(sed (lambda (line)
(apply put (split line))))
This works in Racket. I'm not sure how much of it is specific to Racket. It doesn't seem to work in Chicken or Guile.
I tried an example where we need to pass a list as arguments and if condition succeeds I want to add result to a new list.
Here's the code:
(define get-description
(lambda (codeValue newList)
(cond
((= (car codeValue) 1) (cons "A" newlist))
((= (car codeValue) 2)(cons "B" newlist))
((= (car codeValue) 3) "C")
(else "Negative numbers are not valid"))))
I pass this as the function call:
(get-description (list 1 2 3) (list))
I get output:
(cons "A" empty)
Output should just show: (A)
I am using DrRacket for writing my programs and have chosen language mode as: Beginning Student.
Why do I get cons and A with "" and empty in my newlist?
Please don't use "Beginning Student" as a language type in Racket. That's a subset specially made for the HtDP book. The languages "racket", "r5rs", "pretty big", are more like real Schemes and should all work for The Little Schemer.
In your arguments list, you have (codeValue newList), but in the program body you refer to newlist. All of the Schemes that I've used are case-sensitive. Changing your newList to newlist made your program run perfectly fine on Chez Scheme and Guile too.
Edit: To clarify, "A" is a string. Scheme also has the additional data type of symbol, which is just a name and nothing else (and is probably what you want here). You probably want to (cons 'A newlist) rather than (cons "A" newlist) if you're expecting (A).
Other Schemes would print just ("A"). Such output is clearly an idiosyncrasy of the Racket language.
As for why the A is in quotation marks, that's because it's a string object, and that's simply how string objects are printed. But if you were to DISPLAY such an object, you'd get the A by its lonesome.