I am trying to work on writing objects with Racket, and I am trying to implement "inheritance".
(define-syntax class-trait
(syntax-rules (with)
[(class <Class> (<attr> ...) (with <traits> ...)
[(<method> <param> ...) <body>]...)
(define (<Class> <attr> ...)
(lambda (msg)
(cond [(equal? msg (id->string <attr>)) <attr>]
...
[(equal? msg (id->string <method>))
(lambda (<param> ...) <body>)]
...
[else ((<traits> <param> ...) ... msg)]
))
)]))
This is what I have currently, but for the final else statement, the ellipsis does not work.
Let's first discuss the meaning of the error: "incompatible ellipsis match counts for template".
Suppose the a matches (1 x #t) and b matches (2 y #f), then
the template ((a b) ...) produces ((1 2) (x y) (# f).
Now if a matches (1 x) and b matches (2 y #f) then what should ((a b) ...) produce ? The match counts of a and b are not compatible (of the same length).
In your code, I think, the template
((<traits> <param> ...) ...
could be problematic, if the number of <traits> doesn't match the number of <param> ...s.
Related
(defun all-longer-than-1-char? (&rest elements)
(every (lambda (x) (> (length
(cond ( (typep x 'integer) (write-to-string x) )
( (typep x 'string) x )
( (typep x 'symbol) (symbol-name x) )
))
1))
elements))
(all-longer-than-1-char? "OK" "NO" 1)
I'd like this function to work on symbol parameters (i.e. without having to double quote or to enter numbers) but it doesn't work. To make it work with symbol parameters:
(defun all-longer-than-1-char? (lst)
(every (lambda (x) (> (length
(cond ( (typep x 'integer) (write-to-string x) )
( (typep x 'string) x )
( (typep x 'symbol) (symbol-name x) )
))
1))
lst))
(all-longer-than-1-char? '(OK NO 1))
NIL
But this time I have to enclose the parameters inside parentheses and quote it. I'd like to make it work both with symbol parameters and without having to put parameters inside parentheses and quote them, like:
(all-longer-than-1-char? OK NO 1)
How to do it?
You can use &rest to create what would once have been called a 'nospread' function (or an 'lexpr' depending on your religion), which is very often less useful other than as a user-interface since if you have a list of things you then have to use apply.
Common Lisp doesn't have functions which don't evaluate their arguments, which was once what was known as a 'nlambda' (or an 'fexpr' if you belong to the wrong cult), so you need to quote forms which would otherwise mean something to the evaluator.
You can get the same result as an nlambda with a macro. But you almost certainly don't want to do that as it smells like a bad use of a macro.
Given
(defun all-longer-than-1-char-p (list)
(every (lambda (x)
(> (length
(etypecase x
(string x)
(integer (write-to-string x))
(symbol (symbol-name x))))
1))
list))
Then the nospread one might be
(defun all-longer-than-1-char-p/nospread (&rest list)
(all-longer-than-1-char list))
And the nlambda one might be
(defmacro all-longer-than-1-char-p/quoted/nospread (&rest things)
`(all-longer-than-1-char ',things))
So now
> (all-longer-than-1-char-p '(xx yy 12 "foo"))
t
> (all-longer-than-1-char-p/nospread 'xx 'yy 12 "foo")
t
> (all-longer-than-1-char-p/quoted/nospread xx yy 12 "foo")
t
(All assuming *print-base* is less than 13).
But
> (let ((x "xx"))
(all-longer-than-1-char-p/quoted/nospread x))
nil
So, not very semantically useful, and kind of a poster child for how not to use macros.
This question already has answers here:
Common lisp error: "should be lambda expression"
(4 answers)
Closed 5 years ago.
I'm trying to make a function that changes infix input to prefix eg : (x + 1) as input outputted as (+ x 1).
So here is my code for the moment :
(setq x '(Y + 1))
(if (listp x ) (list (second x) (first x) (first (last x))) x)
so it returns (+ Y 1) if I input a list and the user input if it's not a list.
However, the problem is that I can't get this code working in a function :
(defun prefixToInfix (x)(
(if (listp x ) (list (second x) (first x) (first (last x))) x)
)
)
the function is indeed created but when I call it
(prefixtoinfix '(Y + 1))
I get an error
Error: Illegal function object: (IF (LISTP X) (LIST # # #) X).
[condition type: TYPE-ERROR]
I don't know why my if statement works in the main program but doesn't when I run it from my function.
What you are missing is that in Lisp parentheses are meaningful.
In C/Java/Python &c, the following expressions are the same:
a+b
(a+b)
(a)+(b)
(((a)+(b)))
(((((a)+(b)))))
In Lisp, the following expressions are very different:
a --- a symbol
(a) --- a list with a single element, which is the symbol a
(1 (2)) --- a list of two elements:
number 1
list of of length 1, containing number 2
In your case, function (note indentation and paren placement!)
(defun prefixToInfix (x)
((if (listp x) (list (second x) (first x) (first (last x))) x)))
has extra parens around if (and this causes the whole if form to be interpreted as a function, with disastrous results), and should be (note line breaks and indentation - lispers do not count parens, they look at indentation to understand the code, see http://lisp-lang.org/style-guide/)
(defun prefix-to-infix (x)
(if (listp x)
(list (second x)
(first x)
(first (last x)))
x))
PS. See also recommendations in want to learn common lisp.
During the execution of my code I get the following errors in the different Scheme implementations:
Racket:
application: not a procedure;
expected a procedure that can be applied to arguments
given: '(1 2 3)
arguments...:
Ikarus:
Unhandled exception
Condition components:
1. &assertion
2. &who: apply
3. &message: "not a procedure"
4. &irritants: ((1 2 3))
Chicken:
Error: call of non-procedure: (1 2 3)
Gambit:
*** ERROR IN (console)#2.1 -- Operator is not a PROCEDURE
((1 2 3) 4)
MIT Scheme:
;The object (1 2 3) is not applicable.
;To continue, call RESTART with an option number:
; (RESTART 2) => Specify a procedure to use in its place.
; (RESTART 1) => Return to read-eval-print level 1.
Chez Scheme:
Exception: attempt to apply non-procedure (1 2 3)
Type (debug) to enter the debugger.
Guile:
ERROR: In procedure (1 2 3):
ERROR: Wrong type to apply: (1 2 3)
Chibi:
ERROR in final-resumer: non procedure application: (1 2 3)
Why is it happening
Scheme procedure/function calls look like this:
(operator operand ...)
Both operator and operands can be variables like test, and + that evaluates to different values. For a procedure call to work it has to be a procedure. From the error message it seems likely that test is not a procedure but the list (1 2 3).
All parts of a form can also be expressions so something like ((proc1 4) 5) is valid syntax and it is expected that the call (proc1 4) returns a procedure that is then called with 5 as it's sole argument.
Common mistakes that produces these errors.
Trying to group expressions or create a block
(if (< a b)
((proc1)
(proc2))
#f)
When the predicate/test is true Scheme assumes will try to evaluate both (proc1) and (proc2) then it will call the result of (proc1) because of the parentheses. To create a block in Scheme you use begin:
(if (< a b)
(begin
(proc1)
(proc2))
#f)
In this (proc1) is called just for effect and the result of teh form will be the result of the last expression (proc2).
Shadowing procedures
(define (test list)
(list (cdr list) (car list)))
Here the parameter is called list which makes the procedure list unavailable for the duration of the call. One variable can only be either a procedure or a different value in Scheme and the closest binding is the one that you get in both operator and operand position. This would be a typical mistake made by common-lispers since in CL they can use list as an argument without messing with the function list.
wrapping variables in cond
(define test #t) ; this might be result of a procedure
(cond
((< 5 4) result1)
((test) result2)
(else result3))
While besides the predicate expression (< 5 4) (test) looks correct since it is a value that is checked for thurthness it has more in common with the else term and whould be written like this:
(cond
((< 5 4) result1)
(test result2)
(else result3))
A procedure that should return a procedure doesn't always
Since Scheme doesn't enforce return type your procedure can return a procedure in one situation and a non procedure value in another.
(define (test v)
(if (> v 4)
(lambda (g) (* v g))
'(1 2 3)))
((test 5) 10) ; ==> 50
((test 4) 10) ; ERROR! application: not a procedure
Undefined values like #<void>, #!void, #<undef>, and #<unspecified>
These are usually values returned by mutating forms like set!, set-car!, set-cdr!, define.
(define (test x)
((set! f x) 5))
(test (lambda (x) (* x x)))
The result of this code is undetermined since set! can return any value and I know some scheme implementations like MIT Scheme actually return the bound value or the original value and the result would be 25 or 10, but in many implementations you get a constant value like #<void> and since it is not a procedure you get the same error. Relying on one implementations method of using under specification makes gives you non portable code.
Passing arguments in wrong order
Imagine you have a fucntion like this:
(define (double v f)
(f (f v)))
(double 10 (lambda (v) (* v v))) ; ==> 10000
If you by error swapped the arguments:
(double (lambda (v) (* v v)) 10) ; ERROR: 10 is not a procedure
In higher order functions such as fold and map not passing the arguments in the correct order will produce a similar error.
Trying to apply as in Algol derived languages
In algol languages, like JavaScript and C++, when trying to apply fun with argument arg it looks like:
fun(arg)
This gets interpreted as two separate expressions in Scheme:
fun ; ==> valuates to a procedure object
(arg) ; ==> call arg with no arguments
The correct way to apply fun with arg as argument is:
(fun arg)
Superfluous parentheses
This is the general "catch all" other errors. Code like ((+ 4 5)) will not work in Scheme since each set of parentheses in this expression is a procedure call. You simply cannot add as many as you like and thus you need to keep it (+ 4 5).
Why allow these errors to happen?
Expressions in operator position and allow to call variables as library functions gives expressive powers to the language. These are features you will love having when you have become used to it.
Here is an example of abs:
(define (abs x)
((if (< x 0) - values) x))
This switched between doing (- x) and (values x) (identity that returns its argument) and as you can see it calls the result of an expression. Here is an example of copy-list using cps:
(define (copy-list lst)
(define (helper lst k)
(if (null? lst)
(k '())
(helper (cdr lst)
(lambda (res) (k (cons (car lst) res))))))
(helper lst values))
Notice that k is a variable that we pass a function and that it is called as a function. If we passed anything else than a fucntion there you would get the same error.
Is this unique to Scheme?
Not at all. All languages with one namespace that can pass functions as arguments will have similar challenges. Below is some JavaScript code with similar issues:
function double (f, v) {
return f(f(v));
}
double(v => v * v, 10); // ==> 10000
double(10, v => v * v);
; TypeError: f is not a function
; at double (repl:2:10)
// similar to having extra parentheses
function test (v) {
return v;
}
test(5)(6); // == TypeError: test(...) is not a function
// But it works if it's designed to return a function:
function test2 (v) {
return v2 => v2 + v;
}
test2(5)(6); // ==> 11
Just started to learn LISP and I'm trying to figure out how to write the following recursive function.
So should I have
(DOT-PRODUCT '(1 2) '(3 4)))
The output should be 11
I've written the following
(defun DOT-PRODUCT (a b)
(if (or (null a) (null b))
0
(+ (* (first a) (first b))
(DOT-PRODUCT (rest a) (rest b)))))
And everything seems to work; however, it still works with lists of different lengths. I want it to just work with lists of numbers that have the same length. Where should I add code that returns "invalid length" should we have such?
A simple way is to rewrite the function so that it checks different cases using the conditional form cond:
(defun dot-product (a b)
(cond ((null a) (if (null b) 0 (error "invalid length")))
((null b) (error "invalid length"))
(t (+ (* (first a) (first b))
(dot-product (rest a) (rest b))))))
In the first branch of the cond, if the first argument is NIL, the second one must be NIL as well, otherwise an error is generated. In the second branch, we already know that a is not NIL, so an error is immediately generated. Finally, the result is calculated.
Multiply corresponding elements of lists X and Y:
(mapcar #'* X Y)
Add elements of a list Z:
(reduce #'+ Z)
Put together: dot product:
(reduce #'+ (mapcar #'* X Y))
reduce and mapcar are the basis for the "MapReduce" concept, which is a generalization of that sort of thing that includes dot products, convolution integrals and a myriad ways of massaging and summarizing data.
One can increase efficiency by introducing an accumulator variable and turning the standard recursion into a tail recursion. In this example, I used (labels) to define the recursion:
(defun DOT-PRODUCT (a b)
(labels ((dp (x y accum)
(if (or (null x) (null y))
accum
(dp (rest x) (rest y) (+ accum (* (first x) (first y)))))))
(if (= (length a) (length b))
(dp a b 0)
(error "Invalid length."))))
I wrote a program below for "Define a procedure leet-speak takes a string and returns the result of changing all s's to fives, all e's to threes, all l's to ones, and all o's to zeros. Do not write any recursive code to do this. Simply make use of string->list, map, and list->string."
The error I got is:
~ (leet-speak "leet speak neat speak")
Exception: attempt to apply non-procedure (1 3 3 #\t #\space 5 ...)
Here is my definition for leet-speak:
(define leet-speak
(lambda (y)
(list->string
((map
(lambda (x)
(cond
[(eq? #\l x) 1]
[(eq? #\s x) 5]
[(eq? #\o x) 0]
[(eq? #\e x) 3]
[else x])
) (string->list y )))))
I really can't find out where the problem is.
You have too many parentheses around the map. Remove the extra so that there's only one parenthesis before map, and you should be good to go.
Your cond also needs to return the character corresponding to the number, not the number itself. Also, consider using a case instead of the cond you have.
All up, here's how it would look:
(define (leet-speak str)
(list->string
(map (lambda (x)
(case x
[(#\l) #\1]
[(#\s) #\5]
[(#\o) #\0]
[(#\e) #\3]
[else x]))
(string->list str))))