I'm having trouble reading output from dr racket. By default it displays lists using mcons. For example, sicp exercise 2.32 produces:
> (subsets (list 1 2 3))
(mcons
(mcons
'()
(mcons
(mcons 3 '())
(mcons
(mcons 2 '())
(mcons
(mcons 2 (mcons 3 '()))
(mcons
(mcons 1 '())
(mcons
(mcons 1 (mcons 3 '()))
(mcons
(mcons 1 (mcons 2 '()))
(mcons (mcons 1 (mcons 2 (mcons 3 '()))) '()))))))))
'())
I'm having trouble reading this. Is there a way to make the output look like:
(() (3) (2) (2 3) (1) (1 3) (1 2) (1 2 3))
Thanks!
Do you know what language are you using in your #lang line? The rest of the instructions below are assuming that you're using a #lang line.
If you are in #lang r5rs and you display or write the values, you should see the output you expect.
> (define p (list 1 2))
> (display p)
(1 2)
> (set-car! p 'one)
> (display p)
(one 2)
If you just type the values bare in Interactions, DrRacket will print them, and that uses the representation you're seeing. In DrRacket, you can customize the way that values print. Here's the process, step-by-step:
Go to the Language menu, and select Choose Language. You should see the language dialog pop up.
If the button on the lower left says Show Details, click it, and the dialog window should expand to include customizations.
Look for the Output Style option. There should be four choices: Constructor, Quasiquote, write, and print. Select write style, and then press Ok to confirm the customization.
Once you do this, then:
> (display (list 1 2))
(1 2)
> (write (list 1 2))
(1 2)
> (list 1 2)
{1 2}
It will still print slightly differently than you expect, using curly braces, because it's trying to notate that the list structure is mutable.
If this bothers you, we can fix that. Add the following line near the top of your program (but after the #lang line).
(#%require r5rs/init)
This line pulls in a Racket-specific module called r5rs/init that tries to improve r5rs compliance; in particular, the braces should finally print as round ones for mutable pairs.
> (display (list 1 2))
(1 2)
> (write (list 1 2))
(1 2)
> (list 1 2)
(1 2)
Related
i would like to visit all the cons cells in a list and perform some action on them (including such things as setcar). is there an idiomatic way of doing this?
i can, i think, do something like this
(progn
(setq a (list 1 2 3 4 5 6))
(setq okay a)
(while okay
(if (eq (car okay) 3)
(setcar okay 22))
(setq okay (cdr okay))))
(where the if expression is my "application logic", say.)
but, if there's a terser way of doing this, i'd be interested in hearing about it.
If you want to mutate the cars of the list, then in recent emacsen the likely think you want is cl-mapl, which maps a function over successive tails of the list. This is essentially Common Lisp's mapl function: CL has
maplist which maps a function over tails and returns a new list of the values of the function, so (maplist (lambda (e) e) '(1 2 3)) is ((1 2 3) (2 3) (3));
mapl which is like maplist but returns the original list.
elisp (courtesy of some now-standard library) now has both cl-mapl and cl-maplist.
So:
> (let ((y (list 1 2 3 4 5 6 7)))
(cl-mapl (lambda (tail)
(rplaca tail 0))
y)
y)
(0 0 0 0 0 0 0)
or
> (let ((y (list 1 2 3 4 5 6 7)))
(cl-mapl (lambda (tail)
(rplaca tail (if (cdr tail) (cadr tail) 'fish)))
y)
y)
(2 3 4 5 6 7 fish)
(In neither of these cases do you need to make sure that y is returned: I just did it to make it clear that y is being destructively modified by this.)
(setq a (mapcar (lambda (x) (if (equal x 3) 22 x)) a))
That sets the value of variable a to the result of changing any members of a that are 3 to 22.
Choose the equality operator you want, equal, eql, or =, depending on whether you know that either all list members are numbers (use =) or you know that they are either numbers or you want to test object equality otherwise, (use eql), or you don't know what they might be (use equal).
You haven't indicated any need to do list-structure modification (setcar). It appears that all you care about is for a to be a list as I described.
I'm new to Racket and I'm trying to use call/cc. When I put the following code in the definitions window
of DrRacket, run it, and type (saved-k 0) in the interactions window, I get two of 3 printed.
#lang racket ; the definitions window
(define saved-k #f)
(define (f)
(+ 1
(call/cc (λ (k) (set! saved-k k) 0))))
(+ 1 (+ 1 (f)))
; the interactions window
3
> (saved-k 0)
3
3
My understanding is that the saved continuation should be (+ 1 (+ 1 (+ 1 ?)))
where ? is the hole. Why are there two results printed?
When I try all of those things in the interactions window, everything looks normal.
; the interactions window
> (define saved-k #f)
> (define (f)
(+ 1
(call/cc (λ (k) (set! saved-k k) 0))))
> (+ 1 (+ 1 (f)))
3
> (saved-k 0)
3
Racket prints values at the top level. For example, running
#lang racket
1
2
will print 1 and 2.
How is this done? Well, when the program is run, it expands the code to something like:
(module test racket
(#%module-begin
(#%app call-with-values (lambda () '1) print-values)
(#%app call-with-values (lambda () '2) print-values)))
where print-values is responsible for the printing.
What happened in your program is that when the continuation is captured, it includes the print-values frame. That's why when you invoke the continuation, you see the double printing. One from print-values. Another from the evaluation result.
But when you try them all in the interactive window, there's no print-values, so there's no double printing.
Example, I write a Racket script:
; filename: hello.rkt
#lang racket/base
(displayln "hello")
(+ 1 1)
and execute it:
$ racket hello.rkt
output is:
hello
2
I don't want it to print the number '2', how to disable result of the any S-expression value output?
You could use void to discard values, and begin to group several expressions together. E.g.
(void (begin (+ 1 1) (+ 2 2) (+ 3 3)))
This prints nothing.
Some output from the CLISP REPL:
[1]> (list 'list 1 2 3)
(LIST 1 2 3)
[2]> (list 'list '(1 2 3))
(LIST (1 2 3))
[3]> (list 'quote 1 2 3)
(QUOTE 1 2 3)
[4]> (list 'quote '(1 2 3))
'(1 2 3)
The first three, I understand exactly what's going on: The list function is passed a symbol ('list or 'quote) and so the result is a list that begins with the list or quote symbol. It's the fourth that confuses me. Why doesn't it return (QUOTE (1 2 3))?
I realise that if you enter (QUOTE '(1 2 3)) into the REPL, you get '(1 2 3) back, so the expression are equivalent in that sense. But (LIST 1 2 3) is equivalent to (1 2 3), and yet the first expression doesn't return that.
It seems inconsitent that (list 'quote 1 2 3) returns a list with the first item being a quote symbol, but (list 'quote (1 2 3)) returns a quoted list. Especially since expressions like (list 'list ...) seem to always return a list beginning with the symbol - so far, at least, quote is the only 'special case' like this.
It's not the easiest question to articulate, so I'm hoping I've managed to get my confusion across. Can anyone explain why quote gets treated in this seemingly-unique way?
'something is the same as (quote something) for the lisp reader. Even when nested it will be the case. The next expressions I will double quote so that after evaluation one of the quotes are still in there.
When printing the implementations can choose what to output where there are several possible representations, so some implementations would print the evaluation of ''something as
(quote something) while others may use the abbreviation 'something.
'(quote 1 2 3) cannot be abbreviated since a quoted form only has one argument. Thus here both lisp systems would print (quote 1 2 3).
Here is a way to look at your last expression:
(let ((data (list 'quote '(1 2 3))))
(format nil
"whole thing: ~a first element: ~a second-element: ~a"
data
(car data)
(cadr data)))
This will either evaluate to "whole thing: '(1 2 3) first element: QUOTE second-element: (1 2 3)" or "whole thing: (QUOTE (1 2 3)) first element: QUOTE second-element: (1 2 3)".
Since the printer never sees if the input is abbreviated and the data has the same structure in memory the output is never affected by how you input the data. Thus (quote (quote (1 2 3))) will print the same as ''(1 2 3).
You have the same behaviour with cons cells but the standard dictates how the rules are. (cons 1 (cons 2 (cons 3 '()))) would be (1 . (2 . (3 . ()))) but is actually just printed (1 2 3) However if you (cons 1 2) you get (1 . 2) showing that print treats the output differently based on the cdr. However the reader can read any of these and they will all print the same eg. '(1 . (2 . (3 . ()))) ==> (1 2 3) and (+ . (2 . ( 3 . ()))) ; ==> 5
Numbers can have as many visual forms as there are bases below the number in question.
(let ((*print-base* 16))
(print 255)) ; prints FF (255 in hexadecimal)
list does not have any abbreviation or specialness in Lisp. It's not even a primitive function but it's very helpful as it removes the inconvenience of having to cons by hand everytime. It can be defined like this:
(defun my-list (&rest lst)
lst)
(my-list 1 2 3 4) ; ==> (1 2 3 4)
Note that a REPL (the READ-EVAL-PRINT-LOOP) does three things:
reading using the function READ
evaluating using the function EVAL
and printing the result using something like the function PRINT
To understand what is going on you have to look at all three functions.
Let's look at the third form:
(list 'quote 1 2 3)
This is read as a list of five elements:
LIST
(QUOTE QUOTE)
1
2
3
EVAL then evaluates the arguments, and calls the function list with the four results and returns a new result, a list of four elements:
QUOTE
1
2
3
PRINT then takes this list and writes it as: (QUOTE 1 2 3). There is no abbreviated way to print it.
Let's look at the fourth form:
(list 'quote '(1 2 3))
This is read as a list of three elements:
LIST
(QUOTE QUOTE)
(QUOTE (1 2 3))
eval calls list with two arguments:
QUOTE
(1 2 3)
eval then returns a list of length two:
QUOTE
(1 2 3)
print now can print this list in two different ways:
(QUOTE (1 2 3)) or the abbreviated form '(1 2 3). Here a quote character is in front of a single expression.
Your implementation used the first version.
What's the equivalent of foldr, foldl in Emacs Lisp?
If you
(require 'cl)
then you can use the Common Lisp function reduce. Pass the keyword argument :from-end t for foldr.
ELISP> (reduce #'list '(1 2 3 4))
(((1 2) 3) 4)
ELISP> (reduce #'list '(1 2 3 4) :from-end t)
(1 (2 (3 4)))
Since Emacs-24.3 we recommend the use of cl-lib over cl (which is planned for removal in some distant future), so it would be:
(require 'cl-lib)
(cl-reduce #'+ '(1 2 3 4))
and since Emacs-25, you can also use the seq package for that:
(require 'seq)
(seq-reduce #'+ '(1 2 3 4) 0)
Common Lisp library provides plenty of sequence functions like mapping, filtering, folding, searching and even sorting. CL library is shipped with Emacs by default, so you should stick to it. I however really like dash.el library, because it provides enormous amounts of functions for list and tree manipulations. It also supports anaphoric macros and encourages functional programming, which makes code concise and elegant.
Haskell's folds correspond with dash.el folds:
foldl with -reduce-from
foldr with -reduce-r-from
foldl1 with -reduce
foldr1 with -reduce-r
Sum of a range 1 to 10 using folds might look like in this in Haskell and dash.el:
foldl (+) 0 [1..10] -- Haskell
(-reduce-from '+ 0 (number-sequence 1 10)) ; Elisp
You probably know, that folds are very general, and it is possible to implement maps and filters via folds. For example, to increment every element by 2, Haskell's currying and sections would allow for terse code, but in Elisp you would usually write verbose throwaway lambdas like that:
foldr ((:) . (+2)) [] [1..10] -- Haskell
(-reduce-r-from (lambda (x acc) (cons (+ x 2) acc)) '() (number-sequence 1 10)) ; Elisp
Guess what, it isn't necessary in dash.el with anaphoric macros, which allow special syntax by exposing variables of a lambda as shortcuts, like it and acc in folds. Anaphoric functions start with 2 dashes instead of 1:
(--reduce-r-from (cons (+ it 2) acc) '() (number-sequence 1 10))
There are plenty fold-like functions in dash.el:
;; Count elements matching a predicate
(-count 'evenp '(1 2 3 4 5)) ; 2
;; Add/multiply elements of a list together
(-sum '(1 2 3 4 5)) ; 15
(-product '(1 2 3 4 5)) ; 120
;; Find the smallest and largest element
(-min '(3 1 -1 2 4)) ; -1
(-max '(-10 0 10 5)) ; 10
;; Find smallest/largest with a custom rule (anaphoric versions)
(--min-by (> (length it) (length other)) '((1 2 3) (4 5) (6))) ; (6)
(--max-by (> (length it) (length other)) '((1 2 3) (4 5) (6))) ; (1 2 3)