I found this lisp function while I was googling
(defun filter (lst items-to-filter)
(cond ((null lst) nil)
((member (car lst) items-to-filter) #1=(filter (cdr lst) items-to-filter))
(t (cons (car lst) #1#))))
It's just set difference, but this is the first time i see #1= and #1#, syntax. I think I understand what it means just by looking at the code, but I am not too sure. I think the #1= is used to label an expression so as not to retype it later when needed, one can just refer to it by #index#, in this case index=1. I was wondering if someone could shed some light on this. What are these constructs called, if there's a reference for them, and if they are widely used in modern lisp code. Thanks
To see it in written source code is very very unusual. Most of the time you see it in data. It is used to create or print shared data items in s-expressions. This way you can also read or print circular s-expressions.
You could use it for easier creation of repeated code, but usually one writes functions or macros for that. Functions have the advantage that they save code space - unless they are inlined.
CL-USER 3 > (pprint '(defun filter (lst items-to-filter)
(cond ((null lst) nil)
((member (car lst) items-to-filter)
#1=(filter (cdr lst) items-to-filter))
(t (cons (car lst) #1#)))))
(DEFUN FILTER (LST ITEMS-TO-FILTER)
(COND ((NULL LST) NIL)
((MEMBER (CAR LST) ITEMS-TO-FILTER)
(FILTER (CDR LST) ITEMS-TO-FILTER))
(T
(CONS (CAR LST) (FILTER (CDR LST) ITEMS-TO-FILTER)))))
As you see above the printer does not print it that way. Why is that?
There is a global variable *print-circle* which controls it. For above example it was set to NIL. Let's change that:
CL-USER 4 > (setf *print-circle* t)
T
CL-USER 5 > (pprint '(defun filter (lst items-to-filter)
(cond ((null lst) nil)
((member (car lst) items-to-filter)
#1=(filter (cdr lst) items-to-filter))
(t (cons (car lst) #1#)))))
(DEFUN FILTER (LST ITEMS-TO-FILTER)
(COND ((NULL LST) NIL)
((MEMBER (CAR LST) ITEMS-TO-FILTER)
#1=(FILTER (CDR LST) ITEMS-TO-FILTER))
(T
(CONS (CAR LST) #1#))))
So this shows that one can read and print such s-expressions in Common Lisp
Sharing some source code data structures is more common in computed code:
CL-USER 22 > (defmacro add-1-2-3 (n) `(,n 1 2 3))
ADD-1-2-3
CL-USER 23 > (walker:walk-form '(+ (add-1-2-3 4) (add-1-2-3 5)))
(+ (4 . #1=(1 2 3)) (5 . #1#))
Related
I want to define a function, which converts the elements of a list in to float.
Thats's my solution, which does not work:
(defun intofloat (list)
(cond
((null liste) nil)
((equal (first list) 'id)
(float (first list)))
(t (intofloat (rest list)))))
Maybe there is someone who could help me!
Thanks!
If you are able to use mapcar, this is truly trivial.
* (mapcar #'float '(1 2 3))
(1.0 2.0 3.0)
If you are not allowed to use mapcar, then you should break your problem down and redefine that function first.
(defun my-map (f lst)
(if (null lst)
nil
(let ((hd (car lst))
(tl (cdr lst)))
(cons (funcall f hd) (my-map f tl)))))
I'm trying to teach myself functional language thinking and have written a procedure that takes a list and returns a list with duplicates filtered out. This works, but the output list is sorted in the order in which the last instance of each duplicate item is found in the input list.
(define (inlist L n)
(cond
((null? L) #f)
((= (car L) n) #t)
(else (inlist (cdr L) n))
))
(define (uniquelist L)
(cond
((null? L) '())
((= 1 (length L)) L)
((inlist (cdr L) (car L)) (uniquelist (cdr L)))
(else (cons (car L) (uniquelist (cdr L))))
))
So..
(uniquelist '(1 1 2 3)) => (1 2 3)
...but...
(uniquelist '(1 2 3 1)) => (2 3 1)
Is there a simple alternative that maintains the order of the first instance of each duplicate?
The best way to solve this problem would be to use Racket's built-in remove-duplicates procedure. But of course, you want to implement the solution from scratch. Here's a way using idiomatic Racket, and notice that we can use member (another built-in function) in place of inlist:
(define (uniquelist L)
(let loop ([lst (reverse L)] [acc empty])
(cond [(empty? lst)
acc]
[(member (first lst) (rest lst))
(loop (rest lst) acc)]
[else
(loop (rest lst) (cons (first lst) acc))])))
Or we can write the same procedure using standard Scheme, as shown in SICP:
(define (uniquelist L)
(let loop ((lst (reverse L)) (acc '()))
(cond ((null? lst)
acc)
((member (car lst) (cdr lst))
(loop (cdr lst) acc))
(else
(loop (cdr lst) (cons (car lst) acc))))))
The above makes use of a named let for iteration, and shows how to write a tail-recursive implementation. It works as expected:
(uniquelist '(1 1 2 3))
=> '(1 2 3)
(uniquelist '(1 2 3 1))
=> '(1 2 3)
I have a requirement to return the last negative number in a list, using a recursive procedure. Right now I have a recursive procedure that returns all negative numbers in the list.
(define returnLastNeg
(lambda (lst)
(if (null? lst)
'()
(if (positive? (car lst))
(returnLastNeg (cdr lst))
(cons (car lst) (returnLastNeg (cdr lst)))))))
calling it with (returnLastNeg'(1 -2 -3 4 -5 6)) returns
Output:
'(-2 -3 -5)
I need it to only return -5 though. I tried to modify my procedure to check to see if the last element in the list is positive. If it is, I want to remove the last element and then call the procedure again. But when I do that I get an error (below)
Modified procedure:
(define returnLastNeg-modified
(lambda (lst)
(if (null? lst)
'()
(if (positive? (last lst))
(remove (last lst) (lst))
(cons (car lst) (returnLastNeg-modified (cdr lst)))))))
ERROR:
application: not a procedure;
expected a procedure that can be applied to arguments
given: '(1 -2 -3 4 -5 6)
arguments...: [none]
>
A simpler approach would be with a helper procedure (called "sub") in this example:
(define returnLastNeg
(lambda (lst)
(define sub
(lambda (lst last-neg)
(if (null? lst)
last-neg
(let ((c (car lst)))
(sub (cdr lst)
(if (negative? c) c last-neg))))))
(sub lst null)))
EDIT
Knowing that
(define <procedureName> (lambda (<params>) ... )
is the same as
(define (<procedureName> <params>) ... )
and reformatting a little, this becomes:
(define (returnLastNeg lst)
(define (sub lst last-neg)
(if (null? lst)
last-neg
(let ((c (car lst)))
(sub (cdr lst) (if (negative? c) c last-neg)))))
(sub lst null))
I hope it's clearer
last-neg gets set to null by the very last expression
the recursive call to sub has 2 parameters (split on 2 lines in the initial version, but newlines don't matter).
This is the same as the even shorter version
(define (returnLastNeg lst)
(let sub ((lst lst) (last-neg null))
(if (null? lst)
last-neg
(let ((c (car lst)))
(sub (cdr lst) (if (negative? c) c last-neg))))))
using a so-called "named let".
Can someone show me the error in this code please?
I want to generalize the member function to support nested lists. I need to search thing inside the nested list and return the rest of the list when I found thing. I don't really understand whats wrong with the code below.
(define (memberk thing lis)
(cond
((null? lis) #f)
((list? (car lis))
(cons (memberk thing (car lis))
(memberk thing (cdr lis))))
(else
(if (equal? (car lis) thing)
lis
(memberk thing (cdr lis))))))
Expexted output: (memberk 3 '(1 4 (3 1) 2)) = '((3 1) 2)
Actual output from the code above: '((3 1) . #f)
So how I see this you would like the top level cons that has the key found somewhere in car. I'm thinking something like:
(define (memberk needle lst)
(define (found? haystack)
(or (equal? needle haystack)
(and (pair? haystack)
(or (found? (car haystack))
(found? (cdr haystack))))))
(let loop ((lst lst))
(cond ((null? lst) #f)
((found? (car lst)) lst)
(else (loop (cdr lst))))))
(memberk '(a) '(a b (b (a) c) c d)) ; ==> ((b (a) c) c d)
Something like this?
It is a bit unclear what you want - since there is only one test case.
(define (memberk thing lis)
(cond
[(null? lis)
#f]
[(and (cons? (car lis)) (memberk thing (car lis)))
=> (λ (found) (cons found (cdr lis)))]
[(equal? (car lis) thing)
lis]
[else
(memberk thing (cdr lis))]))
So i started learning Lisp yesterday and started doing some problems.
Something I'm having a hard time doing is inserting/deleting atoms in a list while keeping the list the same ex: (delete 'b '(g a (b) l)) will give me (g a () l).
Also something I'm having trouble with is this problem.
I'm suppose to check if anywhere in the list the atom exist.
I traced through it and it says it returns T at one point, but then gets overriden by a nil.
Can you guys help :)?
I'm using (appear-anywhere 'a '((b c) g ((a))))
at the 4th function call it returns T but then becomes nil.
(defun appear-anywhere (a l)
(cond
((null l) nil)
((atom (car l))
(cond
((equal (car l) a) T)
(T (appear-anywhere a (cdr l)))))
(T (appear-anywhere a (car l))(appear-anywhere a (cdr l)))))
Let's look at one obvious problem:
(defun appear-anywhere (a l)
(cond
((null l) nil)
((atom (car l))
(cond
((equal (car l) a) T)
(T (appear-anywhere a (cdr l)))))
(T (appear-anywhere a (car l))(appear-anywhere a (cdr l)))))
Think about the last line of above.
Let's format it slightly differently.
(defun appear-anywhere (a l)
(cond
((null l) nil)
((atom (car l))
(cond
((equal (car l) a) T)
(T (appear-anywhere a (cdr l)))))
(T
(appear-anywhere a (car l))
(appear-anywhere a (cdr l)))))
The last three lines: So as a default (that's why the T is there) the last two forms will be computed. First the first one and then the second one. The value of the first form is never used or returned.
That's probably not what you want.
Currently your code just returns something when the value of a appears anywhere in the rest of the list. The first form is never really used.
Hint: What is the right logical connector?