It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 11 years ago.
Please demonstrate first-class functions (or some other functional programming concept) for code reuse for a beginner using these two overlapping Clojure functions. Basically, simplify the code block below using functional programming methods.
As a comparison, how would you do it in your other functional language of choice?
insertR and insertL are simple first-occurrence insertion functions. As you can see, they only differ by one line.
;test case
(def newkey :cake)
(def oldkey :and)
(def lat '(:bacon :lettuce :and :tomato :and :jelly)) ; list of keywords
(defn insertR [newkey oldkey lat]
(if (empty? lat)
'()
(if (= (first lat) oldkey)
(cons oldkey (cons newkey (rest lat))) ;;; diff line
(cons (first lat) (insertR newkey oldkey (rest lat))))))
(defn insertL [newkey oldkey lat]
(if (empty? lat)
'()
(if (= (first lat) oldkey)
(cons newkey lat) ;;; diff line
(cons (first lat) (insertL newkey oldkey (rest lat))))))
Here are the outputs.
=> (insertR newkey oldkey lat)
(:bacon :lettuce :and :cake :tomato :and :jelly)
=> (insertL newkey oldkey lat)
(:bacon :lettuce :cake :and :tomato :and :jelly)
Here's an example of refactoring this using first-class functions:
(defn insert [newkey oldkey lat f]
(if (empty? lat)
'()
(if (= (first lat) oldkey)
(f oldkey newkey lat)
(cons (first lat) (insert newkey oldkey (rest lat) f)))))
(defn insertL [newkey oldkey lat]
(insert newkey oldkey lat
(fn [oldkey newkey lat] (cons newkey lat))))
(defn insertR [newkey oldkey lat]
(insert newkey oldkey lat
(fn [oldkey newkey lat] (cons oldkey (cons newkey (rest lat))))))
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 using the beginning language with list abbreviations for DrRacket and want to make a powerset recursively but cannot figure out how to do it. I currently have this much
(define
(powerset aL)
(cond
[(empty? aL) (list)]
any help would be good.
What's in a powerset? A set's subsets!
An empty set is any set's subset,
so powerset of empty set's not empty.
Its (only) element it is an empty set:
(define
(powerset aL)
(cond
[(empty? aL) (list empty)]
[else
As for non-empty sets, there is a choice,
for each set's element, whether to be
or not to be included in subset
which is a member of a powerset.
We thus include both choices when combining
first element with smaller powerset,
that, which we get recursively applying
the same procedure to the rest of input:
(combine (first aL)
(powerset (rest aL)))]))
(define
(combine a r) ; `r` for Recursive Result
(cond
[(empty? r) empty] ; nothing to combine `a` with
[else
(cons (cons a (first r)) ; Both add `a` and
(cons (first r) ; don't add, to first subset in `r`
(combine ; and do the same
a ; with
(rest r))))])) ; the rest of `r`
"There are no answers, only choices". Rather,
the choices made, are what the answer's made of.
In Racket,
#lang racket
(define (power-set xs)
(cond
[(empty? xs) (list empty)] ; the empty set has only empty as subset
[(cons? xs) (define x (first xs)) ; a constructed list has a first element
(define ys (rest xs)) ; and a list of the remaining elements
;; There are two types of subsets of xs, thouse that
;; contain x and those without x.
(define with-out-x ; the power sets without x
(power-set ys))
(define with-x ; to get the power sets with x we
(cons-all x with-out-x)) ; we add x to the power sets without x
(append with-out-x with-x)])) ; Now both kind of subsets are returned.
(define (cons-all x xss)
; xss is a list of lists
; cons x onto all the lists in xss
(cond
[(empty? xss) empty]
[(cons? xss) (cons (cons x (first xss)) ; cons x to the first sublist
(cons-all x (rest xss)))])) ; and to the rest of the sublists
To test:
(power-set '(a b c))
Here's yet another implementation, after a couple of tests it appears to be faster than Chris' answer for larger lists. It was tested using standard Racket:
(define (powerset aL)
(if (empty? aL)
'(())
(let ((rst (powerset (rest aL))))
(append (map (lambda (x) (cons (first aL) x))
rst)
rst))))
Here's my implementation of power set (though I only tested it using standard Racket language, not Beginning Student):
(define (powerset lst)
(if (null? lst)
'(())
(append-map (lambda (x)
(list x (cons (car lst) x)))
(powerset (cdr lst)))))
(Thanks to samth for reminding me that flatmap is called append-map in Racket!)
You can just use side effect:
(define res '())
(define
(pow raw leaf)
(cond
[(empty? raw) (set! res (cons leaf res))
res]
[else (pow (cdr raw) leaf)
(pow (cdr raw) (cons (car raw) leaf))]))
(pow '(1 2 3) '())
I am watching SICP video lectures and i came to a section where tutors are showing procedures to work with lists, so, here is one of them:
(define (map p l)
(if (null? l)
(list)
(cons (p (car l))
(map p (cdr l)))))
What i want to ask is: is there a way to define map in iterative way, or that cons requires lazy evaluation to be executed right?
You original code is almost tail recursive.. the only thing that makes it not is the cons part. If Scheme had equal requirement for having TRMC optimization as it has TCO requirement you could leave your code as is and the implementation would have made it tail recursive for you.
Since it isn't a requirement we need to do our own TRMC optimization. Usually when iterating a list in a loop and having it tail recursive by using an accumulator you get the result in the opposite order, thus you can do linear update reverse:
(define (map proc lst)
(let loop ((lst lst) (acc '()))
(cond ((null? lst) (reverse! acc) acc)
(else (loop (cdr lst)
(cons (proc (car lst)) acc))))))
Or you can do it all in one pass:
(define (map proc lst)
(define head (list 1))
(let loop ((tail head) (lst lst))
(cond ((null? lst) (cdr head))
(else (set-cdr! tail (list (proc (car lst))))
(loop (cdr tail) (cdr lst))))))
Now in both cases you mutate only the structure the procedure has itself created, thus for the user it might as well be implemented in the same manner as your example.
When you use higher order procedures like map from your implementation it could happen it has been implemented like this. It's easy to find out by comparing performance on the supplied map with the different implementations with a very long list. The difference between the executions would tell you if it's TRMCO or how the supplied map probably has been implemented.
You need to embrace recursion in order to appreciate SICP and Scheme in general, so try to get used to it, you will appreciate it later, promised.
But yes, you can:
(define (iterative-map f lst)
(define res null)
(do ((i (- (length lst) 1) (- i 1))) ((= i -1))
(set! res (cons (f (list-ref lst i)) res)))
res)
(iterative-map (lambda (x) (+ x 1)) '(1 3 5))
=> '(2 4 6)
but using set! is considered bad style if avoidable.
In Racket you have a different set of loops that are more elegant:
(define (for-map f lst)
(for/list ((i lst))
(f i)))
(for-map add1 '(1 3 5))
=> '(2 4 6)
"define a procedure 'reduce-per-key' which a procedure reducef and a list of associations in which each key is paired with a list. The output is a list of the same structure except that each key is now associated with the result of applying reducef to its associated list"
I've already written 'map-per-key' and 'group-by-key' :
(define (map-per-key mapf lls)
(cond
[(null? lls) '()]
[else (append (mapf (car lls))(map-per-key mapf (cdr lls)))]))
(define (addval kv lls)
(cond
[(null? lls) (list (list (car kv)(cdr kv)))]
[(eq? (caar lls) (car kv))
(cons (list (car kv) (cons (cadr kv) (cadar lls)))(cdr lls))]
[else (cons (car lls)(addval kv (cdr lls)))]))
(define (group-by-key lls)
(cond
[(null? lls) '()]
[else (addval (car lls) (group-by-key (cdr lls)))]))
how would I write the next step, 'reduce-per-key' ? I'm also having trouble determining if it calls for two arguments or three.
so far, I've come up with:
(define (reduce-per-key reducef lls)
(let loop ((val (car lls))
(lls (cdr lls)))
(if (null? lls) val
(loop (reducef val (car lls)) (cdr lls)))))
however, with a test case such as:
(reduce-per-key
(lambda (kv) (list (car kv) (length (cadr kv))))
(group-by-key
(map-per-key (lambda (kv) (list kv kv kv)) xs)))
I receive an incorrect argument count, but when I try to write it with three arguments, I also receive this error. Anyone know what I'm doing wrong?
Your solution is a lot more complicated than it needs to be, and has several errors. In fact, the correct answer is simple enough to make unnecessary the definition of new helper procedures. Try working on this skeleton of a solution, just fill-in the blanks:
(define (reduce-per-key reducef lls)
(if (null? lls) ; If the association list is empty, we're done
<???> ; and we can return the empty list.
(cons (cons <???> ; Otherwise, build a new association with the same key
<???>) ; and the result of mapping `reducef` on the key's value
(reduce-per-key <???> <???>)))) ; pass reducef, advance the recursion
Remember that there's a built-in procedure for mapping a function over a list. Test it like this:
(reduce-per-key (lambda (x) (* x x))
'((x 1 2) (y 3) (z 4 5 6)))
> '((x 1 4) (y 9) (z 16 25 36))
Notice that each association is composed of a key (the car part) and a list as its value (the cdr part). For example:
(define an-association '(x 3 6 9))
(car an-association)
> 'x ; the key
(cdr an-association)
> '(3 6 9) ; the value, it's a list
As a final thought, the name reduce-per-key is a bit misleading, map-per-key would be a lot more appropriate as this procedure can be easily expressed using map ... but that's left as an exercise for the reader.
UPDATE:
Now that you've found a solution, I can suggest a more concise alternative using map:
(define (reduce-per-key reducef lls)
(map (lambda (e) (cons (car e) (map reducef (cdr e))))
lls))
i'm working through SICP - one exercise is to implement foreach (doseq). This is an academic exercise. In clojure, this is what I came up with:
(defn for-each [proc, items]
(if (empty? items) nil
(do
(proc (first items))
(recur proc (rest items)))))
but, i'm a little murky about if do is cheating, because do is a special form in clojure and i don't think anything like that has been introduced yet in SICP. is there a more minimalist answer?
Here's another attempt which only executes proc on the last element:
(defn for-each-2 [proc, items]
(let [f (first items)
r (rest items)]
(if (empty? r)
(proc f)
(recur proc r))))
Use doseq and you're all set. For example:
(doseq [e '(1 2 3)]
(prn e))
Will print:
1
2
3
nil
EDIT :
If you want to implement for-each by hand and using as few special forms as possible, here's another alternative, although it ends up being almost as short as yours:
(defn for-each [f l]
(cond (empty? l) nil
:else (do (f (first l))
(recur f (rest l)))))
Interestingly, the same procedure could have been written more succinctly in Scheme, the Lisp dialect used in SICP:
(define (for-each f l)
(cond ((null? l) null)
(else (f (first l))
(for-each f (rest l)))))
Here is my attempt. It just carries function execution in an inner loop.
(defn for-each [fun, xs]
(loop [fun fun
xs xs
action nil]
(if (first xs)
(recur fun (rest xs) (fun (first xs)))
xs)))