I have a list in Lisp which I am sorting through, and I want to make an if statement that checks if the current object in the list is a character or an integer.
Is there something like:
(if (EQUAL currentObject char)
...)
Or
(if (EQUAL currentObject integer)
...)
That I can use??
Many thanks.
There are various ways to determine, which kind of object you have at hand.
(typep EXPR 'character) ;; ==> True, if EXPR evaluates to a character
(characterp EXPR) ;; ==> ------------ " -----------------------
(typep EXPR 'integer) ;; ==> True, if EXPR evaluates to an integer
(integerp EXPR) ;; ==> ------------ " -----------------------
Have a look at the definition of typep, typecase, characterp, ...
(loop
for element in list
do (typecase element
(integer #| element is an integer number ... |#)
(character #| element is a character object ... |#)
(t #| element is something not covered above |#)))
For many built-in types, there are predicate functions available, which can be used in to test, whether a particular value is an instance of that type. Often, these predicates are named after their base type's names, with a "p" appended ("stringp", "symbolp", "numberp", "consp", ...)
Related
I am writing a simple interpreter that should
output: +inf or -inf for the following computations:
(/ 0)
(/ 1 0)
(/ -0)
I notice that replaced 0 by 0.0 gives me the behavior I want.
But I haven't figured out to convert -0 to -0.0.
exact->inexact loses the negative sign.
(exact->inexact -0) gives 0.0.
To do this, with the literal text -0 you would have to change the Reader so that -0 reads equal to -0.0, an inexact version. To be consistent you might want to read every number as an inexact number, whether it has a decimal point or not.
It's worth noting that you can do this by prefixing a number #i, for example #i-0 reads equal to -0.0. However, it sounds like you might want to change the reader so that every number reads the same as if it had #i prefixed onto it including -0.
One of the easier ways to extend the reader is with a readtable. You can make a function that extends a readtable like this:
;; Readtable -> Readtable
(define (extend-readtable orig-rt)
;; Char InputPort Any Nat Nat Nat -> Any
(define (rt-proc char in src ln col pos)
....)
...
(make-readtable orig-rt
#f 'non-terminating-macro rt-proc
...))
To use this to define a #lang language, you need to put the reader implementation in your-language/lang/reader.rkt. Here that's inexact-number/lang/reader.rkt, where the inexact-number directory is installed as a single-collection package (raco pkg install path/to/inexact-number).
inexact-number/lang/reader.rkt
#lang racket
(provide (rename-out [-read read]
[-read-syntax read-syntax]
[-get-info get-info]))
(require syntax/readerr
syntax/module-reader)
;; Readtable -> Readtable
(define (extend-readtable orig-rt)
;; Char InputPort Any Nat Nat Nat -> Any
(define (rt-proc char in src ln col pos)
....)
...
(make-readtable orig-rt
#f 'non-terminating-macro rt-proc))
;; [X ... -> Y] -> [X ... -> Y]
(define ((wrap-reader rd) . args)
(parameterize ([current-readtable (extend-readtable (current-readtable))])
(apply rd args)))
(define-values [-read -read-syntax -get-info]
(make-meta-reader 'inexact-number
"language path"
lang-reader-module-paths
wrap-reader
wrap-reader
identity))
The main work goes into filling in the .... holes in the extend-readtable function. Within the rt-proc, you can have it "peek" into the input port in to see if its a number, and if it is, call the Racket reader on a port that has #i appended to the front of in. You might be able to do this with something like input-port-append:
(input-port-append #f (open-input-string "#i") in)
In the context of extend-readtable, here's some code that does the peeking and re-reading:
;; Readtable -> Readtable
(define (extend-readtable orig-rt)
;; Char InputPort Any Nat Nat Nat -> Any
(define (rt-proc char in src ln col pos)
(define try-in (peeking-input-port in))
(define try (read/recursive try-in char orig-rt))
(cond
[(number? try)
;; read it as if it had #i on the front
(define prefix (string-append "#i" (string char)))
(define inexact-in
(input-port-append #f (open-input-string prefix) in))
(read-syntax/recursive src inexact-in #f orig-rt)]
[else
;; read normally
(read-syntax/recursive src in char orig-rt)]))
(make-readtable orig-rt
#f 'non-terminating-macro rt-proc))
Once you have this done, you should be able to use it like this:
#lang inexact-number racket
-0
; => -0.0
(/ -0)
; => -inf.0
P.S. I have now made #lang inexact-number available on the Racket package server, as the package inexact-number-lang. By the way, there's also #lang exact-decimal, which has the opposite affect of making numbers like 5.2 into exact rational numbers.
This is because -0 in Racket is the same literal datum that can also be written as 0, +0, 0000000, #e0, #e-0/1, -00000/1, or in various other ways. All of these syntaxes produce the very same value from the reader, which is an exact integer. Unlike floating-point numbers, exact numbers don't have signed zeros. To illustrate:
> (exact-integer? 0)
#t
> (exact-integer? +0)
#t
> (exact-integer? -0)
#t
> (eq? +0 -0)
#t
> (eq? -0 0)
#t
To get the behavior you want, you need to adjust the reader layer so that 0 and -0 don't produce the same value. I don't think there is a built-in parameter for doing what you want (there are for many other reader customizations), but you can do it by creating a custom readtable.
I would need more context to give you further guidance (for example, you say you're writing an "interpreter," which isn't the usual way of making a DSL in Racket), but my first inclination would be that, rather than re-implementing number parsing, you might map - to a "non-terminating-macro" and handle the rest in the expander (or interpreter) layer.
-0 doesn't exist! If you enter something silly like (define x -0) and press the Macro stepper #'> before any transformations you'll see it has read it in as (define x 0). The sign is truncated by the reader since integers doesn't have positive and negative zero like IEEE754 does. Thus unless you create your own language with your own reader that can discriminate on signed zero mapped to a data structure that supports it you cannot solve this.
IEEE754 floating points has the sign as it's own bit and thus every number, including 0, can be both positive and negative.
As for Scheme standard: Before R6RS there was no requirement for a full numeric tower and the report even mentions that a floating point only Scheme might be useful. Thus I believe some implementations of R5RS actually might read -0 as -0.0.
This question already has an answer here:
Distinguish &optional argument with default value from no value
(1 answer)
Closed 6 years ago.
I am converting some Scheme code to Common Lisp. I don't know Scheme. I know a bit of Common Lisp.
Here is the Scheme code:
(define (close-enuf? h1 h2 #!optional tolerance scale)
(if (default-object? tolerance)
...))
I converted that Scheme code to this Common Lisp:
(defun close-enuf? (h1 h2 &optional tolerance scale)
(if (xxx tolerance)
...))
Aside from xxx, does that look right?
Now, with regard to xxx, what is the Common Lisp equivalent for default-object?
I found this definition of default-object?:
The predicate default-object?, which is true only of default objects, can be used to determine which optional parameters were supplied, and which were defaulted.
I'm not sure what that is saying. Is it saying that default-object? returns true if the argument's value is the default value (not a passed-in value)?
This is covered in the Ordinary Lambda Lists section of the specification:
lambda-list::=
(var*
[&optional {var | (var [init-form [supplied-p-parameter]])}*]
[&rest var]
[&key {var | ({var | (keyword-name var)} [init-form [supplied-p-parameter]])}* [&allow-other-keys]]
[&aux {var | (var [init-form])}*])
The &optional arguments can be single symbols or a list with two or three elements.
In that case, the second value is the default value.
The third value names a variable which holds a boolean value: it is true if and only if the value bound to var was supplied by the caller.
Otherwise, a NIL indicates that the value is the default one.
For example:
(defun foo (&optional (x 1 xp))
(list x xp))
With no argument supplied:
(foo)
=> (1 nil)
With an explicit argument:
(foo 2)
=> (2 T)
With an argument that is indistinguishable from the default value:
(foo 1)
=> (1 T)
In your case, that would be:
(defun close-enough-p (h1 h2 &optional (tolerance nil tolerance-p) scale)
(if tolerance-p
<supplied>
<default>))
Note that the same goes for &key arguments.
I'm trying to create a function that will take a string and display it.
(defun closing (s)
(format t "~{~a~}" ("Sincerely," "\n" s)))
What I hope to get is
Sincerely,
Frank
if "Frank" is the string I passed in. It complains of the variable S is defined but never used. What am I doing wrong?
Trying to use format alone: If I declare urname as a defparameter to be "Frank", the following doesn't print Frank, rather just the variable name. (Without quote it complains of urname not being a function.)
(format t "~{~a~}" '(urname urname urname))
How can I feed variables to format?
There are three issues here: (1) The code you posted doesn't just have the problem of not using s; it's also trying to call the string "Sincerely" as a function; (2) quoting a list means you'll get exactly what's quoted (e.g., a list of symbols, not a list of values of variables); (3) calling format with lists.
(something other-stuff...) is a function call
When I put the code you posted into SBCL, I get some very specific and helpful output:
CL-USER> (defun closing (s)
(format t "~{~a~}" ("Sincerely," "\n" s)))
; in: DEFUN CLOSING
; ("Sincerely," "n" S)
;
; caught ERROR:
; illegal function call
; (SB-INT:NAMED-LAMBDA CLOSING
; (S)
; (BLOCK CLOSING (FORMAT T "~{~a~}" ("Sincerely," "n" S))))
;
; caught STYLE-WARNING:
; The variable S is defined but never used.
;
; compilation unit finished
; caught 1 ERROR condition
; caught 1 STYLE-WARNING condition
("Sincerely," "\n" s) is an illegal function call, since a string, like "Sincerely", can't have a function binding. Since SBCL sees the problem in that, it recognizes that the one thing that s might have been used for (i.e., an argument to a function call), can't happen. That's why you'll get the error, and then the associated style warning.
Creating lists of values
The second is probably answered in other questions already, but the short answer is that you want (list x y z), not '(x y z). The former calls the function list with the values of the variables x, y, and z, while the latter denotes a literal list of the symbols x, y, and z.
CL-USER> (let ((a 42)
(b 89))
(print '(a b)) ; a list of two symbols
(print (list a b))) ; a list of two numbers
(A B)
(42 89)
Format, iteration, &c.
The third is probably more interesting, since format has so many possibilities. The ~{ and ~} in your example are used for iterating over values in a list. First, let's look at a simple example: you can just use the format directive ~a and call format with the arguments you want to splice in:
CL-USER> (let ((closing "Sincerely")
(name "Frank"))
(format t "~a,~%~a" closing name))
Sincerely,
Frank
Now, if you need to print multiple values, you can use ~{ and ~} to have format iterate over a list of values:
CL-USER> (let ((closing "Sincerely")
(names '("Frank" "John")))
(format t "~a,~{~%~a~}" closing names))
Sincerely,
Frank
John
If the names are the values of variables, then you can either create a list containing those values:
CL-USER> (let ((closing "Sincerely")
(name1 "Frank")
(name2 "John"))
(format t "~a,~{~%~a~}" closing (list name1 name2)))
Sincerely,
Frank
John
or you can change ~{ to ~#{ and have format read the remaining arguments as the list:
CL-USER> (let ((closing "Sincerely")
(name1 "Frank")
(name2 "John"))
(format t "~a,~#{~%~a~}" closing name1 name2))
Sincerely,
Frank
John
You should read a tutorial about format, from here for example
For an easy explanation
(format
(destination-stream usually t for standard output nil to form a string)
(here comes the string)
(&rest variables that should write in the string where is an ~A and by position like String.format in java or c))
in your case, you need the symbol ~% or use the character for return in common lisp
CL-USER> (defun closing (s) (format t "~A~%~%~A" "Sincerely," s))
CLOSING
CL-USER> (closing "paco")
Sincerely,
paco
NIL
The nil say that the functions returns null, and the other is the standard output if you want to return a string, put nil instead of t
Can anyone explain why this isn't working? I am following the documentation and I cannot understand why I get an error:
(define (functionName n)
(if (n < 10) ;;if condition
1 ;; then condition
3)) ;; else condition
I get the error:
application: not a procedure;
expected a procedure that can be applied to arguments
given: 5
arguments...:
#<procedure:<>
10
You can see this in two ways. Your code is correct and you just called it wrong (bad type for n) or your code was accidentally written in infix notation. I'll illustrate both:
Passed wrong argument
n can be any data type and it can even be a procedure and if it is there is nothing wrong with your code:
(define (compare-15 predicate-procedure argument)
(predicate-procedure 15 argument))
(define (compare-2 predicate-procedure argument)
(predicate-procedure 2 argument))
(functionName compare-15) ; ==> 3
(functionName compare-2) ; ==> 1
What happens is that your procedure is calling the supplied procedure with a procedure for comparing < and an argument.
Accidental infix
Algol programmers are used to prefix fun( expr ) and infix x cmp y while in LISP dialects all those have one common form and that is prefix all the way: (fun expr) and (cmd x y).
(define (function-name n)
(if (< n 10) ;; predicate expression
1 ;; consequent expression
3)) ;; alternative expression
(function-name 15) ; ==> 3
(function-name 2) ; ==> 1
Since Scheme can have functions as argument, meaning every argument can be put in the first position, it might be exactly what you wanted and Scheme doesn't know until it gets a number to be called as a procedure that something is wrong.
The error message is quite clear when you know that every procedure call is called application. It expected to call a procedure but behind the variable n there was a number. "expected a procedure that can be applied to arguments. given: 5" probably makes more sense now?
Try this:
(define (functionName n)
(if (< n 10)
1
3))
Remember: Scheme uses prefix notation, meaning that all operators must go before the operands. In other words, this is wrong: (n < 10), and this is correct: (< n 10).
The function should be the first thing in the if (scheme uses prefix notation, not infix).
(define (functionName n)
(if (< n 10) ;;if condition
1 ;; then condition
3)) ;; else condition
Then
(functionName 2)
Outputs
1
when I run it in Chicken Scheme.
I want it to extract all the words that have a letter e in them.
eg.
(ewords '(i e ee o oo)) -> '(e ee)
Berkeley's 61a lecture uses (first 'word) to extract the first character of the word. However DrScheme screams at me when I try to do that. How do take the first character of the word? like
(first 'word)->'w.
You'll need to convert it to a string explicitly:
(first (symbol->string 'word)) -> "w"
(I'm not sure off the top of my head whether first operates on strings. You can use string->list to convert to a list and then take the first if it doesn't.)
EDIT: It might be easier to pass around strings instead of symbols in the first place -- to designate a string, use double quotes (e.g. (ewords '("i" "e" "ee" "o" "oo")).) I don't know if this is your intent, but since you're learning, I thought I should mention the distinction.
Symbols are primarily meant to be atomic values, i.e., they are not usually taken apart and examined. If you really want to do it you must first do some type conversions:
; #\a -> a
(define (char->symbol chr)
(string->symbol (list->string (list chr))))
; abc -> (a b c)
(define (symbol->list sym)
(map char->symbol
(string->list (symbol->string sym))))
You can now use first:
> (first (symbol->list 'word))
w
It depends, what is the data definition for a "word"?
Is it a sequence of characters (aka a string)? Is it a list of characters? A list of strings? A list of symbols?
Here is a function that meets your criteria, but as you can see, it is convoluted and I wonder if it is what you really want:
; symbol->list-of-symbols : symbol -> (ListOf symbol)
; To destructure a symbol into a list of its constituent parts
(define (symbol->list-of-symbols sym)
(map (lambda (s) (string->symbol (string s)))
(string->list (symbol->string sym))))