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.
Related
Emacs version: 26.3
Slime version: 2.26.1
I start up Emacs.
I open up a simple .lisp file.
(defun testfn (x y)
(+ x y))
(defmacro testmc (form)
form
`(list 1 2 3))
I place my cursor over the symbol defun and issue the keyboard-command M-. (slime-edit-definition).
This should bring me to the definition of defun.
But it doesn't.
It brings me here:
I place my cursor over the symbol defmacro and issue the keyboard-command M-. (slime-edit-definition).
This should bring me to the definition of defmacro.
But it doesn't.
It brings me here:
Why does it do this & how do I fix this
Notice there is a warning in the REPL when trying to find the source of DEFUN:
WARNING: inconsistent 2 form-number-translations
You can replicate it yourself in the REPL:
CL-USER> (let ((slynk::*buffer-package* (find-package :cl))
(slynk::*buffer-readtable* *readtable*))
(slynk:find-definitions-for-emacs "DEFUN"))
WARNING: inconsistent 2 form-number-translations
(("(DEFMACRO DEFUN)"
(:LOCATION (:FILE "/home/chris/data/src/sbcl/src/code/macros.lisp")
(:POSITION 4140)
(:SNIPPET "(setq doc nil)
(let* (;; stuff shared between LAMBDA and INLINE-LAMBDA and NAMED-LAMBDA
(lambda-guts `(,#decls (block ,(fun-name-block-name name) ,#forms)))
(lambda `(lambda ,lambda-list ,#lambda-guts))
(named-lambda `("))))
To find where the warning comes from, you could do as I did first and do a textual search on the repository, or you could use the following alternate method that works better, namely invoke the debugger on warnings:
(handler-bind ((warning (lambda (c) (invoke-debugger c))))
(let ((slynk::*buffer-package* (find-package :cl))
(slynk::*buffer-readtable* *readtable*))
(slynk:find-definitions-for-emacs "DEFUN")))
This comes from SLYNK-SBCL::FORM-NUMBER-POSITION, and the interesting value in the debugger is the source location obtained from SBCL:
#<SB-INTROSPECT:DEFINITION-SOURCE {10369C50F3}>
--------------------
The object is a STRUCTURE-OBJECT of type SB-INTROSPECT:DEFINITION-SOURCE.
PATHNAME: #P"SYS:SRC;CODE;MACROS.LISP"
FORM-PATH: (5)
FORM-NUMBER: 89
CHARACTER-OFFSET: 3917
FILE-WRITE-DATE: 3825178034
PLIST: NIL
DESCRIPTION: NIL
It says the source is the fifth toplevel form in the file (which corresponds to the character offset), and from here, the FORM-NUMBER is the 89th form in a depth-first search walk of the form (this comes from the structure's docstring).
But, if I recompile the function FORM-NUMBER-POSITION with DEBUG set to 3, the toplevel form read at this position, TLF is NIL:
1: (SLYNK-SBCL::FORM-NUMBER-POSITION #S(SB-INTROSPECT:DEFINITION-SOURCE :PATHNAME #P"SYS:SRC;CODE;MACROS.LISP" :FORM-PATH (5) :FORM-NUMBER 89 :CHARACTER-OFFSET 3917 :FILE-WRITE-DATE 3825178034 :PLIST NIL..
Locals:
DEFINITION-SOURCE = #S(SB-INTROSPECT:DEFINITION-SOURCE :PATHNAME #P"SYS:SRC;CODE;MACROS.LISP" :FORM-PATH (5) :FORM-NUMBER 89 :CHARACTER-OFFSET 3917 :FILE-WRITE-DATE 3825178034 :PLIST NIL :DESCRIPTION NIL)
FORM-NUMBER = 89
PATH-TABLE = #((0 0))
POS-MAP = #<HASH-TABLE :TEST EQ :COUNT 126 {103B227EA3}>
POS-MAP#1 = #<HASH-TABLE :TEST EQ :COUNT 126 {103B227EA3}>
STREAM = #<SB-IMPL::STRING-INPUT-STREAM {7F3E0350D953}>
TLF = NIL
TLF#1 = NIL
TLF-NUMBER = 5
In read-source-form, you can see that the form is being read inside a (ignore-errors (read ...)) form, which returns NIL in case of error. I tried calling (read ...) only but this somehow did not invoke the debugger, so I did the same thing as above and explicitly invoked it on any condition.
There is an error, namely that the package "SB-XC" does not exist, which is expected since, if I am not mistaken, this is a package that only exists during the compilation of SBCL itself.
I think you should contact the SBCL SLY developers and file a bug for this directly, they would certainly have a better idea of how to fix the behaviour (feel free to link to your question in addition to giving the usual details of the bug report).
I'm seeing pretty much what you're seeing.
Defun (line 280 of defboot.lisp) is a macro, which is defined in terms of defun-expander (line 230 of defboot.lisp) which is what you're seeing.
Whereas, defmacro takes you directly to its definition (line 15 of defmacro.lisp) which is what you're seeing.
It seems to be doing useful things.
I defined a new function 'addmore'
(defun addmore (x y z)
(testfn x (testfn y z)))
I compiled it all, and M-. on 'addmore' takes me to the definition of testfn.
So I think it's all working.
I am new to Racket Lang and previously I wrote thousands of lines of code in C++, Java and C. I am trying to figure out how to do the following task:
Given an array (like C uint8_t array) with the following format:
First byte is used to indicate the "format", let's say this could be 0x0a, 0x0b and so on.
Remaining data may include C strings without the null terminator and integers.
Write a function that parses the array and puts the values in some variables.
Before asking here, I was reading: https://docs.racket-lang.org/guide and also https://docs.racket-lang.org/reference
My approach is as follows:
I am using a byte string because it seems it can be used to mimic the C++/C arrays.
I am using tail recursion to traverse the "array".
Questions:
1) In C, I always use the return value of a function as an error code: 0 is ok and any negative value is an error. With Racket, I am using multiple return values to indicate: a) the return code, b) the processed value(s), i.e. something like:
(values return_code out1 out2 ...)
What do you think? Do you recommend the use of exceptions for error handling?
2) What's the best approach to process arrays in Racket? I mean, the best according to the offered by Racket and to achieve a good performance.
Thanks!
Edit1:
Regarding my first question (the return codes), I am calling many functions and I would like to return an exit code that helps me to know if there was an error inside the function. This is a sample code:
#lang racket
(define (is_valid in)
(cond
[(and (>= in 10) (<= in 15)) #t]
[else #f]))
(define (copy_values in)
(define len (bytes-ref in 2))
; 3 is where the string "ABCD" begins
(define str (subbytes in 3 (+ 3 len)))
(define numbers (subbytes in (+ 3 len)))
(values str numbers))
(define (parse in)
(define type (bytes-ref in 0))
(if (is_valid type)
(let ()
(define-values (str numbers) (copy_values in))
(values #t str numbers))
(values #f 0 0)))
; format: type strlen
; len |-- str --| | -- numbers -- |
;
(define input1 (bytes 10 10 4 65 66 67 68 110 120 130 140 150))
(define input2 (bytes 1 10 4 65 66 67 68 110 120 130 140 150))
(parse input1)
(parse input2)
This is the output in DrRacket:
Welcome to DrRacket, version 6.7 [3m].
Language: racket, with debugging; memory limit: 128 MB.
#t
#"ABCD"
#"nx\202\214\226"
#f
0
0
Look how I use the (values ...) stuff, does that make sense?
To return a value to the operating system, use (exit [v]).. Other values should probably go to standard out and/or standard error. This means writing them before the program exits.
In terms of assigning the values of an array to variables, there are many ways to do it depending on how lexical scope comes into play within the function and module and across modules. Also reference semantics versus value semantics are considerations.
Finally, there is no compelling reason to choose recursion over an explicit loop when dealing with a byte-string. bytes-length is a low level primitive implemented in C and will return the length needed for a loop without testing for an empty byte-string.
I have the following structures:
(defstruct track
size
env
startpos
endpositions)
(defstruct state
pos
vel
action
cost
track
other)
I have a state and Im trying to access endpositions(list of lists)
(setq coluna_final (nth 1 (nth 0 (state-track-endpositions st))))
but I get the error: EVAL: undefined function STATE-TRACK-ENDPOSITIONS
What am I doing wrong?
The first defstruct defines (inter alia) function track-endpositions, and the second defines state-track. Lisp has no way to know that the latter returns a track (even if you declare the slot type, it will not define the function you want).
You can do it yourself:
(defun state-track-endpositions (st)
(track-endpositions (state-track st)))
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).
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)))
?