Why single quote is ignored in case expression? - racket

(case 'x
[(x) "ex"]
[('x) "quoted ex"])
I thought the output would be "quoted ex", but it is "ex" actually. Why 'x match x but not 'x?

In the first case, (x) is already quoted, from the documentation (emphasis mine):
The selected clause is the first one with a datum whose quoted form is equal? to the result of val-expr.
Therefore, ('x) is doubly-quoted. If you wanted to match the second case, something like this would be necessary:
(case ''x
[(x) "ex"]
[('x) "quoted ex"])
=> "quoted ex"
To put it another way, the first condition in your code is testing if (equal? 'x 'x) and the second one tests (equal? 'x ''x), clearly only the first one matches.

Related

syntax for unsyntax in syntax-parse

can someone point me to how I can write this in syntax-parse/case?
[(list e ...) #`(list #,(f #'e) ...)]
basically I'd like each element in the list to be processed individually by f in unsyntax. I don't think the above is the right syntax?
You can use unsyntax-splicing (which can be abbreviated as #,#) to embed result of list returning expression as individual elements of outer list. Then you can use map procedure to apply f over all elements of list returned by (syntax->list #'(e ...)) expression. In the end it will look like this:
#`(list #,#(map f (syntax->list #'(e ...))))

Explain me my LISP code

I'm new in LISP and I'm trying to understand recursion.
What I know is that recursion needs a STOP condition. In my code below, can you explain to me why (equal x 0) 1 is my STOP condition SINCE fact(- X 1) could continue indefinitely as in my second condition, I have set to t the second line of my cond which means it should continue.
BUT when I run the program, it works fine though. Below is my code (found by chance)
(defun fact(x)
(cond
((equal x 0) 1)
(t (*(fact(- x 1)) x))
)
)
cond expresssions have a number of clauses. Each clause is of the form (expr1 expr2). If the expr1 evaluates to true then expr2 is evaluated and that is the returned value of thecond`. No other clauses are evaluated.
So, once x becomes 0 the first clauses of cond evaluates to true and that call to fact returns 1.
The other clause of cond has a first expression of t which is true by definition; thus if the first clause is not used it always uses the second clause. (A cond clause with t is like an "else" in an "if" statement in other langugaes.)
This function is recursive, if you call it with an argument of 2, it checks if 2 == 0, it doesn't so then it multiplies 2 with the value returned by recursively calling itself with 1. Since 1 != 0 it will return the value of 1 multiplied by the value of recursively calling itself with 0. Since 0 does equal 0 it just returns 1, which is used one layer to return 1 which is then used at the top layer of this recursion to return 2.
Common Lisp has a function trace which will let you see when your function is called and with what arguments. Typically each recursive call will be indented so you can see something like this:
(fact 2)
(fact 1)
(fact 0)
Which can be helpful for understanding this function.
(As mentioned in a comment - this function doesn't catch the case of a negative input - but that is error handling and could be easily fixed).

sqrt function gets error in racket

I'm trying to build a simple function that gets a number, checks if the number is more the zero and return the square root of the number:
#lang pl 03
(: sqrtt: Number -> Number)
(define (sqrtt root)
(cond [(null? root) error "no number ~s"]
[( < root 0) error "`sqrt' requires a non-negative input ~s"]
[else (sqrt root)]))
but the result I get when I'm trying to compile the function is:
type declaration: too many types after identifier in: (: sqrtt: Number
-> Number)
Why am I getting that error and how do I fix it?
Try this:
(define (sqrtt root)
(cond [(null? root) (error "no number ~s")]
[(< root 0) (error "`sqrt' requires a non-negative input ~s")]
[else (sqrt root)]))
You simply forgot the () around error. Remember that error is a procedure and, like all other procedures, to apply it you have to surround it with parentheses together with its arguments.
The error message you're getting tells you that you have too many types after an identifier in a : type declaration. Now in racket, sqrtt: counts as an identifier. What you probably meant was sqrtt :, with a space in between.
(: sqrtt : Number -> Number)
The difference is that type declarations of the form (: id : In ... -> Out) are treated specially, but those of the form (: id In ... -> Out) are not. And sqrtt: is counts as the id.
There's also the problem Oscar Lopez pointed out, where you're missing parens around the error calls. Whenever you call a function in racket, including error, you need to wrap the function call in parens.
Also, the (null? root) clause is useless, since root has the type Number and null? will always return false for numbers.
And another thing, depending on what the pl language does, if you get a type error from < afterwards, that's because < operates on only Real numbers, but the Number type can include complex numbers. So you might have to change the type to Real or something.

Calling a Clojure function with string inside swap?

The macro, transform!, as defined below seems to work for => (transform! ["foo" 1 2 3]). The purpose is to take in a list, with the first element being a string that represents a function in the namespace. Then wrapping everything into swap!.
The problem is that transform! doesn't work for => (transform! coll), where (def coll ["foo" 1 2 3]). I am getting this mystery exception:
#<UnsupportedOperationException java.lang.UnsupportedOperationException: nth not supported on this type: Symbol>
The function:
(defmacro transform!
" Takes string input and update data with corresponding command function.
"
[[f & args]] ;; note double brackets
`(swap! *image* ~(ns-resolve *ns* (symbol f)) ~#args))
I find it strange that it works for one case and not the other.
Macros work at compile-time and operate on code, not on runtime data. In the case of (transform! coll), the macro is being passed a single, unevaluated argument: the symbol coll.
You don't actually need a macro; a regular function will suffice:
(defn transform! [[f & args]]
(apply swap! *image* (resolve (symbol f)) args)))
Resolving vars at runtime could be considered a code smell, so think about whether you really need to do it.
You're passing a symbol to the macro, namely coll. It will try to pull that symbol apart according to the destructuring statement [f & args], which won't be possible of course.
You can also use (resolve symbol) instead of (ns-resolve *ns* symbol).

Can you return nothing from a function in Scheme?

I'm writing a scheme interpreter, and in the case of an if statement such as:
(if (< 1 0) 'true)
Any interpreter I've tried just returns a new prompt. But when I coded this, I had an if for whether there was an alternative expression. What can I return in the if such that nothing gets printed?
(if (has-alternative if-expr)
(eval (alternative if-expr))
#f) ;; what do I return here?
According to the R6RS specification:
If <test> yields #f and no <alternate>
is specified, then the result of the
expression is unspecified.
So go wild, return anything you want! Although #f or '() are what I, personally, would expect.
Scheme can indeed return no values:
> (values)
In R5RS the one-armed form of if is specified to return an unspecified value.
That means it is up to you, to decide which value to return.
Quite a few Schemes have chosen to introduce a specific value called
"the unspecified value" and returns that value.
Others return "the invisible value" #<void> and the REPL is written
such that it doesn't print it.
> (void)
At first one might think, this is the same as (values),
but note the difference:
> (length (list (void)))
1
> (length (list (values)))
error> context expected 1 value, received 0 values
(Here (list ...) expected 1 value, but received nothing)
If #<void> is part of a list, it is printed:
> (list (void))
(#<void>)
A number of Schemes (PLT, Ikarus, Chicken) have a void type, which you can produce with (void).
In PLT at least, void is what you get when you do (when (< 1 0) #t).
(PLT v4 doesn't allow if without an else clause.)
When the return value is unspecified you can return what you like; the user just can't rely on that value being there, ever, or across implementations.
First, it's OK to require if to have an else clause, if it makes it easier for you. Second, Scheme supports returning multiple values from a function, so if you were to implement the return values as a list, you could have an empty list signify that no return value was given.
(if (has-alternative if-expr)
(eval (alternative if-expr)) ; make sure eval returns a list
'())
An important distinction here: I'm not returning an empty list if there was no else clause. The empty list signifies that there was no return value. If there were one return value from an expression (say it was 3) you would have (3) as the return from the eval behind the scenes. Similarly, returning multiple values from an expression would cause the eval return list to have multiple elements.
Finally, in all practicality, you could really return anything if the condition fails and there's no else, because it would be an error in a program to attempt to capture the value of a function that doesn't return anything. As such, it would be the job of the programmer, not the language, to catch this error.
Weird people would return 'nil or '|| (the empty symbol). The problem is to return a symbol that cannot be return by (eval (alternative if-expr)) to avoid confusion.
If anything can be returned by (eval (alternative if-expr)) and you still want to know whether you came in this alternative or not, you have to pack the result with more information :
(if (has-alternative if-expr)
(cons #t (eval (alternative if-expr)))
(cons #f #f))
Thus, the result is a cons cell. If its car is #t, then you evaled something. If it is #f, you didn't.
What is wrong with just:
(if (has-alternative if-expr) (eval (alternative if-expr)))
?