Racket Programming - my map - if-statement

How would you replace the cond to an if else in this program?
#lang racket
(define (my-map f lst)
(cond
[(empty? lst) empty]
[else (cons (f (first lst))
(my-map f (rest lst)))]))

A cond expression with just one condition and a single expression as the consequent and an else part with a single expression as the alternative can be easily transformed into an if expression. For example, this:
(cond (<cond1> <exp1>)
(else <exp2>))
Is equivalent to this:
(if <cond1> ; condition
<exp1> ; consequent
<exp2>) ; alternative
In particular, your code can be rewritten as:
(define (my-map f lst)
(if (empty? lst)
empty
(cons (f (first lst))
(my-map f (rest lst)))))
Also notice that a cond is just a shorter way to express a series of nested if expressions. Think of it as a shorthand for IF-ELSE IF-ELSE IF-ELSE in other programming languages. In fact, for the general case many interpreters implement this:
(cond (<cond1> <exp1> <exp2>) ; we can have any number of conditions
(<cond2> <exp3> <exp4>) ; and any number of expressions after condition
(else <exp5> <exp 6>))
... As a syntactical transformation that (ignoring the => syntax) gets expanded into:
(if <cond1>
(begin
<exp1>
<exp2>)
(if <cond2>
(begin
<exp3>
<exp4>)
(begin ; the last expression is the `else` part
<exp5>
<exp6>)))
Notice that the expressions after each condition are inside a begin form, meaning that in a cond they're implicitly inside a begin - so you can write more than one! whereas in an if expression only a single expression can go in either the consequent or the alternative, and if more than one is needed a begin must be used. As always, refer to the documentation for more details.

Every cond:
(cond (predicate consequent)
(predicate2 consequent2-1 consequent2-2)
(else alternative))
Can be rewritten:
(if predicate
consequent
(if predicate2
(begin
consequent2-1
consequent2-2)
alternative))
Your example becomes particularly simple because there is not more than 2 clauses and the code does not make use of explicit begin.

Racket isn't really Scheme as, for example, Racket requires a different if syntax than Scheme. But, figuring that you are, in fact, learning Scheme you might check out the Scheme R7RS Specification; it provides a definition of cond in terms of if. Here is a definition that I've simplified for you by axing templates involving '=>':
(define-syntax cond
(syntax-rules (else)
((cond (else result1 result2 ...))
(begin result1 result2 ...))
((cond (test)) test)
((cond (test) clause1 clause2 ...)
(let ((temp test))
(if temp temp
(cond clause1 clause2 ...))))
((cond (test result1 result2 ...))
(if test (begin result1 result2 ...)))
((cond (test result1 result2 ...)
clause1 clause2 ...)
(if test
(begin result1 result2 ...)
(cond clause1 clause2 ...)))))
Beautiful, yes?

Related

first: contract violation error in racket/scheme for printing out a combination of list procedures

I was writing a procedure that takes 2 expressions, and if there is a way for exp1 to be created through exp2 (when we replace exp2 with 'sss) using first, rest, cons, it then returns the code needed to produce exp1.
For example, this is what I would want to produce.
(find-in '(e r t) '(e t) ) => '(cons (first sss) (rest (rest sss)))
My code works for a lot of the test cases but when I ran through
(find-in '(a '(((v)) l) (f g)) '( (v g) l a))
It returns this error:
first: contract violation
expected: (and/c list? (not/c empty?))
given: 'g
The same error shows up when I try running this test case:
(find-in '(x a (x y)) '(z a (b)))
;supposed to return #f
This is my code so far:
(define find-in
(lambda (exp2 exp1)
(cond
((equal? exp2 exp1) 'sss)
((null? exp2) #f)
((not (list? exp2)) #f)
((find-in (first exp2) exp1) (repl 'sss '(first sss) (find-in (first exp2) exp1)))
((find-in (rest exp2) exp1) (repl 'sss '(rest sss) (find-in (rest exp2) exp1)))
(else (list? exp1)
(if
(and (find-in exp2 (first exp1)) (find-in exp2 (rest exp1)))
(list 'cons (find-in exp2 (first exp1)) (find-in exp2 (rest exp1)))
#f) #f))))
I am confused as to which condition I missed when I coded or if there was a logic error. What could have gone wrong?
Your last clause doesn't look right to me. When you use the special else token for your last clause, you are saying "There's nothing to test here, execute the body of this unconditionally if you've made it this far". Thus, your next expression, (list? exp1), is not a test as far as cond is concerned: it is evaluated for side effects, and the results discarded. Then the next expression is also evaluated, whether exp1 was a list or not.
If you want to make this conditional on whether exp1 is a list, you should remove the excess else at the beginning (and probably add an else clause to the end to return #f if none of your cases matched).

Recursion in Common Lisp

I am trying to use recursion in a Common Lisp project to check if a regular expression follows specific "rules". Here is precisely what I need to achieve:
I can have different types of regular expressions (RE), the basic one is just an atom (e.g. 'a), then we can have more complex expressions represented as follows (e.g '(star (seq a b)):
[re1][re2]…[rek] becomes (seq [re1] [re2] … [rek])
[re1]|[re2]…[rek] becomes (or [re1] [re2] … [rek])
[re]* becomes (star [re])
[re]+ becomes (plus [re])
The alphabet of the symbols is composed of Lisp S-exps.
I want to implement this function in COMMON LISP:
(is-regular-xp RE) returns TRUE when RE is a regular expression; false (NIL) in any other case.
This is what I have already written, it works in every case, EXCEPT when I check a RE that starts with an accepted atom, but then contains a not accepted one. For example: if you try to check (is-regexp '(seq a b)) LispWorks returns TRUE. Which is correct! But if you try (is-regexp '(seq (crazytest a b))) it returns, again TRUE, which is wrong! In this case "crazytest" doesn't exist in my grammar and the console should return NIL.
(defun is-regexp (RE)
;;Enters this check only if RE is a list
(if (listp RE)
(if (atom (car RE))
;;Verifies that the first element of the list is accepted
(cond ((eql (car RE) 'seq) T)
((eql (car RE) 'or) T)
((eql (car RE) 'star) T)
((eql (car RE) 'plus) T)))
;;Enters this check only if RE is not a list
(if (not(listp RE))
(if (atom 'RE) T)
)
)
)
The problem that I want to resolve is the recursive check of the inner regular expressions, I tried to put a recursive call to "is-regexp" using "cdr" to analyze only the rest of the list, but it still doesn't work...
Thank you in advance for your precious help!
Try this:
CL-USER> (defun is-regexp (RE)
(cond ((null RE) nil)
((atom RE) t)
((consp RE)
(and (member (car RE) '(seq or star plus))
(every #'is-regexp (cdr RE))))
(t nil)))
IS-REGEXP
CL-USER> (is-regexp 'a)
T
CL-USER> (is-regexp '(star (seq a b)))
T
CL-USER> (is-regexp '(seq (crazytest a b)))
NIL
Note that this function does not check for the length of the list of the operators as it should. This is left as exercise to you.
This sort of problem is quite a natural fit for CLOS, if you have the right mindset. Using CLOS also has the advantage that it's probably not something people can submit as homework.
This code doesn't do quite what you want (it assumes that the basic regexps are only symbols), but could be changed to do so.
(defgeneric valid-regexp-p (r)
;; Is something a valid regular expression?
(:method ((r t))
nil))
(defmethod valid-regexp-p ((r symbol))
t)
(defmethod valid-regexp-p ((r cons))
(valid-operator-regexp-p (first r) (rest r)))
(defgeneric proper-list-p (l)
(:method ((l t))
nil)
(:method ((l null))
t)
(:method ((l cons))
(proper-list-p (rest l))))
(defgeneric valid-operator-regexp-p (op body)
(:method :around (op body)
(and (proper-list-p body)
(call-next-method)
(every #'valid-regexp-p body)))
(:method (op body)
nil))
(defmethod valid-operator-regexp-p ((op (eql 'seq)) body)
t)
(defmethod valid-operator-regexp-p ((op (eql 'or)) body)
t)
(defmethod valid-operator-regexp-p ((op (eql 'star)) body)
(= (length body) 1))
(defmethod valid-operator-regexp-p ((op (eql '+)) body)
(= (length body) 1))
I don't think that, in real life, I'd write proper-list-p like that, but it's quite cool I think.

How to transform a list into a set in LISP?

I have been trying to transform a linear list into a set but with no avail. Everytime I run this, I get some weird compilation errors like "badly formed lambda" which points to the way I use append. Here is my code:
(defun mem(e l)
(cond
((null l) nil)
((equal e (car l)) t)
((listp (car l)) (mem e (car l)))
(t(mem e (cdr l)))
)
)
(defun st(l k)
(cond
((null l) nil)
(( mem '(car l) 'k) (st (cdr l) k))
((listp (car l)) (st (car l) k))
( t (st (cdr l) (append((car l) k)) ))
(t(mem e (cdr l)))
)
)
EDIT: frankly I just want to remove the duplicates from list l
Prefer Standard Library Functions
EDIT: frankly I just want to remove the duplicates from list l
Common Lisp has a remove-duplicates function. The documentation inclues examples:
Examples:
(remove-duplicates "aBcDAbCd" :test #'char-equal :from-end t) => "aBcD"
(remove-duplicates '(a b c b d d e)) => (A C B D E)
(remove-duplicates '(a b c b d d e) :from-end t) => (A B C D E)
(remove-duplicates '((foo #\a) (bar #\%) (baz #\A))
:test #'char-equal :key #'cadr) => ((BAR #\%) (BAZ #\A))
(remove-duplicates '((foo #\a) (bar #\%) (baz #\A))
:test #'char-equal :key #'cadr :from-end t) => ((FOO #\a) (BAR #\%))
Are you trying to flatten the list too?
From your code for mem, where you do:
((listp (car l)) (mem e (car l)))
it looks like you want your member function to also recurse into sublists. That's a bit questionable, even when working with sets, since sets can traditionally include other sets. E.g., {{3},{4},5} is a set containing 5, the set {3}, and the set {4}. It's not the same as the set {3,4,5}. Your st function also looks like it's trying to recurse into lists, which makes it seem like you want to flatten you lists, too. Again, that's a bit questionable, but if you want to do that, then your conversion to a set would be easier as a "flatten, then remove duplicates" process:
(defun flatten (list)
"Returns a fresh list containing the leaf elements of LIST."
(if (listp list)
(mapcan 'flatten list)
(list list)))
;; CL-USER> (flatten '(1 2 (3 4) 5 ((6))))
;; (1 2 3 4 5 6)
(defun to-set (list)
"Returns a set based on the elements of LIST. The result
is a flat list containing the leaf elements of LIST, but
with any duplicate elements removed."
(delete-duplicates (flatten list)))
;; CL-USER> (to-set '(1 3 (3 4) ((4) 5)))
;; (1 3 4 5)
Notes
I get some weird compilation errors like "badly formed lambda" which points to the way I use append.
Yes, you're trying to call append like: (append((car l) k)). That's actually not a problem for append. Remember, the syntax for a function call in Lisp is (function argument…). That means that you've got:
(append ((car l) k))
<function> <argument1>
But your argument1 is also a function call:
((car l) k )
<function> <argument1>
In Common Lisp, you can't use (car l) as a function. The only thing that can appear for a function is a symbol (e.g., car, append) or a lambda expression (e.g., (lambda (x) (+ x 1)).
You want to call (append (car l) k) instead.
First, CL does not have a set data type.
Lists, however, can be used as sets, you do not need to write any special code for that.
Second, I don't understand what your st function is supposed to do, but I bet that in the second cond clause you should not quote (car l) and k. You should use meaningful names for your functions and avoid abbreviations. As per your explanation in the comment, you should use pushnew instead.
Third, your mem function is quite weird, I am pretty sure you do not mean what you wrote: e is searched along a path in the tree l, not in the list l. As per your explanation in the comment, you should check both car and cdr:
(defun tree-member (tree element &key (test #'eql))
(if (consp tree)
(or (tree-member (car tree) element :test test)
(tree-member (cdr tree) element :test test))
(funcall test element tree)))

Turning list of atoms into a single list using recursion

I'm looking for an answer that turns a list of atoms into a single list recursively.
An example would be, (slist '(a (b c) (d e (f) g) h)) into (slist (a b c d e f g h))
Any answer will be helpful.
What you're trying to do is called flattening a list. Here are a bunch of options:
; required predicate
(define (atom? x)
(and (not (null? x))
(not (pair? x))))
; naïve version using append
(define (flatten1 lst)
(cond ((null? lst)
'())
((not (pair? lst))
(list lst))
(else
(append (flatten1 (car lst))
(flatten1 (cdr lst))))))
; naïve version using append, map, apply
(define (flatten2 lst)
(if (atom? lst)
(list lst)
(apply append (map flatten2 lst))))
; efficient version using fold-left
(define (flatten3 lst)
(define (loop lst acc)
(if (atom? lst)
(cons lst acc)
(foldl loop acc lst)))
(reverse (loop lst '())))
; very efficient version with no higher-order procedures
(define (flatten4 lst)
(let loop ((lst lst)
(acc '()))
(cond ((null? lst)
acc)
((not (pair? lst))
(cons lst acc))
(else
(loop (car lst) (loop (cdr lst) acc))))))
Any of the above will work as expected. For instance, using flatten4:
(flatten4 '(a (b c) (d e (f) g) h))
=> '(a b c d e f g h)
Depending on the interpreter you're using, it's quite possible that it already includes an implementation. For example, in Racket:
(flatten '(a (b c) (d e (f) g) h))
=> '(a b c d e f g h)
In Lisp, as opposed to Scheme, you have to accept the fact that the atom nil represents an empty list in your list structure. So, strictly speaking, when you flatten a list, you do not obtain all of the atoms from the tree structure; only those ones that do not represent empty lists and list terminators.
You also have to make a design decision: does your code handle improper lists and circular list? That is to say, what should these cases do:
(flatten '(a . b)) ;; (a b), accurate diagnostic or failure?
(flatten '#1=(a . #1#)) ;; (a), accurate diagnostic or failure?
Do you handle the situation and collect the actual non-list atoms that are present in the tree structure, regardless of cycles or improper termination? Or do you detect the situation accurately and report a meaningful diagnostic? Or just ignore the possibility and let the code blow up in lower level functions, or perform runaway recursion?
If you don't care about dealing with improper lists and circular structure, flattening a list is recursively defined like this.
A non-list is flattened by returning a list containing that atom.
A list is flattened by flattening all of its elements and catenating them.
In Lisp it's usually easier and clearer to write the code than the English spec or pseudo-code:
(defun flatten (obj)
"Simple flatten: no handling of improper lists or cycles"
(if (listp obj)
(mapcan #'flatten obj)
(list obj)))
Note that although mapcan is destructive, that doesn't present a problem here, because it only ever catenates list structure that is constructed within our function call and not any incoming list structure. Stated in other words, our output does not share structure with the input.
You've already checked a correct answer, but here is a trivial implementation which clearly indicates the recursion:
(define (slist list)
(if (null? list)
'()
(let ((next (car list))
(rest (cdr list)))
(if (list? next)
(append (slist next) (slist rest))
(cons next (slist rest))))))

Scheme storing the result of a function (Let)

(define [DML vara]
(cond
((atom? (car vara))
(cond
((eqan? (car vara) 'N)
(display (cdr vara)))
(else (negate vara)))
)))
I'm currently trying to save the content of a return right now for simplicity I was testing the negate function it "returns" a list and I wanted to save the result of that function to do testing. How do I actually save the list return from negate.
Kind of like (x = (negate vara)) where x is the list. I look up let on google and in stack over flow but I can't find a very simple basic assignment.
Excuse my poor syntax on scheme I'm just starting..and going from imperative language to function isn't so smooth..
edit:
I wanted to print out the result expression of (negate vara) but since scheme only prints out the last "recursive call" (pardon my bad wording). I wanted it to use the resulting list from (negate vara) but still print out that list like
say if I had
(else (test (negate vara)))
...
(define (test vara)
(display "test")
)
I wanted it to display
'(O a b)) ;list
here
As you already know, a let expression will do the trick:
(let ((x 10)
(y 20))
(+ x y))
=> 30
The above expression binds values to two variables, x and y. These bindings will exist inside the body of the let. Implicitly, all the expressions in the let form are packed inside a begin, and the end result of the whole expression is the final expression. Notice that one binding cannot refer to the others in the definition part; if one variable needs to refer to previous definitions, then use a let*:
(let* ((x 10)
(y (* x 2)))
(+ x y))
=> 30
Finally, if you need to create a recursive definition use letrec:
(letrec ((fact (lambda (x)
(if (zero? x) 1 (* x (fact (sub1 x)))))))
(fact 10))
=> 3628800
You could make a procedure like you proposed:
(define (test var)
(display var)
var)
(test (negate (test vara)))) ; prints our argument and return
Or you could use DrRacket and use the debugger. You'll miss it after using it once!