Scheme storing the result of a function (Let) - list

(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!

Related

Racket, applying list of functions: abstract list functions

I want to create a function using abstract list functions that will apply a list of functions onto each other, without a starting element (take the starting point as 0)
So '(list add1 sqr add1) -> 2
What I have so far creates a list of what those function do individually, so for the above example '(1 0 1)
Any help? An explanation would be nice if you could spare one, I'm still iffy about things such as foldr, map, etc
(define (apply_functions lof)
(map (lambda (lof) (lof 0)) lof))
I previously defined a composite function as below in case its helpful at all?
(define (composite f g)
(lambda (x) (f (g x))))
Could the initial problem also be translated to a function which takes in a list of function and an initial number (other than 0) and produces the number result
for example:
'( add1 sqr sub1) 4 -> 10
EDIT::
So looking at the question, it wanted something such as (check-expect ((composite-list (list add1 sqr sub1)) 3) 5), where the start number is not included as a variable. I've tried multiple variations of the code but can't make it work.
This is a perfect situation for using foldr, it behaves as expected:
(define (apply-functions lof)
(foldr (lambda (f acc) (f acc))
0
lof))
(apply-functions (list add1 sqr add1))
=> 2
It works because we apply each f in turn to the accumulated result, starting with 0. Notice that foldr applies the functions in the list in a right-to-left order (that is: the first function applied is the last one in the list, then the result of that is passed to the second-to-last function and so on). If you want to enforce a left-to-right order use foldl instead.
For the last part of your question (after the edit): we can start with a different initial number by simply passing the right parameter to foldr, and returning a curried function:
(define ((composite-list lof) init)
(foldr (lambda (f acc) (f acc))
init
lof))
((composite-list (list add1 sqr sub1)) 3)
=> 5
You can even do it more general than that. You can actually make a generic compose:
(define (my-compose . procedures)
(let* ((proc-in-order (reverse procedures))
(init-proc (car proc-in-order))
(remaining-procs (cdr proc-in-order)))
(lambda g
(foldl (lambda (x acc) (x acc))
(apply init-proc g)
remaining-procs))))
;; test first makes a list of it's arguments,
;; then takes the length, then negates that value
(define test (my-compose - length list))
(test 1 2 3 4) ; ==> -4
The first procedure in the chain (last argument) is applied with the initial argument as a list so it takes many arguments while the rest of the chain takes exactly one.

Abstract List Functions in Racket/Scheme - Num of element occurrences in list

So I'm currently stuck on a "simple?" function in Racket. It's using the Intermediate Student with lambda language.
Some restrictions on this are that NO recursion is allowed, neither are local functions. It's plain and simple abstract list functions.
What this function is supposed to do is to take in a list of numbers, and output a list of pairs in which each pair has the first element as the number with the second element being the number it has occurred in the list.
Examples:
(1 1 2 3) => ((1 2) (2 1) (3 1))
(2 3 4 3) => ((2 1) (3 2) (4 1))
I have a function that produces the number of occurrences by inputting a list of numbers and a number which is:
(define (occurrences lon n)
(length (filter (lambda (x) (= x n)) lon)))
My approach, which was clearly wrong was:
(define (num-pairs-occurrences lon)
(list (lambda (x) (map (occurrences lon x) (remove x lon)) x))
I thought the above would work, but apparently my lambda isn't placed properly. Any ideas?
It's a bit trickier than you imagine. As you've probably noticed, we must remove duplicate elements in the output list. For this, is better that we define a remove-duplicates helper function (also using abstract list functions) - in fact, this is so common that is a built-in function in Racket, but not available in your current language settings:
(define (remove-duplicates lst)
(foldr (lambda (e acc)
(if (member e acc)
acc
(cons e acc)))
'()
lst))
Now it's easy to compose the solution using abstract list functions:
(define (num-pairs-occurrences lon)
(map (lambda (e) (list e (occurrences lon e)))
(remove-duplicates lon)))
The above might return and output list in a different order, but that's all right. And before you ask: yes, we do need that helper function. Please don't ask for a solution without it...
An easy, self-contained solution would be:
(define (num-pairs-occurences lst)
(foldl (lambda (e r)
(if (or (null? r) (not (= (caar r) e)))
(cons (list e 1) r)
(cons (list e (add1 (cadar r))) (cdr r))))
null
(sort lst >)))
Basically, you sort the list first, and then you fold over it. If the element (e) you get is the same as the first element of the result list (r), you increment the count, otherwise you add a new sublist to r.
If you sort by > (descending), you can actually use foldl which is more memory-efficient. If you sort by < (ascending), you need to use foldr which is less efficient.

my defined cond function is not working properly (LISP)

I am trying to define my own function to make my hw2 easier but it is not working. Could you take a look at it and tell me what I am missing?
(DEFUN testAL(x)
COND ( ( ATOMP(x) ) 'this-is-an-atom )
( ( LISTP(x) ) 'this-is-a-list )
( T 'this-is-neither ) )
I want this conditional function to take an input X and output if it is an atom, list, or neither. Problem is that when I input NIL, I get an error: Attempt to take the value of the unbound variable `COND'.
Homework 2 consists of the following question:
Which of the following are atoms, which lists, which both and witch neither?
a. nil
b. (expt 10 3)
c. (a b)
d. 64
e. T
f. (No place like home)
g. ‘(+ 3 5 6)
Your parenthesis are not in the correct places. A parenthesis, unless quoted, are the start of a function application.
It begins with a variable cond that is not bound. It's not the special form (cond (predicate consequent) (predicate2 consequent2)) since it doesn't start with an open parenthesis.
From indentation alone I guess you meant to write:
(DEFUN testAL (x)
(COND ((ATOM x) 'this-is-an-atom)
((LISTP x) 'this-is-a-list)
(T 'this-is-neither)))
(testal 'test) ; ==> THIS-IS-AN-ATOM
(testal '(a b c)) ; ==> THIS-IS-A-LIST
I have removed the extra parenthesis around x since (x) means apply the function x while x means the variable x. With x in a different position like (+ x 3) then + is the function to be applied and x is one of its operands.
I changed atomp to atom. Since atom is one of the very first primitives defined with the very first LISP in the 50's, it does not have a postfix p like most other predicates.
Edit: Multiple match
You could just have several cond (or if since you only have one test in each) and do side effects like (print "THIS-IS-AN-ATOM") since your base case will never trigger (nothing is neither list nor atom in CL). This is perhaps the easies solution.
(DEFUN testAL (x)
(if (ATOM x) (print 'this-is-an-atom))
(if (LISTP x) (print 'this-is-a-list)))
(testal '()) ; ==> THIS-IS-A-LIST (but prints both)
For a more functional approach I would have done it with higher order functions keeping the code testable and supply a print-function that does the side effects. Be aware that this might not be as easy to read for a beginner:
;; a list of pairs of predicate and their desription
(defparameter *type-predicates-and-description*
'((douglasp . this-is-the-answer-to-everything)
(floatp . this-is-a-floating-pont-number)
(integerp . this-is-an-integer)
(numberp . this-is-a-number)
(null . this-is-null)
(listp . this-is-a-list)
(characterp . this-is-a-character)
(stringp . this-is-a-string)))
;; custom made predicate
(defun douglasp (x)
(and (numberp x) (= x 42)))
;; returns all the types of a particular value
(defun get-type-info (x)
"return a list if types thet describes argument"
(flet ((check-type (acc type-pair)
"Accumulate description when predicate match"
(if (funcall (car type-pair) x)
(cons (cdr type-pair) acc)
acc)))
;; test x for each type predicate-description
(let ((res (reduce #'check-type
*type-predicates-and-description*
:initial-value '())))
;; check of empty list (no types matched)
(if (null res)
(list 'this-is-neither)
res))))
;; test it
(get-type-info '()) ; ==> (THIS-IS-A-LIST THIS-IS-NULL)
(get-type-info 42) ; ==> (THIS-IS-A-NUMBER
; THIS-IS-AN-INTEGER
; THIS-IS-THE-ANSWER-TO-EVERYTHING)
(get-type-info #()) ; ==> (THIS-IS-NEITHER)
;; Make a function to do side effects
(defun print-type-info (x)
(format t "~{~a~^, ~}." (get-type-info x)))
(print-type-info '()) ; ==> NIL
; and prints "THIS-IS-A-LIST, THIS-IS-NULL."

Lisp S-Expressions and Lists Length/Size

I am trying to write a function using Common Lisp functions only that will count how many s-expressions are in an s-expression. For example:
((x = y)(z = 1)) ;; returns 2
and
((x - y)) ;; returns 1
Nested expressions are possible so:
((if x then (x = y)(z = w))) ;; returns 3
I wrote a function which finds the length and it works if no nested expressions are there. It is:
(define (length exp)
(cond
((null? exp) 0)
(#t (+ 1 (length (cdr exp))))))
Now I modified this in an attempt to support nested expressions to the following:
(define (length exp)
(cond
((null? exp) 0)
((list? (car exp)) (+ 1 (length (cdr exp))))
(#t (length (cdr exp)))))
This works for expressions with no nests, but is always 1 less than the answer for nested expressions. This is because taking the example above, ((if x then (x = y)(z = w))), this will look at if at first and which satisfies the third condition, returning the cdr (the rest of the expression as a list) into length. The same happens up until (x=y) is reached, at which point a +1 is returned. This means that the expression (if x then .... ) has not been counted.
In what ways would I be able to account for it? Adding +2 will over-count un-nested expressions.
I will need this to work in one function as nesting can happen anywhere, so:
((x = y) (if y then (z = w)))
At first sight, your code only recurses to the right (cdr-side) and not to the left (car-side), so that definitely is a problem there.
On second sight, this is even a little bit more tricky than that, because you are not exactly counting conses; you need to differentiate the case where a cons starts a proper list vs where it's the cdr of a list. If you were to recurse to the car and cdr, that information would be lost. We need to iterate over the sexp as a proper list,
(defun count-proper-list (sexp)
(cond ((atom sexp) 0)
(t (1+ (reduce #'+ (mapcar #'count-proper-list sexp))))))
But this will also count the top level list, therefor always return one more than what you seem to want. So perhaps,
(defun count-proper-sublist (sexp)
(1- (count-proper-list sexp)))

Scheme equivalent of print function in Clojure

I'm looking at Scheme (Dr-Scheme) coming from Clojure.
In Clojure I can type
(print 'a 'b 'c)
and the print function figures out that this is an arbitrary number of non-string arguments and prints them out separated by a space.
In Scheme the print function expects a single argument.
Is there a way to get the equivalent of Clojure's print function in Scheme?
Interesting... you can roll one of those pretty easily, but I'm not sure I see the need for it. For instance:
#lang racket
(define (print-many . args)
(display
(apply
string-append
(add-between (map print-to-string args) " "))))
(define (print-to-string arg) (format "~v" arg))
(print-many 3 4 5 'b '(3 3 4))
In general, though, I'm thinking that if you're generating output for a user, you're going to want better control over the output, and if you're not generating output for a user, you're just as happy slapping a pair of parens around it and making it into a list.
What's the use case for this?
Perhaps you are looking for trace ?
#lang racket
(define (foo x y)
(+ x y))
(define (bar x)
(+ (foo 1 x)
(foo 2 (+ x 1))))
(require racket/trace)
(trace foo)
And then in the interaction window:
> (bar 3)
>(foo 1 3)
<4
>(foo 2 4)
<6
10
I use this set of definitions to print multiple arguments separated by new line:
(define (println x) (display x) (newline))
(define (printlist l) (begin
(println (car l))
(if (not (null? (cdr l))) (printlist (cdr l)))))
(define (multiprint . args) (begin
(if (not (null? args)) (printlist args)
(println "Error: multiprint requires at least one argument"))))