Creating a Lisp alias with defalias or new function? - function

I want mylist to have the same functionality as list. In most Lisps (I'm on Emacs Lisp) I can simply write
(defalias 'mylist 'list)
But if I want to write my own I can write
(defun mylist (&rest x)
(car (list x)))
which has the same functionality. But then I got this by experimenting. First, I had this code
(defun mylist (&rest x)
(list x))
which produced a list in a list. I wasn't sure why, but the simple solution was to just put (list x) inside a car and call it good. But I'd like to know why I get a list inside a list when I don't use the car trick. What am I missing?

But if I want to write my own I can write
(defun mylist (&rest x)
(car (list x)))
But why?
3 -> 3
(list 3) -> (3)
(car (list 3)) -> 3
So (car (list arg)) is a no-op on arg.
Thus it's just:
(defun mylist (&rest x)
x)
But I'd like to know why I get a list inside a list when I don't use the car trick. What am I missing?
if you have a list
x -> (1 2 3)
and call list on it
(list x) -> ((1 2 3))
Then you get a list in a list.
Calling car on a list is also not a trick. It's returning the first element of that list:
(car (list x)) -> (1 2 3)

(defun my-list (&rest x) …
The &rest parameter means that all remaining arguments are put into a list that is bound to this parameter. X then holds the list that you want. You're done.
(defun my-list (&rest x)
x)

Related

Combining two functions in LISP to atomize list and then find max?

So, id like to take in a list of numbers, atomize it (to remove nested integers), then find the max value. I have two functions written that accomplish this individually, but can't figure out how to combine them in LISP so I can make one call and have them both run. Any help would be appreciated.
:Atomize function to remove nests
:(atomify ‘( a (b c) (e (f (g h) i)) j)->(a b c e f g h i j)
(defun atomify (numbers)
(cond ((null numbers) nil)
((atom (car numbers))
(cons (car numbers)
(atomify (cdr numbers))))
(t
(append (atomify (car numbers))
(atomify (cdr numbers))))))
:Max value of a list of integers function
(defun large_atom (numbers)
(if (null numbers)
0
(max (first numbers)
(large_atom (rest numbers)))))
Jamie. Your way has two steps:
1. Flatten list
2. Find max value from result of 1'st step
In this case it's true way. But you need do it with one function call. It's easy. Just use labels, apply and of course max
(defun foo (lst)
(labels ((flatten (lst acc)
(cond
((null lst)
acc)
((consp (car lst))
(flatten (cdr lst) (flatten (car lst) acc)))
(t
(flatten (cdr lst) (cons (car lst) acc))))))
(apply #'max (flatten lst nil))))
Another way, is do not flatten source list. But in this case you need find first value to compare with other values. Try it yourself.
Here is another way to solve the problem: rather than flattening the list, this walks down it recursively. This is very explicit about what the structure of the list must be: a good list is a non-null proper list each of whose elements is either an integer or a good list.
The problem with this approach is that it's not tail recursive so it will necessarily fail on very large structures (and even if it was tail recursive CL does not promise to deal with tail recursion.
(defun greatest-integer (good-list)
;; a good list is one of:
;; - a cons of a good list and either a good list or ()
;; - a cons of an integer and either a good list or ()
;; In particular it can't be () and it can't be an improper list
;;
(destructuring-bind (a . b) good-list
;; a can be an integer or a good list, b can be null or a good list
(etypecase b
(null
(etypecase a
(integer a)
(cons (greatest-integer a))))
(cons
(max (etypecase a
(integer a)
(cons (greatest-integer a)))
(greatest-integer b))))))

lisp self-developed recursive reverse function

I have writte a list reverse function in lisp and I wanted to test it but I had an error and I couldn't solve it
the function and calling is below :
(defun myreverse (list)
(cond((null list) nil))
(cons (myreverse(cdr list) (car list))))
(myreverse '(1 2 3))
any help will be appreciated...
The arguments when you defun myreverse are (list), thus when you call it (myreverse '(1 2 3)) list gets bound to (1 2 3).
Since the list is not null you suddenly do (myreverse '(2 3) 1) and list gets bound to (2 3), but what do 1 get bound to? You have no more than one argument thus the call is invalid and warrants an error.
Hint1: There is a way to make optional arguments:
(defun test (a &optional (b 0) (c 0))
(+ a b c))
(test 10) ; ==> 10
(test 10 1 2) ; ==> 13
Hint2: You need to build a list not just pass a bare element. The passed list will be the tail of the next round until the every element is added.
The bad answer (or one of the bad answers):
(defun reverse (list)
(cond ((null list) list)
(t (append (reverse (cdr list)) (cons (car list) nil)))))
A better answer:
(defun reverse (list)
(reverse-aux list nil))
(defun reverse-aux (list result)
(cond ((null list) result)
(t (reverse-aux (cdr list) (cons (car list) result)))))
It's the basic example we use in comparison to the definition of 'append' in lessons to differentiate tail recursion.

I wrote up some simple scheme functions, but apparently none of them work and I'm wondering why

I wrote up a few little scheme functions
; Given a list, this should return the maximum value in the list.
(define (maxInt lst)
(if (empty? lst) 0 ; if the list is empty, return 0
(max(first lst) (maxInt(rest lst)))))
; ^ What this line does is recursively take the maximum of pairs in the list.
; Ex. If the list was (7 3 6 2), this line would take the max of 7 and (the max of 3 and(the max of 2 and 6)),
; returning a result of 7.
; The zip3 function. Takes three lists of integers and returns a list of ordered triples containing the first, second, or third elements of each original list(i.e. an ordered triple containing the first elements of each list, etc)
(define (zip3 lst1 lst2 lst3)
(if (or((not(= (length lst1)(length lst2))) (not(= (length lst2)(length lst3))) (not(= (length lst 1)(length lst3))))) (error "Error")
(append (map car(lst1 lst2 lst3)) (map cadr(lst1 lst2 lst3)) (map caddr(lst1 lst2 lst3)))))
; This says 'if list 1 and 2 are different lengths or list 2 and 3 are different lengths or list 1 and 3 are different lengths, return an error.
; Otherwise, append the list containing the ordered triple of the second element of each list and that containing said triple of the third element
; to the list containing the ordered triple of the first element of each list.'
; The compute function. takes a list of integers and and integer x and computes a + bx + cx^2 + etc, with a, b, c, etc being the ints in the list.
(define (compute polyLst x)
(for ([i (length polyLst)])
(+ (* (list-ref polyLst i) (expt x i)))))
; Recursion was hinted at for this one, but I found it easier to just use a for loop. This takes the sum of the products of each element of the list and
; x raised to the power of that element's index in the list.
I used the scheme notation exactly right(I thought), but none of these functions worked upon testing with a test program that called them. I'm really confused as to why these functions didn't work. It doesn't make any sense to me. I just want to know what I did wrong.
maxInt seems to work.
zip3 has a few parentheses errors, must use list and should read
(define (zip3 lst1 lst2 lst3)
(if (or (not(= (length lst1)(length lst2))) (not(= (length lst2)(length lst3))) (not(= (length lst1)(length lst3))))
(error "Error")
(append (map car (list lst1 lst2 lst3)) (map cadr (list lst1 lst2 lst3)) (map caddr (list lst1 lst2 lst3)))))
and compute needs to use for/sum:
(define (compute polyLst x)
(for/sum ([i (length polyLst)])
(* (list-ref polyLst i) (expt x i))))
Some refactoring ideas:
(define (maxInt lst)
(apply max lst))
(define (zip3 . l)
(flatten (apply map list l)))
(define (compute polyLst x)
(for/sum ([(e n) (in-indexed polyLst)])
(* e (expt x n))))

Creating a Function that produces a Function Scheme/DrRacket

I'm working on a function that takes in a list of structures and then using that list of structures produces a function that processes a list of symbols into a number. Each structure is made up of a symbol, that will be in the second list consumed, and a number. This function produced has to turn the list of symbols into a number by assigning each symbol a value based on the previous structures. Using abstract list functions btw.
Example: ((function (list (make-value 'value1 10) (make-value 'value2 20)))
(list 'value1 'value2 'nothing 'value1)) would produced 40.
Heres my code but it only works for specific cases.
(define (function lst)
(lambda (x) (foldr + 0 (map (lambda (x)
(cond
[(equal? x (value-name(first lst)))(value-value (first lst))]
[else (value-value (second lst))]))
(filter (lambda (x) (member? x (map value-name lst)))x)))))
Looks like a homework. Basic shape of your solution is ok. I think the reason you have a problem here is that there is no decomposition in your code so it's easy to get lost in parentheses.
Let's start with your idea of fold-ing with + over list of integers as a last step of computation.
For this subtask you have:
1) a list of (name, value) pairs
2) a list of names
and you need to get a list of values. Write a separate function which does exactly that and use it. Like this
(define (function lst)
(lambda (x) (foldr +
0
(to-values x lst)))
(define (to-values names names-to-values)
(map (lambda (name)
(to-value name names-to-values))))
(define (to-value n ns-to-vs)
...)
Here we map over the names with another little function. It will lookup the n value in ns-to-vs and return it or 0 if there is no one.
There are two approaches for solving the problem with foldr, it'd be interesting to study and understand both of them. The first one, attempted in the question, is to first produce a list with all the values and let foldr take care of adding them. It can be implemented in a simpler way like this:
(define (function lst)
(lambda (x)
(foldr +
0
(map (lambda (e)
(cond ((assoc e lst) => value-value)
(else 0)))
x))))
Alternatively: maybe using foldr is overkill, applying + is simpler:
(define (function lst)
(lambda (x)
(apply +
(map (lambda (e)
(cond ((assoc e lst) => value-value)
(else 0)))
x))))
In the second approach we take the input list "as is" and let foldr's lambda perform the addition logic. This is more efficient than the first approach using foldr, because there's no need to create an intermediate list - the one generated by map in the first version:
(define (function lst)
(lambda (x)
(foldr (lambda (e a)
(cond ((assoc e lst) => (lambda (p) (+ a (value-value p))))
(else a)))
0
x)))
In both approaches I'm using assoc for finding the element in the list; it's easy to implement as a helper function if you're not allowed to use it or if it doesn't work for the values created with make-value: assoc takes a list of name-value pairs and returns the first pair with the given name. The => syntax of cond passes the pair returned by assoc to a lambda's parameter and executes it.
And because you're using Racket, there's a bit of syntactic sugar that can be used for returning a function from another function, try this equivalent code, for simplicity's sake:
(define ((function lst) x)
(foldr +
0
(map (lambda (e)
(cond ((assoc e lst) => value-value)
(else 0)))
x)))
Or this:
(define ((function lst) x)
(foldr (lambda (e a)
(cond ((assoc e lst) => (lambda (p) (+ a (value-value p))))
(else a)))
0
x))
Anyway, the result is as expected:
((function (list (make-value 'value1 10) (make-value 'value2 20)))
(list 'value1 'value2 'nothing 'value1))
=> 40

Common Lisp - Using a function as input to another function

Say I have a function that takes a list and does something:
(defun foo(aList)
(loop for element in aList ...))
But if the list is nested I want to flatten it first before the loop does stuff, so I want to use another function (defun flatten(aList)) that flattens any list:
(defun foo(flatten(aList))
(loop for element in aList ...))
Lisp doesn't like this. Is there another direct way around this?
Here's one way:
(defun foo (alist)
(loop for element in (flatten alist) ...)
You can pass the function as an &optional argument.
(defun foo (alist &optional fn)
(if (not (null fn))
(setf alist (funcall fn alist)))
(dostuff alist))
A sample run where dostuff just print its argument:
(foo '(1 2 (3)))
=> (1 2 (3))
(foo '(1 2 (3)) #'flatten)
=> (1 2 3)
This approach is more flexible as you are not tied to just one 'pre-processor' function.