Need a little help for this scheme "leet-speak" - recursion

I wrote a program below for "Define a procedure leet-speak takes a string and returns the result of changing all s's to fives, all e's to threes, all l's to ones, and all o's to zeros. Do not write any recursive code to do this. Simply make use of string->list, map, and list->string."
The error I got is:
~ (leet-speak "leet speak neat speak")
Exception: attempt to apply non-procedure (1 3 3 #\t #\space 5 ...)
Here is my definition for leet-speak:
(define leet-speak
(lambda (y)
(list->string
((map
(lambda (x)
(cond
[(eq? #\l x) 1]
[(eq? #\s x) 5]
[(eq? #\o x) 0]
[(eq? #\e x) 3]
[else x])
) (string->list y )))))
I really can't find out where the problem is.

You have too many parentheses around the map. Remove the extra so that there's only one parenthesis before map, and you should be good to go.
Your cond also needs to return the character corresponding to the number, not the number itself. Also, consider using a case instead of the cond you have.
All up, here's how it would look:
(define (leet-speak str)
(list->string
(map (lambda (x)
(case x
[(#\l) #\1]
[(#\s) #\5]
[(#\o) #\0]
[(#\e) #\3]
[else x]))
(string->list str))))

Related

Using symbol parameters in a function without parentheses and quote in Common Lisp

(defun all-longer-than-1-char? (&rest elements)
(every (lambda (x) (> (length
(cond ( (typep x 'integer) (write-to-string x) )
( (typep x 'string) x )
( (typep x 'symbol) (symbol-name x) )
))
1))
elements))
(all-longer-than-1-char? "OK" "NO" 1)
I'd like this function to work on symbol parameters (i.e. without having to double quote or to enter numbers) but it doesn't work. To make it work with symbol parameters:
(defun all-longer-than-1-char? (lst)
(every (lambda (x) (> (length
(cond ( (typep x 'integer) (write-to-string x) )
( (typep x 'string) x )
( (typep x 'symbol) (symbol-name x) )
))
1))
lst))
(all-longer-than-1-char? '(OK NO 1))
NIL
But this time I have to enclose the parameters inside parentheses and quote it. I'd like to make it work both with symbol parameters and without having to put parameters inside parentheses and quote them, like:
(all-longer-than-1-char? OK NO 1)
How to do it?
You can use &rest to create what would once have been called a 'nospread' function (or an 'lexpr' depending on your religion), which is very often less useful other than as a user-interface since if you have a list of things you then have to use apply.
Common Lisp doesn't have functions which don't evaluate their arguments, which was once what was known as a 'nlambda' (or an 'fexpr' if you belong to the wrong cult), so you need to quote forms which would otherwise mean something to the evaluator.
You can get the same result as an nlambda with a macro. But you almost certainly don't want to do that as it smells like a bad use of a macro.
Given
(defun all-longer-than-1-char-p (list)
(every (lambda (x)
(> (length
(etypecase x
(string x)
(integer (write-to-string x))
(symbol (symbol-name x))))
1))
list))
Then the nospread one might be
(defun all-longer-than-1-char-p/nospread (&rest list)
(all-longer-than-1-char list))
And the nlambda one might be
(defmacro all-longer-than-1-char-p/quoted/nospread (&rest things)
`(all-longer-than-1-char ',things))
So now
> (all-longer-than-1-char-p '(xx yy 12 "foo"))
t
> (all-longer-than-1-char-p/nospread 'xx 'yy 12 "foo")
t
> (all-longer-than-1-char-p/quoted/nospread xx yy 12 "foo")
t
(All assuming *print-base* is less than 13).
But
> (let ((x "xx"))
(all-longer-than-1-char-p/quoted/nospread x))
nil
So, not very semantically useful, and kind of a poster child for how not to use macros.

Why are this list's contents retained between function calls? [duplicate]

Could someone explain to me what's going on in this very simple code snippet?
(defun test-a ()
(let ((x '(nil)))
(setcar x (cons 1 (car x)))
x))
Upon a calling (test-a) for the first time, I get the expected result: ((1)).
But to my surprise, calling it once more, I get ((1 1)), ((1 1 1)) and so on.
Why is this happening? Am I wrong to expect (test-a) to always return ((1))?
Also note that after re-evaluating the definition of test-a, the return result resets.
Also consider that this function works as I expect:
(defun test-b ()
(let ((x '(nil)))
(setq x (cons (cons 1 (car x))
(cdr x)))))
(test-b) always returns ((1)).
Why aren't test-a and test-b equivalent?
The Bad
test-a is self-modifying code. This is extremely dangerous. While the variable x disappears at the end of the let form, its initial value persists in the function object, and that is the value you are modifying. Remember that in Lisp a function is a first class object, which can be passed around (just like a number or a list), and, sometimes, modified. This is exactly what you are doing here: the initial value for x is a part of the function object and you are modifying it.
Let us actually see what is happening:
(symbol-function 'test-a)
=> (lambda nil (let ((x (quote (nil)))) (setcar x (cons 1 (car x))) x))
(test-a)
=> ((1))
(symbol-function 'test-a)
=> (lambda nil (let ((x (quote ((1))))) (setcar x (cons 1 (car x))) x))
(test-a)
=> ((1 1))
(symbol-function 'test-a)
=> (lambda nil (let ((x (quote ((1 1))))) (setcar x (cons 1 (car x))) x))
(test-a)
=> ((1 1 1))
(symbol-function 'test-a)
=> (lambda nil (let ((x (quote ((1 1 1))))) (setcar x (cons 1 (car x))) x))
The Good
test-b returns a fresh cons cell and thus is safe. The initial value of x is never modified. The difference between (setcar x ...) and (setq x ...) is that the former modifies the object already stored in the variable x while the latter stores a new object in x. The difference is similar to x.setField(42) vs. x = new MyObject(42) in C++.
The Bottom Line
In general, it is best to treat quoted data like '(1) as constants - do not modify them:
quote returns the argument, without evaluating it. (quote x) yields x.
Warning: quote does not construct its return value, but just returns
the value that was pre-constructed by the Lisp reader (see info node
Printed Representation). This means that (a . b) is not
identical to (cons 'a 'b): the former does not cons. Quoting should
be reserved for constants that will never be modified by side-effects,
unless you like self-modifying code. See the common pitfall in info
node Rearrangement for an example of unexpected results when
a quoted object is modified.
If you need to modify a list, create it with list or cons or copy-list instead of quote.
See more examples.
PS1. This has been duplicated on Emacs.
PS2. See also Why does this function return a different value every time? for an identical Common Lisp issue.
PS3. See also Issue CONSTANT-MODIFICATION.
I found the culprit is indeed 'quote. Here's its doc-string:
Return the argument, without evaluating it.
...
Warning: `quote' does not construct its return value, but just returns
the value that was pre-constructed by the Lisp reader
...
Quoting should be reserved for constants that will
never be modified by side-effects, unless you like self-modifying code.
I also rewrote for convenience
(setq test-a
(lambda () ((lambda (x) (setcar x (cons 1 (car x))) x) (quote (nil)))))
and then used
(funcall test-a)
to see how 'test-a was changing.
It looks like the '(nil) in your (let) is only evaluated once. When you (setcar), each call is modifying the same list in-place. You can make (test-a) work if you replace the '(nil) with (list (list)), although I presume there's a more elegant way to do it.
(test-b) constructs a totally new list from cons cells each time, which is why it works differently.

Scheme Make list of all pair permutations of elements in two equal length lists

I am trying to combine two lists of x coordinates and y coordinates into pairs in scheme, and I am close, but can't get a list of pairs returned.
The following can match up all the pairs using nested loops, but I'm not sure the best way to out put them, right now I am just displaying them to console.
(define X (list 1 2 3 4 5))
(define Y (list 6 7 8 9 10))
(define (map2d X Y)
(do ((a 0 (+ a 1))) ; Count a upwards from 0
((= a (length X) ) ) ; Stop when a = length of list
(do ((b 0 (+ b 1))) ; Count b upwards from 0
((= b (length Y) ) ) ; Stop when b = length of second list
(display (cons (list-ref X a) (list-ref Y b))) (newline)
))
)
(map2d X Y)
I am looking to have this function output
((1 . 6) (1 . 7) (1 . 8) ... (2 . 6) (2 . 7) ... (5 . 10))
I will then use map to feed this list into another function that takes pairs.
Bonus points if you can help me make this more recursive (do isn't 'pure' functional, right?), this is my first time using functional programming and the recursion has not been easy to grasp. Thanks!
The solutions of Óscar López are correct and elegant, and address you to the “right” way of programming in a functional language. However, since you are starting to study recursion, I will propose a simple recursive solution, without high-level functions:
(define (prepend-to-all value y)
(if (null? y)
'()
(cons (cons value (car y)) (prepend-to-all value (cdr y)))))
(define (map2d x y)
(if (null? x)
'()
(append (prepend-to-all (car x) y) (map2d (cdr x) y))))
The function map2d recurs on the first list: if it is empty, then the cartesian product will be empty; otherwise, it will collect all the pairs obtained by prepending the first element of x to all the elements of y, with all the pairs obtained by applying itself to the rest of x and all the elements of y.
The function prepend-to-all, will produce all the pairs built from a single value, value and all the elements of the list y. It recurs on the second parameter, the list. When y is empty the result is the empty list of pairs, otherwise, it builds a pair with value and the first element of y, and “conses” it on the result of prepending value to all the remaining elements of y.
When you will master the recursion, you can pass to the next step, by learning tail-recursion, in which the call to the function is not contained in some other “building” form, but is the first one of the recursive call. Such form has the advantage that the compiler can transform it into a (much) more efficient iterative program. Here is an example of this technique applied to your problem:
(define (map2d x y)
(define (prepend-to-all value y pairs)
(if (null? y)
pairs
(prepend-to-all value (cdr y) (cons (cons value (car y)) pairs))))
(define (cross-product x y all-pairs)
(if (null? x)
(reverse all-pairs)
(cross-product (cdr x) y (prepend-to-all (car x) y all-pairs))))
(cross-product x y '()))
The key idea is to define an helper function with a new parameter that “accumulates” the result while it is built. This “accumulator”, which is initialized with () in the call of the helper function, will be returned as result in the terminal case of the recursion. In this case the situation is more complex since there are two functions, but you can study the new version of prepend-to-all to see how this works. Note that, to return all the pairs in the natural order, at the end of the cross-product function the result is reversed. If you do not need this order, you can omit the reverse to make the function more efficient.
Using do isn't very idiomatic. You can try nesting maps instead, this is more in the spirit of Scheme - using built-in higher-order procedures is the way to go!
; this is required to flatten the list
(define (flatmap proc seq)
(fold-right append '() (map proc seq)))
(define (map2d X Y)
(flatmap
(lambda (i)
(map (lambda (j)
(cons i j))
Y))
X))
It's a shame you're not using Racket, this would have been nicer:
(define (map2d X Y)
(for*/list ([i X] [j Y])
(cons i j)))

What's wrong with my Lisp code?

I have some lisp code that I have to write multiple different ways. I've tried two different ways and I'm unsure of why they don't work. The function has to take a list and return only integers in that list. The first one has to take a map function and the second one has to use loop. This is in Clisp.
Here is my code.
(defun posint1 (l)
(mapcan #'(lambda (x)
(and (integerp x)
(list l)))))
and
(defun posint1 (l)
(loop for x in (list l)
when (integerp x)
collect x)
(format t "~A " x))))
mapcan requires at least one list argument and you have supplied none in your first function (I can't use names since you call both the same)
The second function tried to format a variable, x, that does not exist in that scope. In loop x are the one element in (list l) which probably should just be l since making a one number list doesn't really need iteration. Perhaps you wanted something like:
(defun print-integers (list)
(loop :for x :in list
:when (integerp x)
:collect x :into result
:finally (format t "~A " result)))
;; or using the result as argument
(defun print-integers (list)
(format t
"~A "
(loop :for x :in list
:when (integerp x)
:collect x)))
(print-integers '(-1 0.5 1/3 +inf.0 9)) ; ==> NIL (prints (-1 9)
Also notice that integerp works for whole numbers, also negative ones. The name hinted that you might want to use (and (integerp x) (>= x 0)) instead.

Trouble returning recursively-built lists to calling functions in Lisp

I am new to Lisp and have an issue regarding recursion and function returns. In the interests of trying to better understand and solve my problem, I provide the following scenario. I apologize if it is verbose. If this aggravates others, I'm happy to trim it down. To skip right to the business, please read from the horizontal line onward.
Imagine a waitress at a bar. Instead of taking drink orders, she forces her patrons to identify themselves as drinkers of beer, rum, whiskey, or some combination of these. Then she grabs a tray full of either beer, rum or whiskey and does a lap around the bar, leaving exactly one drink with any customer who has identified themself as a drinker of that particular beverage. When she's finished each round, she always sits down and has a Long Island Ice Tea. Afterward, she proceeds to grab another tray of exclusively one type of drink and goes out for delivery again. No customer can ever refuse a drink, and no one can change their drink preferences.
Now, Mindy (the waitress) needs a novel way of keeping track of how many drinks of each type she is delivering to each patron. Mindy isn't very good at math and by the end of the night all of those Long Island Ice Teas are really adding up.
So when she asked for a simple solution for tracking her drink dispensing, I naturally suggested creating a simple little Lisp program. Here's how it is to work: When she has finished delivering a round of tasty beverages, Mindy simply walks up to her Altair 8800 and types the following:
(update-orders <order-list> <drink>)
where is the list of all customers and their orders, and is the drink she just served in her most recent outing.
It should properly go through the lists of customers and their drink counts, updating the proper drinks by one and leaving the others alone. To interface with the computer system in place, a newly-updated orders-list needs to be returned from the function when it is complete.
Just today I came across the following bug: after properly calling the function, the value returned is not what I want. The list only includes the very last drink count list of the very first customer in the list, every time. Recursive programming is the real culprit here, as opposed to Lisp, and I have tried altering the code to fix this, but to no avail. I need a full list returned from the function.
As you may have guessed, this story is not true. The real problem I am trying to solve is related to calculus, and is a well-known topic for those getting their feet wet with Lisp. However, my problem is not with my assignment, but rather with wrapping my mind around the recursive calls and returning full lists of values to calling functions, so that I may build a complete list of all terms to return when finished. After I am able to solve this sub-problem, I am just a stones throw away from applying it to my actual assignment and solving it.
Running the following function call:
(update-orders (quote ( (bill (4 beer) (5 whiskey)) (jim (1 beer)) (kenny (1 whiskey) (4 rum)) (abdul (1 beer) (3 whiskey) (2 rum) ))) (quote beer))
gets me the following returned:
((5 WHISKEY))
I would, instead, like a list in the same format as the one supplied to the function above.
Please see the code below. It has been modified to include debugging output to the screen for convenience. Function drink-list is likely where my trouble lies.
(defun update-orders (x d)
(print 'orders)
(prin1 x)
(order (car x) d)
)
(defun order (x d)
(print 'order)
(prin1 x)
(drink-list (cdr x) d)
)
(defun drink-list (x d)
(print 'drink-list)
(prin1 x)
;(append
;(cons
;(list
(drink-count (car x) d)
(cond
((cdr x) (drink-list (cdr x) d))
(t x)
)
;)
)
(defun drink-count (x d)
(print 'drink-count)
(prin1 x)
(list
(cond
((eq (car (cdr x)) d)
(modify-count (car x) 1))
(t x)
)
)
)
(defun modify-count (x d)
(print 'modify-count)
(prin1 x)
(print 'new-modify-count)
(prin1 (+ (parse-integer (subseq (write-to-string x) 0)) 1))
(list
(+ (parse-integer (subseq (write-to-string x) 0)) 1)
)
)
EDIT:
I have incorporated ooga's suggestions into my code. The new order and update-order functions are shown below:
(defun update-orders (x d)
(cond
((null x) ())
(t (cons (order (car x) d) (update-orders (cdr x) d)))
)
)
(defun order (x d)
;(print 'order)
;(prin1 x)
(drink-list (cdr x) d)
)
I now get the following list returned, running the same function call as above:
(((5 WHISKEY)) ((1 BEER)) ((4 RUM)) ((2 RUM)))
which is a list of embedded lists (2 deep, I believe) that include all of the last drink item and drink count of each patron in the list (Bill's final list entry is 5 whiskey, Jim final entry is 1 beer, etc). Their first n-1 drinks are not added to the returned list of their drinks.
Have I misread your suggestion? I have a feeling I am a half step away here.
In update-orders you only pass the car of x to order. The rest of x is completely ignored. Then you only pass the cdr of that is on to drink-list.
As an example of how your code should be structured, here's a program that adds 1 to each member of the given list.
Example call: (increment-list '(1 2 3))
(defun increment-list (x)
(cond
((null x) ())
(t (cons (increment (car x)) (increment-list (cdr x))))
)
)
(defun increment (x)
(+ x 1)
)
Change increment-list to update-orders and increment to orders (and add the second input, etc.) and that, I think, should be your program structure.
Also, you should try to build it from the bottom up. Try writing a function that will add one to the number if the given drink in a (number drink) list matches. I.e., given this:
(add-one-if '(4 beer) 'beer)
It should return this
(5 BEER)
And given this
(add-one-if '(3 whiskey) 'beer)
It should return this
(3 WHISKEY)
As suggest above, here is the full code I have implemented to solve my problem, incorporating the suggested structure provided by ooga.
;;;; WAITING-TABLES
(defun update-orders (x d)
(cond
((null x) ())
(t (cons (order (car x) d) (update-orders (cdr x) d)))
)
)
(defun order (x d)
(cons (car x) (drink-list (cdr x) d))
)
(defun drink-list (x d)
(cond
((null x) ())
(t (cons (drink-count (car x) d) (drink-list (cdr x) d)))
)
)
(defun drink-count (x d)
(cond
((eq (car (cdr x)) d)
(cons (modify-count (car x) 1) (drink-count (cdr x) d)))
(t x)
)
)
(defun modify-count (x d)
(+ (parse-integer (subseq (write-to-string x) 0)) 1)
)

Resources