How do I work with nested list in LISP - nested

I am working on a homework assignment, and the first functions had me doing things like deleting a given element of a list, or displaying a given element of a list. The next functions want me to delete nested lists, or display them. Do you have any general tips for working with nested lists? I imagine the functions will be very similar to the ones I wrote before, just tweaked a bit.
Here are two example of functions I have written so far. Note I must use the "cond" style of writing functions.
(defun delnth(L A)
(cond ((= A 1) (rest L))
(t (cons (first L) (delnth (rest L) (- A 1))))))
(defun remv(A L)
(cond ((eq A (first L)) (remv A (rest L)))
((null L) nil)
(t (cons (first L) (remv A (rest L) )))))

Both of your functions work with nested cons. '(1 2 3) is (1 . (2 . (3 . ())) and (cons 1 (cons 2 (cons 3 '()))). A nested list would be that you also have nested cons in the car of cons. eg. ((1 . ()) . ()) ; ==> ((1)).
It's important to be able to see ((1) (2 3)) and understand that it is ((1 . ()) . ((2 . (3 . ())) . ())) so that if you want to access 3 it's obviously the path d,a,d,a and in the reverse you can construct the accessor cadadr.
cons with cons in the car part are trees. When you make a function that walks the tree you need to walk both the car and the cdr in the event they are cons. Thus:
;; generic function to walk trees and reduce
;; by combiner every value accessed by term
;; the default argument to combiner is tree-null
(defun accumulate-tree (tree term combiner null-value)
(labels ((rec (tree)
(cond ((null tree) null-value)
((atom tree) (funcall term tree))
(t (funcall combiner (rec (car tree))
(rec (cdr tree)))))))
(rec tree)))
(defun sum-numbers (tree)
(accumulate-tree tree
#'identity
#'+
0))
(defun count-numbers (tree)
(accumulate-tree tree
(lambda (v) (if (numberp v) 1 0))
#'+
0))
(sum-numbers '((1) (2 3) (((4)) 5))) ; ==> 15
(count-numbers '(a b 4 3 (e f 5) . 9)) ; ==> 4
The combiner doesn't need to reduce to an atom:
(defun reverse-tree (tree)
(accumulate-tree tree
#'identity
(lambda (a d) (cons d a))
'()))
(reverse-tree '((1 2) (3 4)))
; ==> ((nil (nil . 4) . 3) (nil . 2) . 1)

Related

How to reference list from input file

There are lots of manual how to make an input in scheme, but I do not understand how to work with it.
Lets say we have simple txt file as an input
a.txt:
1 2 3
I am calling standard io procedure on it
(let ((p (open-input-file "a.txt")))
(let f ((x (read p))) ; reading from file
(if (eof-object? x) ; check for eof
(begin
(close-input-port p)
'()
)
(cons x (f (read p))))))
output:
'(1 2 3)
Which is something I am looking for, but if I want to make standard pair/list manipulations on it I do not get what I expect:
(let ((p (open-input-file "a.txt")))
(let f ((x (read p))) ; reading from file
(if (eof-object? x) ; check for eof
(begin
(close-input-port p)
'()
)
(cdr
(cons x (f (read p)))))))
output:
'()
How do I get a hold of rest of the list?
Notice that the list you want to manipulate is constructed by the (let ...) expression, ie:
(let ((p ...)) ...) ;; => '(1 2 3)
So, to get the "rest" of the list, you have to apply cdr to the entire let expression, ie:
(cdr (let ((p ...)) ...)) ;; => '(2 3)
There is a difference to applying cdr outside the let expression as opposed to within. When you apply it outside, the let expression first gets evaluated to a list, which cdr then manipulates to get its "rest" values. This is equivalent to writing:
(cdr '(1 2 3)) ;; => '(2 3)
But if you apply it the way you have within its body, then at every recursive call for f, which is where a single cons cell is appended recursively to the list-so-far, you end up chaining a cdr to it, so instead of constructing a chain of cons as follows:
(cons 1 (cons 2 (cons 3 '()))) ;; => '(1 2 3)
you instead construct a chain of the form:
(cdr (cons 1 (cdr (cons 2 (cdr (cons 3 '())))))) ;; => '()
To see how this happens, it is a good idea to either think mentally about, or write down, the execution flow of your program. This enables you to understand what your expressions would evaluate to.
For example, your first let expression can be rewritten to an equivalent function as follows:
(define p (open-input-file "a.txt"))
;; (let f (...) ...) is a named let,
;; and is equivalent to the function below.
(define (f x)
(if (eof-object? x)
'()
(cons x (f (read p)))))
(f (read p))
(close-input-port p)
and its execution flow would look somewhat as follows:
(f (read p))
=> (f 1)
=> (cons 1 (f (read p)))
=> (cons 1 (f 2))
=> (cons 1 (cons 2 (f (read p))))
=> (cons 1 (cons 2 (f 3)))
=> (cons 1 (cons 2 (cons 3 (f (read p)))))
=> (cons 1 (cons 2 (cons 3 (f eof))))
=> (cons 1 (cons 2 (cons 3 '()))) ;; => '(1 2 3)
but if you apply cdr to your recursive call as follows:
(define (f x)
(if (eof-object? x)
'()
(cdr (cons x (f (read p))))))
then the execution would change to the following:
(f (read p))
=> (f 1)
=> (cdr (cons 1 (f (read p))))
=> (cdr (cons 1 (f 2)))
=> (cdr (cons 1 (cdr (cons 2 (f (read p))))))
=> (cdr (cons 1 (cdr (cons 2 (f 3)))))
=> (cdr (cons 1 (cdr (cons 2 (cdr (cons 3 (f (read p))))))))
=> (cdr (cons 1 (cdr (cons 2 (cdr (cons 3 (f eof)))))))
=> (cdr (cons 1 (cdr (cons 2 (cdr (cons 3 '()))))))
=> (cdr (cons 1 (cdr (cons 2 '()))))
=> (cdr (cons 1 '()))
=> '()

Displaying intermediate terms in a β-reductor

Consider the following β-reductor:
(define (normalize v)
(set! count 0)
(set! reflected '())
(reify v))
(define (reify v)
(if (memq v reflected)
(v cancel)
(let ((x (gensym)))
(ABS x (reify (v (reflect x)))))))
(define (reflect e)
(let ((f (lambda (v)
(if (eq? v cancel)
e
(reflect (APP e (reify v)))))))
(set! reflected (cons f reflected))
f))
(define (APP e1 e2) `(,e1 ,e2))
(define (ABS x e) `(lambda (,x) ,e))
(define reflected '())
(define count 0)
(define cancel '(cancel))
(define (gensym)
(set! count (+ 1 count))
(string->symbol (string-append "x" (number->string count))))
I would like to analyze its β-reduction order. However, since I'm not too savvy with Scheme, I would like to see the intermediate terms (right now it only prints the end result) it calculates as pure lambda expressions. I know how to display a line, but I am unable to squeeze a (display term) (newline) in the right spot.
Below are two simple terms that can be used to verify a solution - Church one (λfx.f x) and succ (λnfx.f (n f x)) (I hope I wrote them correctly in Scheme):
(define One
(lambda (f) (lambda (x) (f x))))
(define succ
(lambda (n) (lambda (f) (lambda (x) (f ((n f) x))))))
(normalize (succ One))
Is it possible to display the intermediate terms calculated by this reductor?
No, This is a big-step NBE algorithm (meaning "all at once"). it works by reflecting your term language into the host languages to piggy back on the hosts execution engine.

How to search a trinary tree?

I just started learning scheme. I'm trying to make a procedure to look for an item in a trinary tree. It returns true if it is found.
Here is what I got so far:
(define nullnode '())
(define leaf (lambda (x) (eqv? '() x) nullnode (list x nullnode nullnode nullnode)))
(define tritree (list 9 (leaf 1) (leaf 2) (leaf 3)))
; (display tritree) => (9 (1 () () ()) (2 () () ()) (3 () () ()))
(define lookup
(lambda (tr x)
(or (eqv? x (car tr))
(and (list? (cdr tr)) (lookup (cadr tr) x)))))
I want to get out of (leaf 1) and go through (leaf 2). How can I do that?
Is there a better way to define my lookup?
This is a straightforward implementation of how to search in a tree, it's just that this time we have three possible subtrees:
(define lookup
(lambda (tr x)
(cond ((null? tr) #f)
((equal? (first tr) x) #t) ; don't use eqv?, equal? is more general
(else
(or (lookup (second tr) x)
(lookup (third tr) x)
(lookup (fourth tr) x))))))
Alternatively, without using cond (and a bit closer to what you had in mind):
(define lookup
(lambda (tr x)
(and (not (null? tr))
(or (equal? (first tr) x)
(lookup (second tr) x)
(lookup (third tr) x)
(lookup (fourth tr) x)))))
And do notice that your implementation of leaf is incorrect, for the above to work you'll have to fix it first:
(define leaf
(lambda (x)
(if (null? x)
nullnode
(list x nullnode nullnode nullnode))))
It works as expected with the sample input:
(lookup tritree 3)
=> #t
(lookup tritree 5)
=> #f

I want to know what is wrong in my function please

I want to get all sublists that start with a number. So I did
(defun function (list)
(cond
((atom list) nil)
((and (numberq (car list)) (consp (car list)))
(cons (function (car list)) (number (cdr list))) )
((not (and (numberq (car list)) (consp (car list)))) (function (cdr list))) ) )
(function '((3 f g h) l s (v k) (2 m n) (9 d) c))
It returns nil instead of ((3 f g h) (2 m n) (9 d)).
Thank you for your help!
I guess this is roughly what you were trying to do:
(defun f (lst)
(when lst
(let ((e (car lst)))
(if (and (consp e) (numberp (car e)))
(cons e (f (cdr lst)))
(f (cdr lst))))))
Alternatively, you can use remove-if-not:
(defun f (lst)
(remove-if-not
(lambda (e) (and (consp e) (numberp (car e))))
lst))
In both cases, it works as expected:
? (f '((3 f g h) l s (v k) (2 m n) (9 d) c))
((3 F G H) (2 M N) (9 D))

A 'cons' in Haskell that displays like its Scheme counterpart

As an exercise, I am implementing in Haskell a 'cons' operation that forms a pair from two values of any type. Implementing the needed data type is easy enough:
data Nil = Nil deriving (Eq)
data Pair a b = Cons a b deriving (Eq)
car (Cons x _) = x
cdr (Cons _ y) = y
caar = car . car
cdar = cdr . car
cadr = car . cdr
cddr = cdr . cdr
*Main> cddr (Cons 55 (Cons (1,2,3,4) "hello, world!"))
"hello, world!"
*Main>
but inspired by this thread, I want to make the resulting pairs print out like Scheme lists would - including the infamous "improper list" (1 2 3 . 4). My implementation (see below) is working for Char's:
*Main> Cons 'a' (Cons 'b' (Cons 'c' Nil))
('a' 'b' 'c')
*Main> Cons 'a' (Cons 'b' 'c')
('a' 'b' . 'c')
*Main> Cons (Cons 'a' 'b')(Cons 'c' (Cons 'd' Nil))
(('a' . 'b') 'c' 'd')
It's not working so well for Int's (or any other data type). So my question is: how can I make this work for other data types? i.e., I want it to work like this:
*Main> Cons 5 (Cons "hello" (Cons False Nil))
(5 "hello" False)
My current full implementation follows:
data Nil = Nil deriving (Eq)
data Pair a b = Cons a b deriving (Eq)
car (Cons x _) = x
cdr (Cons _ y) = y
caar = car . car
cdar = cdr . car
cadr = car . cdr
cddr = cdr . cdr
instance Show Nil where show _ = "()"
class ShowPair a where
showRight::a->String
instance (Show a, ShowPair a, ShowPair b)=>Show (Pair a b) where
show (Cons car cdr) = "(" ++ (show car) ++ (showRight cdr) ++ ")"
instance (Show a, ShowPair a, ShowPair b)=>ShowPair (Pair a b) where
showRight (Cons car cdr) = " " ++ (show car) ++ (showRight cdr)
instance ShowPair Char where
showRight x = " . " ++ show x
instance ShowPair Int where
showRight x = " . " ++ show x
instance ShowPair Nil where
showRight _ = ""
Here's an option. First, enable these extensions by putting this line at the top of your file:
{-# LANGUAGE FlexibleInstances, OverlappingInstances, UndecidableInstances#-}
Next, remove your ShowPair instances for Char and Int.
Now add a ShowPair instance for anything with Show:
instance Show a => ShowPair a where showRight = (" . " ++) . show
This now ensures that any type a which is an instance of Show is also an instance of ShowPair where it is shown by prepending a . to its normal string form. However, if a type has a more specific ShowPair instance (e.g. Nil), Haskell will use that one instead.
This is not part of standard Haskell, so you need to enable the three language extensions. Look at How to write an instance for all types in another type class? for more information on why you need the extensions.
Ben in the comments to the question mentions the native pair type, which I'm going to use in this answer. I'm also going to substitute your Nil with the Haskell unit type ().
This is a bit outside what you're asking, but I think it's worth saying. It is difficult in Haskell to capture the notion of a "list" in Scheme unless you "cheat" and use an extension like Data.Dynamic. This is because from the point of view of "pure," unextended Haskell, it is difficult if not impossible to assign all Scheme lists the same type. This means that while Scheme allows you to write functions that take any list, proper or improper, you're going to have a hard time doing the same in Haskell (and for good reason; improper "lists" should probably not exist anyway).
So for example, you've basically chosen to use (a, b) as the type of Scheme-like pairs. Now suppose we have these Scheme lists:
(define zero '())
(define one '(1))
(define two '(1 2))
(define three '(1 2 3))
(define four '(1 2 3 4))
Here's a simple translation in terms of Haskell pairs, which corresponds to the way you're doing it:
zero :: ()
zero = ()
one :: (Integer, ())
one = (1, ())
two :: (Integer, (Integer, ()))
two = (1, (2, ()))
three :: (Integer, (Integer, (Integer, ())))
three = (1, (2, (3, ())))
four :: (Integer, (Integer, (Integer, (Integer, ()))))
four = (1, (2, (3, (4, ()))))
The key thing is that in Scheme you can easily write a function that ranges over all lists:
(define (reverse list)
(foldl cons '() list))
(define (filter pred? list)
(foldr (lambda (elem rest)
(if (pred? elem)
(cons elem rest)
rest))
'()
list))
(define (foldl fn init list)
(if (null? list)
init
(foldl fn (fn (car list) init) (cdr list))))
(define (foldr fn init list)
(if (null? list)
init
(fn (car list)
(foldr fn init (cdr list)))))
In this Haskell translation, you cannot do that easily at all, because "lists" of different lengths have different types. And it gets worse when you consider the difference between reverse (which takes a list of length n and produces a list of length n) and filter (which takes a list of length n and produces a list of length m ≤ n such that m can only be known at runtime).

Resources