I hate using SO as a way to find simple functions, but I really can't find a function like this anywhere:
Given a list (1 2 3 4 5), I'd like the equivalent of (PHP's, Perl's, Python's)
$a = array(1, 2, 3, 4, 5);
$a[3] = 100;
Which results in (1 2 3 100 5)
Thanks!
You can write list-set! of Guile, like so:
(define a (list 1 2 3 4)) ; a is '(1 2 3 4)
(define (list-set! list k val)
(if (zero? k)
(set-car! list val)
(list-set! (cdr list) (- k 1) val)))
(list-set! a 2 100) ; a is '(1 2 100 4)
(Tried this in DrRacket.)
Using standard functions without any SRFI:
(set-car! (list-tail lst k) val)
I may be a bit late, but I have a different answer.
Part of the functional-program paradigm seems to be to try to avoid modifying data when possible. For efficiency reasons you may want to go with the other answers here. But otherwise, consider a non-mutating function such as this:
(define (list-with lst idx val)
(if (null? lst)
lst
(cons
(if (zero? idx)
val
(car lst))
(list-with (cdr lst) (- idx 1) val))))
Which passes the following tests:
(describe "a function that returns a list with a 'changed' value"
(it "can modify the edges of lists without having 1-off errors"
(expect (list-with '(1 2 3 4 5) 0 99) (be equal? '(99 2 3 4 5)))
(expect (list-with '(1 2 3 4 5) 4 99) (be equal? '(1 2 3 4 99))))
(it "has something to do with creating new lists"
(expect (list-with '(1 2 3 4 5) 2 99) (be equal? '(1 2 99 4 5))))
(it "doesnt just modify the contents of the original list"
(let ((a '(1 2 3 4 5)))
(list-with a 2 99)
(expect a (be equal? '(1 2 3 4 5))))))
(The code is written in Chicken Scheme and the tests with the "missbehave" library. But it seems like pretty portable Scheme.)
Guile has a built-in function called list-set! that does exactly what you want, using zero-based indices. For your example, you would have:
(define a '(1 2 3 4 5))
(list-set! a 3 100)
I don't think this is standard Scheme, however, and I don't know if it's really efficient. For a fixed-length array you should probably use a vector:
(define a2 #(1 2 3 4 5))
(vector-set! a2 3 100)
I'm pretty sure this is part of the language standard.
Related
The function has 1 parameter, an integer.
For example rot-left(2 '(1 2 3 4 5)) should return (3 4 5 1 2 ) and rot-right(2 '(1 2 3 4 5)) should return (5 4 1 2 3).
I've tried this... it doesn't work but what it's supposed to do is add the last n elements of a list to an empty list.
(defun rot_left (n l)
(if (zerop n)
'()
(append (last l)
rot-left ((- n 1) (cdr l)))))
I will give a solution assuming that, if the function rot-right should rotate the elements of the list from right to left, (rot-right 2 '(1 2 3 4 5)) should produce (4 5 1 2 3) and not (5 4 1 2 3).
Then, assuming that this interpretation is correct, the functions can be written only by means of primitive operators in Common Lisp, without the use of iteration or recursion:
(defun rot-left(n l)
(append (nthcdr n l) (butlast l (- (length l) n))))
(defun rot-right(n l)
(rot-left (- (length l) n) l))
(defvar a '(1 2 3 4 5))
(rot-left 2 a) ; produces (3 4 5 1 2)
(rot-right 2 a) ; produces (4 5 1 2 3)
Is there anything which acts as the opposite of list-ref, where instead of selecting certain values to add to a list, it'll take values away from a list?
I basically want to do the following
(list 1 2 3 4 5 6 7) (list 3 6 7) -> (list 1 2 4 5)
Where the values in list two get deleted from list one. (preferred)
Since I will always start with a list that goes from 1 to n,
the second list could also represent the location/position where a number on list 1 should be deleted. (less preferred)
I'm trying to create a code which will manipulate other functions to come up with these lists, so please be clear where each list is 'mentioned' in the code, as I sometimes get confused if people use x y and z and so forth with multiple lambda, local definitions, etc.
I have something here which does the opposite of what I want and I've been trying to alter it so instead of outputting the elements of x that are on y, it gives the elements of x which are NOT on y.
(define (selection x y)
(filter (lambda (e2)
(ormap (lambda (e1) (equal? e1 e2))
y))
x))
example:
(list 1 2 3 4 5 6 7 8 9 10)
(list 2 4 6 8 10))
-> (list 2 4 6 8 10))
Anybody have any ideas on how to change the output to what I need?
It sounds like you're using lists as sets. You could instead use Racket sets, and use the set-subtract function:
#lang racket
(set-subtract (set 1 2 3 4 5 6 7)
(set 3 6 7))
;; => (set 1 2 4 5)
remove will do the trick I guess.
> (remove* (list 1 2) (list 1 2 3 2 4 5 2))
'(3 4 5)
You can read the doc here.
Here's a simple recursive function that achieves what you want:
(define remove-list-from-list (lambda (list remlist)
(cond
[(null? list) '()]
[(member (car list) remlist) (remove-list-from-list (cdr list) remlist)]
[else (cons (car list) (remove-list-from-list (cdr list) remlist))])))
Now you can use it like so:
> (remove-list-from-list (list 1 2 3 4 5 6 7) (list 3 6 7))
'(1 2 4 5)
I've been getting a strange behavior when invoking a destructive definition receiving as argument a local variable whose type is a list created with a quote.
Destructive function:
(defun insert-at-pos (pos list elem)
(if (= pos 0)
(cons elem list)
(let ((aux-list (nthcdr (1- pos) list)))
(setf (rest aux-list) (cons elem (rest aux-list)))
list)))
WRONG: Local variable is a list created with the special operator quote.
(defun test ()
(let ((l '(1 2 3)))
(print l)
(insert-at-pos 2 l 4)
(print l)))
> (test)
(1 2 3)
(1 2 4 3)
(1 2 4 3)
> (test)
(1 2 4 3)
(1 2 4 4 3)
(1 2 4 4 3)
> (test)
(1 2 4 4 3)
(1 2 4 4 4 3)
(1 2 4 4 4 3)
CORRECT: Local variable is a list created with function list.
(defun test2 ()
(let ((l (list 1 2 3)))
(print l)
(insert-at-pos 2 l 4)
(print l)))
or
(defun test2 ()
(let ((l '(1 2 3)))
(print l)
(setf l (cons (first l) (cons (second l) (cons 4 (nthcdr 2 l)))))
(print l)))
> (test2)
(1 2 3)
(1 2 4 3)
(1 2 4 3)
> (test2)
(1 2 3)
(1 2 4 3)
(1 2 4 3)
> (test2)
(1 2 3)
(1 2 4 3)
(1 2 4 3)
Does someone know the reason of this strange behaviour?
If you quote data in a function, then it is literal data. The effects of destructively modifying such literal data are undefined in the Common Lisp standard. In your example all function invocations share the same literal data and the implementation does not warn you that you are changing it. That's what most implementations do. But it would also possible to imagine an implementation which puts all code (and its literal data) into a read-only part of the memory.
You can get funky effects with this.
If you want to destructively modify a list without running into potential problems, then you need to create a fresh copy at runtime. For example by calling LIST or COPY-LIST. LIST will return a fresh consed list.
There are similar pitfalls. For example imagine a file with these definitions:
(defvar *foo* '(1 2 3 4 5 6 ... 10000))
(defvar *foo* '(0 1 2 3 4 5 6 ... 10000))
If you compile such a file with the file compiler, the compiler is allowed to create a compiled file, where the two variables share literal data - saving space. If you would change an element in either list, both might be changed.
I need to create a Scheme function that receives a list and a desired new size, the function then extends the list size by using the same list values. For example:
'(1 2 3) to size 6 will turn to '(1 2 3 1 2 3)
'(1 2) to size 5 will turn to '(1 2 1 2 1)
'(4 5 6 1) to size 7 will turn to '(4 5 6 1 4 5 6)
The new length function parameter can be equal or bigger than the current list size.
You can use SRFI 1 function circular-list (alongside Racket's built-in take) to do this:
(require srfi/1)
(define (take-circular lst n)
(take (apply circular-list lst) n))
If you want to avoid using SRFI 1, another method works like this:
(define (take-circular lst n)
(let ((size (length lst)))
(if (> n size)
(append lst (take-circular lst (- n size)))
(take lst n))))
Say I want to take the first item of the lists '(4 3 1) '(5 6 8)
I want something like this
(first '(4 3 1) '(5 6 8))
should return me the first item
(4 3 1)
as result. Is there something like this in scheme build-in function I can call ?
car doesn't work, as it only returns me the first item inside 1 list
list-ref doesn't work, same reason above, returns me 1 item inside the list
How can I do that? if I need to write it myself this first function ?
You can use the list-ref procedure to get an element from a list, using its index, for example:
(let ((l '((4 3 1) (5 6 8))))
(list-ref l 0)) ; get the element at index 0
However if you only want the first element, you can use car:
(let ((l '((4 3 1) (5 6 8))))
(car l))
Check the snippet running here.
You can use "." in function definition to take arbitrary number of arguments.
(define (first . args) (car args))
(first '(4 3 1) '(5 6 8)) ;; => (4 3 1)
You're trying too hard:
> (define (first a b) a)
> (first '(1 2 3) '(4 5 6))
(1 2 3)
It's been a while since I used scheme, but wouldn't you need to have the lists in their own list first
(first (list '(4 3 1) '(5 6 8)))