I can't for the life of me find out why this code produces the error.
Here's the error:
let*: bad syntax (missing body) in: (let* ((tempp2 (p2) (letrec ((mloop (p1 p2) (if (= (length p1) 0)) (else if ((= (length p2) 0) ((set! p2 (pn)) (multiloop (cdr p1) (p2)))) (else (let* ((prod (append (prod) (cons (* (coeff (car p1)) (coeff (car p2))) (+ (expon (car p1)) (expon (car p2)))))))) (set! p2 (cdr p2)) (mloop (p1 p2)) (simplify (sort newone))))))))))
Here's the code:
(define multiplyPoly (lambda (p1 p2)
(
(let* ((hardp2 (p2)
(letrec
((mloop (p1 p2)
(if (= (length p1) 0))
(else if ((=(length p2) 0) ((set! p2 (hardp2)) (multiloop (cdr p1) (p2))))
(else
(let* ([prod (append (prod) (cons(*(coeff(car p1)) (coeff(car p2))) (+(expon(car p1)) (expon(car p2)))))]))
(set! p2 (cdr p2))
(mloop (p1 p2))
(simplify (sort newone)))))))))))))
You have lots of syntax errors in your code. I urge you to install a IDE that does matching of parentheses and ident your code properly, like DrRacket. DrRacket supports both R5RS and R6RS so you can still program in Scheme with DrRacket.
Usually a let, let* and letrec has the following form:
(let ((var expression) ...)
body)
In a letrec or letrec* the expression looks like (lambda (arg ...) expression).
If you take any Scheme expression like (if (positive? x) - +) and surround them with an extra pair of parenthesis you are calling the result as a procecdure: ((if (positive? -1) - +)) ; ==> 0
An if works like this:
(if predicate-expression
consequent-expression
alternative-expression)
If you need to nest you need to have the nested if as alternative expression.
(if predicate-expression
consequent-expression
(if predicate-expression2
consequent-expression2
alternative-expression))
If you nest there cond might be a better match. The expression above might be written:
(cond (predicate-expression consequent-expression)
(predicate-expression2 consequent-expression)
(else alternative-expression))
else has special meaning in a cond so it's not something that works on its own.
Related
I've read here that named let can be rewritten with letrec.
And so I proceeded to rewrite the following function with letrec:
(define (duplicate pos lst)
(let dup ([i 0] [lst lst])
(cond
[(= i pos) (cons (car lst) lst)]
[else (cons (car lst) (dup (+ i 1) (cdr lst)))])))
My attempt at this:
(define (duplicate pos lst)
(letrec ((dup (lambda ([i 0] [lst lst])
(cond
[(= i pos) (cons (car lst) lst)]
[else (cons (car lst) (dup (+ i 1) (cdr lst)))]))))))
Sadly, when I call it with (duplicate 1 (list "apple" "cheese burger!" "banana")) I get from Racket letrec: bad syntax (missing body). How might I rewrite duplicate with letrec?
As you can see in the documentation for letrec, it has these arguments:
(letrec ([id val-expr] ...) body ...+)
So, you have to add at least one body form after definitions.
I also replaced cond with if (you have only two branches of code), (+ ... 1) with add1 and improved indentation:
#lang racket
(define (duplicate pos lst)
(letrec ((dup (lambda ([i 0] [lst lst])
(if (= i pos)
(cons (car lst)
lst)
(cons (car lst)
(dup (add1 i) (cdr lst)))))))
(dup)))
Test:
> (duplicate 1 (list "apple" "cheese burger!" "banana"))
'("apple" "cheese burger!" "cheese burger!" "banana")
The named let is (more or less) a locally defined regular procedure that is called "behind the scenes".
The body of a named let is not the body of the equivalent "unnamed" let, but the body of that procedure;
(let f ([x init])
body)
can be rewritten as
(letrec ([f (lambda ([x init]) body)])
(f))
or, without using default arguments (which some would find clearer),
(letrec ([f (lambda (x) body)])
(f init))
In "The Scheme Programming Language 4th Edition" section 3.3 Continuations the following example is given:
(define product
(lambda (ls)
(call/cc
(lambda (break)
(let f ([ls ls])
(cond
[(null? ls) 1]
[(= (car ls) 0) (break 0)]
[else (* (car ls) (f (cdr ls)))]))))))
I can confirm it works in chezscheme as written:
> (product '(1 2 3 4 5))
120
What is 'f' in the above let? Why is the given ls being assigned to itself? It doesn't seem to match what I understand about (let ...) as described in 4.4 local binding:
syntax: (let ((var expr) ...) body1 body2 ...)
If 'f' is being defined here I would expect it inside parenthesis/square brackets:
(let ([f some-value]) ...)
This is 'named let', and it's a syntactic convenience.
(let f ([x y] ...)
...
(f ...)
...)
is more-or-less equivalent to
(letrec ([f (λ (x ...)
...
(f ...)
...)])
(f y ...))
or, in suitable contexts, to a local define followed by a call:
(define (outer ...)
(let inner ([x y] ...)
...
(inner ...)
...))
is more-or-less equivalent to
(define (outer ...)
(define (inner x ...)
...
(inner ...)
...)
(inner y ...))
The nice thing about named let is that it puts the definition and the initial call of the local function in the same place.
Cavemen like me who use CL sometimes use macros like binding, below, to implement this (note this is not production code: all its error messages are obscure jokes):
(defmacro binding (name/bindings &body bindings/decls/forms)
;; let / named let
(typecase name/bindings
(list
`(let ,name/bindings ,#bindings/decls/forms))
(symbol
(unless (not (null bindings/decls/forms))
(error "a syntax"))
(destructuring-bind (bindings . decls/forms) bindings/decls/forms
(unless (listp bindings)
(error "another syntax"))
(unless (listp decls/forms)
(error "yet another syntax"))
(multiple-value-bind (args inits)
(loop for binding in bindings
do (unless (and (listp binding)
(= (length binding) 2)
(symbolp (first binding)))
(error "a more subtle syntax"))
collect (first binding) into args
collect (second binding) into inits
finally (return (values args inits)))
`(labels ((,name/bindings ,args
,#decls/forms))
(,name/bindings ,#inits)))))
(t
(error "yet a different syntax"))))
f is bound to a procedure that has the body of let as a body and ls as a parameter.
http://www.r6rs.org/final/html/r6rs/r6rs-Z-H-14.html#node_sec_11.16
Think of this procedure:
(define (sum lst)
(define (helper lst acc)
(if (null? lst)
acc
(helper (cdr lst)
(+ (car lst) acc))))
(helper lst 0))
(sum '(1 2 3)) ; ==> 6
We can use named let instead of defining a local procedure and then use it like this:
(define (sum lst-arg)
(let helper ((lst lst-arg) (acc 0))
(if (null? lst)
acc
(helper (cdr lst)
(+ (car lst) acc)))))
Those are the exact same code with the exception of some duplicate naming situations. lst-arg can have the same name lst and it is never the same as lst inside the let.
Named let is easy to grasp. call/ccusually takes some maturing. I didn't get call/cc before I started creating my own implementations.
Currently working on a lexical analyzer in Scheme. I'm new to scheme but have a general understanding of what to do. I am following a online tutorial, however I keep getting this error because I'm not using UMASS scheme. What can I do to replace this class (Error: record-parse unbound identifier). Below is my code
#lang racket
(define record_parse
(lambda(noun adjective adverb conjunction prep terminator)
((noun) '(dog cat rat house tree))
((adjective) '(furry fast lazy sneaky))
((adverb) '(quickly silently))
((conjunction) '(and or))
((prep) '(with around up))
((terminator) '(!))))
(define noun '(dog cat rat house tree))
(define adjective '(furry fast lazy sneaky))
(define adverb '(quickly silently))
(define conjunction '(and or))
(define prep '(with around up))
(define terminator '(!))
(define class_parse (record-parse 'parse '(full full)))
(define cons_parse (car class_parse))
(define sel_parse (caddr class_parse))
(define tree_parse (car sel_parse))
(define rest_parse (cadr sel_parse))
(define parse_article
(lambda (list_of_tokens)
(cond
((null? list_of_tokens) #f)
((member? (car list_of_tokens) '(a the))
(cons_parse
(car list_of_tokens)
(cdr list_of_tokens)))
(else #f )
)
)
)
(define (member? x list)
(if (null? list) #f
(if (equal? x (car list)) #t
(member? x (cdr list)))))
(define parse_noun
(lambda (list_of_tokens)
(cond
((null? list_of_tokens) #f)
((member? (car list_of_tokens) noun)
(cons_parse
(car list_of_tokens)
(cdr list_of_tokens)))
(else #f )
)
)
)
(define parse_noun_phrase
(lambda (list_of_tokens)
(let ((p_det (parse_article list_of_tokens)))
(if p_det
(let ( (p_n (parse_noun (rest_parse p_det))))
(if p_n
(cons_parse
(list 'noun_phrase
(tree_parse p_det)
(tree_parse p_n))
(rest_parse p_n)
)
#f)
)
#f)
)
))
(define verb '(loves hates eats chases stalks))
(define parse_verb
(lambda (list_of_tokens)
(cond
((null? list_of_tokens) #f)
((member? (car list_of_tokens) verb)
(cons_parse
(car list_of_tokens)
(cdr list_of_tokens)))
(else #f )
)
)
)
(define parse_verb_phrase
(lambda (list_of_tokens)
(let ((p1 (parse_verb list_of_tokens)))
(if p1
(let ((p2 (parse_noun_phrase (rest_parse p1))))
(if p2
(cons_parse
(list 'verb_phrase
(tree_parse p1)
(tree_parse p2))
(rest_parse p2)
)
#f)
)
#f)
)
))
(define parse_sentence
(lambda (list_of_tokens)
(let ((p1 (parse_noun_phrase list_of_tokens)))
(if p1
(let ((p2 (parse_verb_phrase (rest_parse p1))))
(if p2
(cons_parse
(list 'sentence
(tree_parse p1)
(tree_parse p2))
(rest_parse p2)
)
#f)
)
#f)
)
))
;example of parsing a sentence
;(example
; '(parse_sentence '(the dog chases the cat))
; (cons_parse
; '(sentence (noun_phrase the dog)
; (verb_phrase chases
; (noun_phrase the cat)
; (terminator)))
; '()
; )
; )
(begin
(display "Enter a Sentance in (): ")
(let ((input (read)))
(parse_article (parse_sentence input))))
I am getting the error with the (define class_parse (record-parse 'parse '(full full)))
The procedure you defined is called record_parse, but you're trying to invoke it as record-parse. After that typo is fixed, you'll get a different error: record_parse is defined to receive 6 parameters, but you're passing only two: 'parse and '(full full). And the body of record_parse doesn't make sense, it seems that you tried to implement a case expression, but that's not how it's written in Scheme - at all.
That's only for starters, it looks like there are more errors. You should test each procedure individually until you get the hang of the syntax and before writing more complex behavior that involves using all of the procedures.
I try to write function which add some number to every element in the list and then makes sum of all this terms.
(define (num-to-sumtup num)
(lambda (tup)
(cond
((null? tup) 0)
(else (+ (car tup) num (num-to-sumtup ())) ;; here I need to get reference on the inner function
is it possible?
You don't need to make it a anonymous procedure. It may have a name in the scope of num-to-sumtup. Here are some examples of ways to do it. The simples way to do this would be to use the rec syntax which is defined in the SRFI-31.
#!r6rs
(import (rnrs base)
(srfi :31))
(define (num-to-sumtup num)
(rec (recur tup)
(cond
((null? tup) 0)
(else (+ (car tup) num (recur (cdr tup)))))))
((num-to-sumtup 10) '(1 2 3 4 5)) ; ==> 65
You can also do this with define:
(define (num-to-sumtup num)
(define (sum-list tup)
(cond
((null? tup) 0)
(else (+ (car tup) num (sum-list (cdr tup))))))
sum-list); we return the locally named procedure
Using higher order procedures and cut from SRFI-26.
#!r6rs
(import (rnrs base)
(rnrs lists) ; fold-left
(srfi :26)) ; cut
(define (num-to-sumtup num)
(lambda (tup)
(fold-left (cut + <> <> num) 0 tup)))
Yes, it is possible. num-to-sumtup Takes a number as argument, and returns a function, that takes a list. So you execute it to get the function, and then execute that function.
(define (num-to-sumtup num)
(lambda (tup)
(cond
((null? tup) 0)
(else
(+ (car tup) num ((num-to-sumtup num) (cdr tup)))))))
;Value: num-to-sumtup
((num-to-sumtup 10) '(1 2 3 4 5))
;Value: 65
In the spirit of sylwester's answer here's another option
(define (num-to-sup num)
(lambda (tup)
(foldl (lambda (x y) (+ num x y)) 0 tup)))
i need to create this procedures: my-cons, my-car, my-cdr in Scheme.
It should work like this:
(define p1 (my-cons 3 8))
(p1 #t)
3
(p1 #f)
8
(my-car p1)
3
(my-cdr p1)
8
now, I have only this:
(define my-cons
(lambda (x y)
(cons x y)
(let ((a (car (cons x y))))
(lambda (a)
(if (equal? a #f) y x)))))
but in this code i can't apply my-cons or my-cdr on defined p1
Can someone help me with this?
First, there's some extraneous code in my-cons which doesn't seem to belong here. This is enough:
(define my-cons
(lambda (x y)
(lambda (a)
(if a x y))))
(Also, you don't need to compare a boolean value with #t or #f — it's usable in if as it is.)
Now you have my-cons that returns a function which returns either x or y depending on its arugment. You can use that when implementing my-car and my-cdr:
(define my-car
(lambda (c)
(c #t)))
(define my-cdr
(lambda (c)
(c #f)))