Say X is a data expression in Scheme. I am wondering if there is a way to test if X is a list, and if so, my machine will output #t, otherwise it will output #f.
You can use the function list?:
(list? 42)
=> #f
(list? '(1 2 3))
=> #t
Related
(cons 1 (list 2 3)) returns a clojure.lang.cons. How can I convert it to clojure.lang.PersistentList?
Instead of calling cons and trying to convert the result, use conj:
(conj (list 2 3) 1)
=> (1 2 3)
(type (conj (list 2 3) 1))
=> clojure.lang.PersistentList
Clojure: how to convert cons to list
Don't!
Clojure is built upon extensible abstractions. One of the most important is the sequence.
I can think of no reason why you would want to convert a cons into a listor vice versa. They are both sequences and nothing much else. What you can do with one you can do with the other.
The above takes forward Leetwinski's comment on the question.
You can apply the contents of the returned sequence to the list function:
(apply list (cons 1 (list 2 3)))
=> (1 2 3)
(type *1)
=> clojure.lang.PersistentList
The easiest way would be to turn it into a vector. This data type works great in Clojure. In fact, when programming in Clojure, the most of the data is kept either in vectors or maps while lists are used for "code as data" (macro system).
In your case, the solution would be:
user=> (vec (cons 1 (list 2 3)))
[1 2 3]
I don't know such a case where you need a list exactly, not a vector or a seq. Because most of the functions operate on sequences but not strict collection types. The cons type should also work, I believe.
If you really need a list, you may use into function that is to convert collections' types. But please keep in mind that when dealing with a list, the order will be opposite:
user=> (into '() (cons 1 (list 2 3)))
(3 2 1)
So you need to reverse the input data first:
user=> (into '() (reverse (cons 1 (list 2 3))))
(1 2 3)
user=> (type (into '() (reverse (cons 1 (list 2 3)))))
clojure.lang.PersistentList
I was told butlast return all items in the list except the last item.
Here's a picture of my output when I try entering it manually:
The output was supposed to be '(1 2) because we removed the last item from the list.I found a documentation online on butlast but I'm not sure why the command isnt working for me: https://planet.racket-lang.org/package-source/cce/dracula.plt/6/0/planet-docs/manual/Lists.html#(def._((planet.dracula..scm.(cce._dracula..plt._6._0)._language)._butlast))
The documentation you have referenced belongs to the ACL2 programming language, where butlast is a well defined built-in procedure.
Racket, however, does not have a built-in procedure named butlast. You can verify this using Racket's official documentation, which can be found at: https://docs.racket-lang.org/. This is why you are getting the error butlast: undefined; when applying the function, because the procedure is neither built-in nor one that you have defined.
In Racket, the built-in drop-right procedure exists and works the same way as butlast. For example:
(drop-right '(1 2 3) 1)
=> '(1 2)
(drop-right '(1 2 3) 2)
=> '(1)
You can also manually create a butlast procedure as follows:
(define (butlast lst n)
(let ([len (length lst)])
(if (< len n)
"handle error"
(take lst (- len n)))))
For example:
(butlast '(1 2 3) 1)
=> '(1 2)
(butlast '(1 2 3) 2)
=> '(1)
In "Realm of Racket", the authors build a built-in function for educational purposes.
Their implementation of ormap is:
(define (my-ormap-book pred lst)
(cond [(empty? lst) #f]
[else (or (pred (first lst))
(my-ormap-book pred (rest lst)))]))
This code seems to work fine in many cases, like the unit-tests bellow show:
(require rackunit)
(check-equal? (my-ormap-book add1 '(3 4 5)) 4)
(check-equal? (my-ormap-book add1 '()) #f)
(check-equal? (my-ormap-book positive? '(1 2 a)) #t)
However, the real Ormap, like racket documentation shows - link - also works with two or more lists as inputs, like:
(check-equal? (ormap + '(1 2 3) '(4 5 6)) 5)
When doing that test with "Realm of Racket"s implementation, you get:
(check-equal? (my-ormap-book + '(1 2 3) '(4 5 6)) 5)
my-ormap-book: arity mismatch;
the expected number of arguments does not match the given number
expected: 2
given: 3
arguments...:
How do I solve this?
How do I make the "my-ormap-book" procedure pass on this test case?
You're right that the built-in ormap handles multiple lists. I think I would separate your question into two questions. First: how do you define a function that takes a variable number of arguments (known as 'variadic')? Second: how do you define a variadic ormap?
In answer to the first: there are a couple of ways of defining variadic functions. The simplest is to use a dot in the argument list, before the last argument:
(define (f a b . rest-args)
(first rest-args))
All arguments after the first two are bundled into a list with the given name.
This totally useless function accepts two or more arguments, and returns the third one (okay, pointless and broken).
In answer to your other question... well, this is a question of simultaneous recursion over multiple lists of the same length, and I think I'd refer you to section 23.1 of HtDP 2e.
So I am new to using Scheme/Guile and have an assignment where I must take 2 inputs; a simple variable and a list.
I then add the variable to each number in the list and print it out. I have got it to load but when I enter this:
(add 1 (1 2 3))
I get this error:
Backtrace:
39: 0* [add 1 ...
39: 1* [1 2 3]
standard inout:39:8: In expression (1 2 3):
standard input:39:8:wrong type to appy: 1
ABORT: (misc-error)
Here is the code that I currently have.
(define a (list a))
(define (add y a)
(define x 0)
(while (< x (length a))
(display (+ y (car a)))
(newline)
(set! a (cdr a))
(set! x (+ x 1))
)
)
My question is:
How do I get the list to work in the parameter? I have looked around online but havent found much to fix this problem.
Many thanks ahead of time for any help you can give me.
You're getting an error because (1 2 3) tells it to call the function 1 with two arguments, 2 and 3. To create a list containing 1, 2 and 3, use (list 1 2 3).
Do you really intend to write a procedure in such an imperative way? It looks not very Scheme-like. Evaluating your procedures in GNU Guile yields many error messages about unbound variables etc. set! is eval for beginners of Scheme ;) :) (SICP treats assignment extensively in chapter 3). You can do it much easier in functional style without the side-effects of set! and display.
If you are already aware about mapping and high-order functions, you could do something like this:
(define (add x)
(lambda (y) (+ x y)))
(map (add 1) (list 1 2 3))
===> (2 3 4)
If not, write a recursive procedure yourself:
(define (add-to-list x list)
(if (null? list)
'()
(cons (+ x (car list))
(add-to-list x (cdr list)))))
(add-to-list 1 '(1 2 3))
===> (2 3 4)
In order to learn thinking recursively, consult books like SICP, HTDP or "The litte Schemer".
Below is my code which takes a car element of a list(carVal) and an list(initialized to empty) as parameters. I want to append the element to the list but the same is not working.
(define populateValues
(lambda (carVal currVal)
(append currVal(list carVal ))
(display currVal)))
The display shows empty list all the time () . Can anyone help me understand why?
Well, there is append! as a primitive, which solves most of your problems, as noted already, Scheme tends to frown on mutation, it is possible, but typically avoided, so all procedures that mutate have a ! (called a bang) at their end.
Also, set! does not mutate data, it changes an environment, it makes a variable point to another thing, the original data is left unchanged.
Mutating data in Scheme is quite cumbersome, but, to give you my own implementation of append! to see how it is done:
(define (append! lst . lsts)
(if (not (null? lsts))
(if (null? (cdr lst))
(begin
(set-cdr! lst (car lsts))
(apply append! (car lsts) (cdr lsts)))
(apply append! (cdr lst) lsts))))
Note the use of set-cdr!, which is a true mutator, it only works on pairs, it mutates data in memory, unlike `set!'. If a pair is passed to a function and mutated with set-cdr! or set-car!, it is mutated every-where in the program.
This obeys the SRFI append! spec which says that it should be variadic and that it should return an undefined value, for instance.
(define l1 (list 1 2 3 4))
(define l2 (list 2 3 4))
(define l3 (list 3 1))
(append! l1 l2 l3)
l1
l2
l3
Which displays:
(1 2 3 4 2 3 4 3 1)
(2 3 4 3 1)
(3 1)
As visible, append! can take an infinite number of arguments and it mutates them all but the last.
Scheme might not be the ideal language for you though. The use of append! as said before is nonstandard, instead, append is preferred, which does not mutate and is called for its return value. Which I implement as such:
(define (append . lsts)
(cond
((null? lsts) '())
((null? (car lsts)) (apply append (cdr lsts)))
(else (cons (caar lsts) (apply append (cdar lsts) (cdr lsts))))))
> (append (list 1 2 3) (list 4 5 6) (list 'granny 'porn))
(1 2 3 4 5 6 granny porn)
Which shows a more familiar Scheme style in the absence of mutation, heavy use of recursion
and no use of sequencing.
Edit: If you just want to add some elements to a list and not per se join two though:
(define (extend l . xs)
(if (null? l)
xs
(cons (car l) (apply extend (cdr l) xs))))
(define (extend! l . xs)
(if (null? (cdr l))
(set-cdr! l xs)
(apply extend! (cdr l) xs)))
(extend '(0 1 2 3) 4 5 6)
(define list1 '(0 1 2 3))
(extend! list1 4 5 6)
list1
Which does what you expect
append creates a new list, it does not modify an existing one.
This is because in general, Scheme (and Racket in this case) is a language that prefers functional style.
You could get somewhat closer with a set! -- but even that will disappoint you since it will modify only the local binding.
Note that in Racket in particular, lists are immutable, so there's nothing that can change a list.
Furthermore, even if you could modify a list this way, it's a very inefficient way to accumulate long lists, since you have to repeatedly scan the whole list.
Finally, if you have issues at this level, then I strongly recommend going over HtDP
(append foo bar) returns the concatenation of foo and bar. It doesn't change either foo or bar.
You have to update the value of currVal with set!. Your example should have
(set! currVal (append currVal (list carVal))
(display currVal)
You really need to think about what exact functionality you are looking for
If you want to mutate a referenced list in place, then you have to do the equivalent of append! (as noted in the other answers). But that is dangerous, BECAUSE you may have other code that is counting on the list being immutable, and if you are going to do that, your procedure needs to have a ! in the end to flag that danger.
A cheap approximation to what you want to do, in a more functional style, is:
(define (populateValues carVal currVal)
(let ((ll (append currVal (list carVal))))
(display ll)
ll))
Note that it makes a new list, does the append, displays the result, and RETURNS the new list as a value. This is a useful debugging technique if you don't have access to the intermediate value: bind to a varible, display or log it, and then return it.