I am trying to understand why I am getting this error, as I am fairly new to lisp. I want to create a function that takes a number n from the user and creates a list of up to five numbers based on that number. The function then takes the first number in the list and sends it to the end of the list.
Example
> (my_func 1)
> (2 3 4 5 1)
This is what I have so far, I am able to get the function to return a list, however I am unsure on how to send the first element to the back of the list.
(defun my_rotate (y)
(labels ((var (list) (loop for i from y to list collect i)))
(var 5) (append (rest list)(list (first list))))
)
Let's start by formatting the code "properly", this makes it much easier to see the structure of the code:
(defun my_rotate (y)
(labels ((var (list)
(loop for i from y to list collect i)))
(var 5)
(append (rest list) ;; This form is not in a lexical context
(list (first list))))) ;; where list is bound
We can clearly see that the reason we're getting an error is because list simply isn't bound, so the local function var is not actually useful (it's called, but throws the value away, since it has no side effects, it could in theory be optimized away).
The simplest fix is to move the append call outside the labels, drop the labels form, then change the name of the input argument to list.
Your question isn't entirely clear to me, but if I understand correctly, something like this should work:
(defun my_rotate (y)
(let ((list (loop for i from y to (+ 4 y) collect i))) ;; create the list you want
(append (rest list) (subseq list 0 1)))) ;; move first element to end
Related
I am brand new to scheme and trying to create a real simple interpreter as a starting off point.
Given two lists, one containing variables in the form:
(x y z)
and a second containing their values:
(1 2 3)
how can i combine them to make one list that looks like this:
((x 1) (y 2) (z 3))
I will then append this to my original environment. I'm struggling with just getting used to these simple operations with this type of programming language. Thanks.
Use map.
(map list '(x y z) '(1 2 3))
I'm currently a university student using the Begining Student environment of the Dr. Racket. So there might be some differences in terms of the notations and syntax.
(define (combine-list list1 list2)
(cond
;; Using (cond) function to create a recursion
[(or (empty? list1) (empty? list2)) empty]
;; The base case: when to stop the recursion
;; It would be written in the first line cuz it will be evaluated first
[else (cons (list (first list1) (first list2))
;; The recursive case: construct one typical element of the resulting list
(combine-list (rest list1) (rest list2)))]))
;; Do the recursive case on all of the rest of the lists
I haven't learned what (map) does,but in my opinion, the function (combine-list) has the same behaviour as (map) if the inputs are two arguments, like what #soegaard did in the answer.
I am new to Scheme and not currently using (Racket version), therefore I do not have such built in functions as filter and etc.
My task for now is to get elements out of my inputted list, and take out of it only those that are above my MinValue and below my MaxValue
In my "lst" variable for example I have (2 4 1 6 5 4 7 3)
In my "MinValue" I have 2
In my MaxValue I have 5
So that now after I apply something similar like
(remove (< # minVal) lst)
It technically should give remove and left out:
(2 4 4 3)
But I am getting the error:
READ from #<INPUT CONCATENATED-STREAM #<INPUT STRING-INPUT-STREAM> #<IO TERMINAL-STREAM>>: objects printed as # in view of *PRINT-LEVEL* cannot be read back in
Main questions:
Does Scheme has a specific defined variable like # that is iterating through the list when remove/remove-if functions are used, so I can use it?
Is there is a way to get this to work in such way:
(remove (< # minVal) lst)
Thanks!
tag "homework" should be there, but I cannot create it yet
Almost any Scheme I know of includes a filter procedure, it's not specific to Racket, you should be able to use it (remove is not the right tool for this job).
Simply pass a lambda that receives each element in turn and you can set any condition for determining which elements go in the output list:
(filter (lambda (e) (and (>= e 2) (< e 5)))
'(2 4 1 6 5 4 7 3))
=> '(2 4 4 3)
There is no # variable that iterates through a list and gives you each element in turn, to do that you have to explicitly traverse the list using recursion, or use one of the built-in procedures that expect a list and a lambda - the lambda's parameter represents each of the elements.
If for some reason you are not allowed to use filter, it's easy to implement it from scratch, and again notice that we don't need to use remove, and that pred gets called with each of the elements:
(define (filter pred lst)
(cond ((null? lst) '())
((pred (car lst))
(cons (car lst) (filter pred (cdr lst))))
(else (filter pred (cdr lst)))))
This is extremely easy if I can use an array in imperative language or map (tree-structure) in C++ for example. In scheme, I have no idea how to start this idea? Can anyone help me on this?
Thanks,
Your question wasn't very specific about what's being counted. I will presume you want to create some sort of frequency table of the elements. There are several ways to go about this. (If you're using Racket, scroll down to the bottom for my preferred solution.)
Portable, pure-functional, but verbose and slow
This approach uses an association list (alist) to hold the elements and their counts. For each item in the incoming list, it looks up the item in the alist, and increments the value of it exists, or initialises it to 1 if it doesn't.
(define (bagify lst)
(define (exclude alist key)
(fold (lambda (ass result)
(if (equal? (car ass) key)
result
(cons ass result)))
'() alist))
(fold (lambda (key bag)
(cond ((assoc key bag)
=> (lambda (old)
(let ((new (cons key (+ (cdr old) 1))))
(cons new (exclude bag key)))))
(else (let ((new (cons key 1)))
(cons new bag)))))
'() lst))
The incrementing is the interesting part. In order to be pure-functional, we can't actually change any element of the alist, but instead have to exclude the association being changed, then add that association (with the new value) to the result. For example, if you had the following alist:
((foo . 1) (bar . 2) (baz . 2))
and wanted to add 1 to baz's value, you create a new alist that excludes baz:
((foo . 1) (bar . 2))
then add baz's new value back on:
((baz . 3) (foo . 1) (bar . 2))
The second step is what the exclude function does, and is probably the most complicated part of the function.
Portable, succinct, fast, but non-functional
A much more straightforward way is to use a hash table (from SRFI 69), then update it piecemeal for each element of the list. Since we're updating the hash table directly, it's not pure-functional.
(define (bagify lst)
(let ((ht (make-hash-table)))
(define (process key)
(hash-table-update/default! ht key (lambda (x) (+ x 1)) 0))
(for-each process lst)
(hash-table->alist ht)))
Pure-functional, succinct, fast, but non-portable
This approach uses Racket-specific hash tables (which are different from SRFI 69's ones), which do support a pure-functional workflow. As another benefit, this version is also the most succinct of the three.
(define (bagify lst)
(foldl (lambda (key ht)
(hash-update ht key add1 0))
#hash() lst))
You can even use a for comprehension for this:
(define (bagify lst)
(for/fold ((ht #hash()))
((key (in-list lst)))
(hash-update ht key add1 0)))
This is more a sign of the shortcomings of the portable SRFI 69 hashing library, than any particular failing of Scheme for doing pure-functional tasks. With the right library, this task can be implemented easily and functionally.
In Racket, you could do
(count even? '(1 2 3 4))
But more seriously, doing this with lists in Scheme is much easier that what you mention. A list is either empty, or a pair holding the first item and the rest. Follow that definition in code and you'll get it to "write itself out".
Here's a hint for a start, based on HtDP (which is a good book to go through to learn about these things). Start with just the function "header" -- it should receive a predicate and a list:
(define (count what list)
...)
Add the types for the inputs -- what is some value, and list is a list of stuff:
;; count : Any List -> Int
(define (count what list)
...)
Now, given the type of list, and the definition of list as either an empty list or a pair of two things, we need to check which kind of list it is:
;; count : Any List -> Int
(define (count what list)
(cond [(null? list) ...]
[else ...]))
The first case should be obvious: how many what items are in the empty list?
For the second case, you know that it's a non-empty list, therefore you have two pieces of information: its head (which you get using first or car) and its tail (which you get with rest or cdr):
;; count : Any List -> Int
(define (count what list)
(cond [(null? list) ...]
[else ... (first list) ...
... (rest list) ...]))
All you need now is to figure out how to combine these two pieces of information to get the code. One last bit of information that makes it very straightforward is: since the tail of a (non-empty) list is itself a list, then you can use count to count stuff in it. Therefore, you can further conclude that you should use (count what (rest list)) in there.
In functional programming languages like Scheme you have to think a bit differently and exploit the way lists are being constructed. Instead of iterating over a list by incrementing an index, you go through the list recursively. You can remove the head of the list with car (single element), you can get the tail with cdr (a list itself) and you can glue together a head and its tail with cons. The outline of your function would be like this:
You have to "hand-down" the element you're searching for and the current count to each call of the function
If you hit the empty list, you're done with the list an you can output the result
If the car of the list equals the element you're looking for, call the function recursively with the cdr of the list and the counter + 1
If not, call the function recursively with the cdr of the list and the same counter value as before
In Scheme you generally use association lists as an O(n) poor-man's hashtable/dictionary. The only remaining issue for you would be how to update the associated element.
I need some help understanding the syntax on how to append a number into a list, i'm doing this from user input via the console so this elements have to be entered in recursively. So for ever number that is entered, the list must grow for each element (only numbers) added.
Here is the code I am working with, the problem lies in the second conditional. Right now this works but only creates an empty list of each number I put in, so the results would be
>12
>202
>30
()()()
zero input: stopping list
(define (inputlist)
(let ((applist list))
(let ((inpt (read)))
(cond
((= inpt 0)(newline) (display "zero input: stopping list"))
;;OLD((number? inpt) (cons inpt applist) (display (applist))(inputlist))
((number? inpt) (append (applist)(list inpt)) (display (applist))(inputlist))
(else
display "Not a number")))))
I understand why cons is not doing what I need it to be doing, but is there a similar functionality to appending each read in element to a pre-existing list?
EDIT: I've gotten closer what i've needed to do but still with the same results, i am now appending upon my applist with a list i create via every input, though it is still resulting in as many empty lists as I input.
SECOND EDIT: I've realized why it's printing multiple ()'s is because it's being called off the stack when 0 is entered, so i'm sure it's not working because the appending isn't working as intended, i've displayed the applist on the 0 conditional and it returns one null list.
A simple way to append an element to the end of a list while looping would be to do call append and update the reference to the list afterwards:
(set! applist (append applist (list inpt)))
Notice that you have several misplaced parentheses - in your code some are missing, some are unnecessary. In Scheme () means function application, and you have to be careful where you put those brackets.
Also, be aware that append doesn't modify the initial list, it creates a new one, and if you need to refer to it, you have to store it somewhere (that's why I'm doing a set! above).
There are more serious errors with you logic. The conditions are in the wrong order (you have to test if the input is a number before asking if it's zero), and you forgot to loop if something other than a number is entered. Also, if we pass along the list as a parameter to the loop, we won't have to do an ugly set!. Try this instead, it's closer to what you were aiming for:
(define (inputlist)
(let loop ((applist '()))
(let ((inpt (read)))
(cond ((not (number? inpt))
(display "not a number")
(newline)
(loop applist))
((zero? inpt)
(display "zero input: stopping list"))
(else
(let ((new-applist (append applist (list inpt))))
(display new-applist)
(newline)
(loop new-applist)))))))
As mentioned in the comments, bear in mind that appending at the end of a list inside a loop in general is a bad idea. It's ok for learning purposes, but in real-life code, you'd cons at the head of the list and reverse it at the end - this is more efficient.
Note that (cons x xs) where x is an element and xs is a list produces a new list which has x as its first element.
Here is one way to use cons to add an element in the end of a list:
Example:
Add 4 to (1 2 3)
1. Reverse the list: (3 2 1)
2. Add 4 to the front: (4 3 2 1)
3. Reverse: (1 2 3 4)
> (reverse (cons 4 (reverse (list 1 2 3)))
(1 2 3 4)
A function that uses this principle:
(define (cons-to-back x xs)
(reverse (cons x (reverse xs))))
> (cons-to-back 4 (list 1 2 3))
(1 2 3 4)
An alternative is to use append which appends the elements of two lists:
> (append '(1 2 3) '(4 5 6))
(1 2 3 4 5 6)
All we need to do, is to the the element into a list before using append:
> (append '(1 2 3) (list 4))
'(1 2 3 4)
Alternative definition of cons-to-back:
(define (cons-to-back x xs)
(append xs (list x)))
I'm newbie in Scheme and find out that if I change a list with set-car!/set-cdr! (even locally) the parent list is modified too. This is an example what I mean:
(define my-list '(1 2 3 4 5)) ; Original list
(define (function list) ; Some example function
(let ((copy list))
(set-car! copy 'new)
(display copy)
)
(function my-list); will display (new 2 3 4 5)
my-list; but the original is changed "forever" and will be also '(new 2 3 4 5)
My question is:
Is there a way to make a copy of the original list and work only on it, so at the end the original not to be changed?
Your code (let ((copy list)) allows list to be accessed through the name copy. So when you set-car! copy, you are actually set-car!'ing the original list.
The phenomenon of mutation in lisp like languages is a little confusing at first.
Mutation is to be avoided usually, for the reasons you have discovered. Parts of lists and things a floating around. This is because internally each node in a list has two parts - the car is it's value which may point to another list, and it's cdr is the part that follows it - usually this is a lit of things similar to the value in car.
This solves your problem using SRFI1's list-copy function
(let ((copy (list-copy list)))
Here is one way to copy a list (make a new list). This code is not really complete. When we look at it internally it adds pieces of a list in each recursive call. Where do the pieces of each new list-section come from? The cdr is generated with the call (list-copy (cdr list)), while the car is simply taken - not copied! - from the other list.
(define (list-copy list)
(if (null? list) '() (cons (car list) (list-copy (cdr list)))))
The result for you when experimenting, was that the car's of your list copy where borrowed from my-list.
Here is a more proper version:
(define (full-copy list)
(if (null? list)
'()
(if (list? list)
(cons (full-copy (car list)) (full-copy (cdr list)))
list)))
Only the code for the car has changed. Now, the car is reconstructed to. The only parts that are borrowed are the numbers (so this copy is not okay when the numbers are instead something more special). I'm not sure how the srfi1 version works.
The let statement only ever binds one identifier to an object - the object is not copied, you simply have another way to access it. So any changes (use of mutation, as in functions that end in "!") will affect both.
I suggest that when you're learning Scheme or Racket, you avoid all the ! functions such as set-car!, set-cdr!, and set!.
Instead of mutating things, try to think in terms of creating a new thing from the old thing(s).
For instance if you have a list and want something new at the start:
;; Return a new list with `x` replacing the head of the list `xs`.
(define (replace-head xs x) ; list? any? -> list?
(cons x (cdr xs)))
;; Using it:
(replace-head '(1 2 3 4 5) 100)
; => '(100 2 3 4 5)
p.s. A version of replace-head that can handle xs being empty could be:
(define (replace-head xs x) ; list? any? -> list?
(cond [(empty? xs) (list x)]
[else (cons x (cdr xs))]))
(replace-head '(1 2 3 4 5) 100)
; => '(100 2 3 4 5)
(replace-head '() 100)
; => '(100)
You also might find it helpful to look at How to Design Programs, for examples of good ways to design and think in Scheme or Racket.