Scheme equivalent of print function in Clojure - 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"))))

Related

Scheme list as an argument

So in Scheme, if I make a list as an argument, how would I go about evaluating that list to itself in the same order?
Would I just write:
(define (function list)
(list)
I don't really understand this.
Your question lacks an example.
Is this what you want:
(define (f . args)
args)
It can be used like this:
> (f 1 2 3)
(1 2 3)
If you have a list and a function which 'evaluates' elements of that list and you want to construct another list which is the result of calling that function on each element of the list then what you are doing is called mapping the function over the list and the function do do that is called map. Given the following two definitions:
(define course-names '((1 "Exploding buckets 101")
(2 "Squirrel cooking 201")
(4 "Flamethrower maintenance 211")))
(define (course->name c)
(let ((found (assq c course-names)))
(if found (second found) "UNKNOWN SECRET COURSE")))
Then
> (map course->name '(1 2 3 4))
'("Exploding buckets 101"
"Squirrel cooking 201"
"UNKNOWN SECRET COURSE"
"Flamethrower maintenance 211")
It's worth seeing how you can write things like map: here is one way:
(define (simple-map f l)
(define (simple-map-loop tail accum)
(if (null? tail)
(reverse accum)
(simple-map-loop (rest tail) (cons (f (first tail)) accum))))
(simple-map-loop l '()))
or:
(define (f lst)
lst)
used as:
(f '(1 2 3))
;; '(1 2 3)

How can I apply each element in a list to a function in scheme?

The function applyToAll is suppose to take in a function and a List, then take the car of the list and apply each element to the fuction.
This is what I have worked out so far:
(define applyToAll(lambda (f L)
(cond
((null? L) '())
(#t (cons (L) (applyToAll f(car L))))
)))
I'm not sure what I am doing wrong. A fuction call would look like
(applyToAll (lambda (n) (* n n)) '(1 2 3) )
and it would return
(1 4 9)
Instead it returns: function call: expected a function after the open parenthesis, but received (list 1 2 3)
Any help as to why my code is not working?
Thanks
It sounds like you are trying to implement map.
The error you are getting is because you are calling a list as though it's a function (lst1)
( ) this means function call in scheme
You are making the same mistake here:
(#t (cons (L) (applyToAll f(car L))))
the right way to apply is:
(function arg0 arg1 ... argn)
You need to apply f to each element in the list like so:
(cons (f (car L)) (applyToAll f (cdr L))))
OR just use map:
(map proc lst ...+)
gl

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)))

Ignore non-number values in a list and find the sum recursive method

I need to create a recursive method in LISP that takes the numbers in a list and finds the sum. Anything in the list that is not a number is skipped (For example, if the list contains "Cheese 12 Dog 8 Shoe 5", the output would be 25).
Right now my code finds the sum, but throws an error if there is anything in the list that is not a number. What can be changed to fix that?
(defun adder (lis)
(cond
((null lis) 0)
(t (eval (cons '+ lis)) )
)
)
This would do:
(defun adder (lis)
(if (null lis)
0
(let ((c (car lis)))
(if (numberp c)
(+ c (adder (cdr lis)))
(adder (cdr lis))))))
Your version is not recursive (you don't call adder inside of adder), maybe you meant something like this (which is non-recursive)?
(defun adder (lis)
(apply '+ (remove-if-not 'numberp lis)))
Using apply on lists that can be long is a bit dangerous. If the list is longer than call-arguments-limit, then (apply '+ list) won't work. Now, call-arguments-limit is typically pretty big in modern Lisps, but it's allowed to be as small as 50. For more information about this, see:
Common lisp: How many argument can a function take? (this answer uses (reduce '+ …))
In Lisp, how many inputs can the + function actually have?
I think your best bet would be to use reduce '+ list with a key function that takes each number to itself and each non-number to 0. (This key function is what abiessu mentioned in a comment.)
(reduce '+ list :key (lambda (x) (if (numberp x) x 0)))
CL-USER> (let ((list '(cheese 12 dog 8 shoe 5)))
(reduce '+ list :key (lambda (x) (if (numberp x) x 0))))
25
CL-USER> (let ((list '()))
(reduce '+ list :key (lambda (x) (if (numberp x) x 0))))
0
Instead of using a more complex key function, you could also use (remove-if-not 'numberp list) to get rid of the non-numbers (or (remove-if (complement 'numberp) list)):
CL-USER> (let ((list '(cheese 12 dog 8 shoe 5)))
(reduce '+ (remove-if-not 'numberp list)))
25
CL-USER> (let ((list '()))
(reduce '+ (remove-if-not 'numberp list)))
0

How do I handle a variable number of arguments passed to a function in Racket?

I like creating functions which take an unlimited number of arguments, and being able to deal with them as a list. It's been useful to me when creating binary trees & I'm using it for a variation on the nearest-neighbor algorithm right now. My method, however, is really horrible: since I can't think of a way to iterate over an improper list (which may well be improper & degenerate), I tried using various list functions to force the improper list into list form.
This is my best attempt in a simple function to determine difference between map-nodes (works, just not sure why it works):
(define distance-between
(lambda xs
(let ([input-list (list* xs null)])
(letrec
([f (lambda (xs acc)
(if (null? (cdr xs))
acc
(f (cdr xs)
(+ (abs (- (map-node-x (car xs))
(map-node-x (cadr xs))))
(abs (- (map-node-y (car xs))
(map-node-y (cadr xs))))
acc))))])
(f (car input-list) 0)))))
As you can see, it's an ugly solution and involves some of what seems like magic to me - why is the improper list coerced into list form when I include it in a list*? (note: this sentence is misleading, this does not occur).
I'd rather have a pretty solution and no magic. Can anyone help?
For example a typical input would be:
(distance-between (map-node 1 2) (map-node 2 3) (map-node 3 4))
with the expected result:
4
(a distance of 2 between map-node (a) and m-n (b), plus a distance of 2 between map-node (b) and map-node (c)).
Alternatively one might simply input:
(distance-between (map-node 1 2) (map-node 2 2))
and get an answer of:
1
If I attempted this on the raw input, without my (let ([input-list...])...) statement, it would cause an error as (? not actually sure why given response to this question).
The function works as expected.
There's nothing improper about the list received as a variadic argument list (meaning: variable number of arguments). For example:
(define test-list
(lambda xs
(length xs))) ; xs is a normal list, use it like any other list
(test-list 1 2 3 4)
=> 4
In the above example, the xs parameter is a normal, plain, vanilla list, there's nothing improper about it. You can iterate over it as you would over any other list. There's no need to car it, it's already a list! Also, notice that the same function can be written like this:
(define (test-list . xs)
(length xs)) ; xs is a normal list, use it like any other list
Just for reference: an improper list is one that does not end with the null list. For example: '(1 2 3 . 4). Again, that's not how a variadic argument list looks.
I also don't understand how your variadic argument list could be improper.
But to answer your original question (how to iterate over a possibly improper list, somewhat more elegantly), here is one way using match:
#lang racket
(define (properly-sum-improper-list xs)
(let loop ([acc 0]
[xs xs])
(match xs
[(list) acc]
[(cons x more) (loop (+ acc x) more)]
[x (+ acc x)]))) ;last item of improper list
(require rackunit)
(check-equal? (properly-sum-improper-list '(1 2 3 4)) 10)
(check-equal? (properly-sum-improper-list '(1 2 3 . 4)) 10)
However needing to do this, at all, is probably an indication you want to fix or change something else.
Your list is not improper. When your argument is not a pair, like (lambda xs body ...) or (define (fun . xs) body ...) all your arguments gets slurped into a list. Eg.. (fun 1 2 3) would make xs '(1 2 3). Doing (list* '(1 2 3) '()) makes '((1 2 3) which you undo right away by calling your loop with car which makes it '(1 2 3) again.
Other than that your procedure works as intended. You might clean up your procedure a little, but since there is no list comprehensions that glides over a list folding over the two next elements it won't become much smaller. Below is basically the same code, but abstracting out the procedure that does the work (which if existed a foldl-pair you could have used) and with a named let as a iterator loop (which is syntactic sugar for a letrec+call).
(define (distance-between e1 . lst)
(define (add-diff-acc e1 e2 acc)
(+ (abs (- (map-node-x e1) (map-node-x e2)))
(abs (- (map-node-y e1) (map-node-y e2)))
acc))
(let iterate ((e1 e1) (lst lst) (acc 0))
(if (pair? lst)
(let ((e2 (car lst)))
(iterate e2 (cdr lst) (add-diff-acc e1 e2 acc)))
acc)))
EDIT: About syntax sugar, named let and letrec.
(let ((x 10) (y 19))
body)
is syntactic sugar for a anonymous procedure call
((lambda (x y)
body)
10 19)
A named let is just giving that procedure a name, though as if by letrec, making a recursive binding. you call it with the name you give and the arguments will be what you supply instead of the initial value in the let. I'm used to them and prefer them today. It might take some time to get used to though.
Most of the code we write is syntactic sugar for some lower level stuff. The macros are nested so that your letrec form could get reduced down lambdas eventually. The whole procedure without syntactic sugar would look like this:
(define distance-between
(lambda (e1 . lst)
((lambda (add-diff-acc)
((lambda (iterate e1 lst acc) ; emulate Y to substitute `letrec`
(iterate iterate e1 lst acc))
(lambda (iterate e1 lst acc)
(if (pair? lst)
((lambda (e2)
(iterate iterate e2 (cdr lst) (add-diff-acc e1 e2 acc)))
(car lst))
acc))
e1 lst 0))
(lambda (e1 e2 acc)
(+ (abs (- (map-node-x e1) (map-node-x e2)))
(abs (- (map-node-y e1) (map-node-y e2)))
acc)))))