Construct a map function with elisp - elisp

I mimic a general map function from SICP's
(define (map proc items)
(if (null? items)
nil
(cons (proc (car items))
(map proc (cdr items)))))
(map abs (list -10 2.5 -11.6 17))
Rephrase it with elisp
(defun map(proc items)
(if (null items)
nil
(cons (proc (car items))
(map proc (cdr items)))))
(map abs (list -10 2.5 -11.6 17))
Run but report error:
ELISP> (map abs (list -3 -5))
*** Eval error *** Symbol’s value as variable is void: abs
However, abs works
ELISP> (map abs (list -3 -5))
*** Eval error *** Symbol’s value as variable is void: abs
What's the problem with my rewriting?

Related

Scheme Error Unknown Identifier: map when using higher order function

Essentially, I am trying to write a scheme method which will use the map function to cube every item in a list. so it would go from '(1 2 3 4) to '(1 8 27 64). Here is my current code:
(define (cube-all lst)
(map (lambda (x) (* (* x x) x)) lst)
)
This is the error message:
SchemeError: unknown identifier: map
Current Eval Stack:
-------------------------
0: map
1: (cube-all (quote (1 2 3 4)))
2: (println (cube-all (quote (1 2 3 4))))
Is this due to improper syntax? Or do I have to do something else with map?
Edit: println is another function which just displays the answer
If you are constrained to using the 'scheme' mentioned in a comment then you can't use map.
But ... you can write map:
(define (reverse l)
(define (reverse-loop lt into)
(if (null? lt)
into
(reverse-loop (cdr lt) (cons (car lt) into))))
(reverse-loop l '()))
(define (map f l)
(define (map-loop lt into)
(if (null? lt)
(reverse into)
(map-loop (cdr lt) (cons (f (car lt)) into))))
(map-loop l '()))
(define (cube-all lst)
(map (lambda (x) (* (* x x) x)) lst))
(cube-all '(1 2 3))

what does mean "scheme and: bad syntax in: and"

I am getting the following error "and: bad syntax in: and
#lang racket
(define fold
(lambda (fn lst)
(if (null? (cdr lst))
(car lst)
(fn (car lst) (fold fn (cdr lst)))
)
)
)
(define none-diff?
(lambda (lst num)
(if (even? num)
(fold and (map even? lst))
(fold and (map odd? lst))
)
)
)
I try foldr in szScheme , the same error , I do not know why ?
(fold + (list 1 2 3)) : ok
(fold and (map (even? (list 1 2 3)))) : error
"and" and "+" are function , but ?
And isn't function, but macro. And macros can't be used as argument for higher-order functions (for example map, apply or foldl variants).
In this case, you can use andmap:
> (andmap even? (list 2 4 6))
#t
> (andmap even? (list 1 2 3))
#f
(fold and
(map (even? (list 1 2 3))))
fold almost sure requires 3 arguments
and is not a function, but a special form
you pass map a single argument
a list cannot be even.

Revising Intersect Mutable Object

I tried making a mutable function with intersect, but I think I'm severely messing it up with how I implemented intersect into the function and I'm not sure about the best way to fix the function.
(define (intersect-mutable)
(let ((lst '()))
(let ((lst2 '()))
(define (insert x)
(set! lst (cons x lst)))
(define (intersect)
(define (helper lst lst2)
(define contains member)
(cond ((null? set) '())
((contains (car lst) lst2)
(cons (car lst) (intersect (cdr lst) lst)))
(else
(intersect (cdr lst) lst2))))
(helper lst lst2))
(lambda (function)
(cond ((eq? function 'intersect) intersect)
((eq? function 'insert) insert)
(else
'undefined))))))
A test case for the recursive function would be:
>(intersection '(2 4 7 10) '(2 9 0 10))
(2 10)
>(intersection '(1 4 10) '(83 1 48 2 4))
(1 4)
Test cases for insert:
(define mut (intersect-mutable))
((mut 'insert) 'intersect)
((mut 'insert) 'mutable)
To clarify, I'm trying to intersect two separate lists into one list. I added an insert function.
Use list->mlist in order to convert a list of immutable cons cells into a list of mutable cons (mcons cells).
See more here: docs
If the mutation is only to housekeep the two lists:
(define (intersect-mutable (lst1 '()) (lst2 '()))
(define (method-insert lst1? value)
(if lst1?
(set! lst1 (cons value lst1))
(set! lst2 (cons value lst2)))
message-handler)
(define (method-intersect)
;; intersect is a working intersect without mutation
(intersect lst1 lst2))
(define (message-handler msg)
(case msg
((insert) method-insert)
((insert1) (lambda (v) (method-insert #t v)))
((insert2) (lambda (v) (method-insert #f v)))
((lst1) lst1)
((lst2) lst2)
((intersect) method-intersect)
(else (error "No such method" msg))))
message-handler)
(define obj (intersect-mutable '(10) '(30)))
((obj 'insert) #t 5)
((obj 'insert2) 10)
(obj 'lst1) ; ==> (5 10)
(obj 'lst2) ; ==> (10 30)
((obj 'intersect)) ; ==> (10)
However notice that intersect doesn't really mutate anything. I think perhaps the whole point with this is OO so I imagine we can make operate on one list like this:
(define (list-object (lst '()))
(define (method-insert . values)
(set! lst (foldl cons lst values))
message-handler)
(define (method-intersect lst2)
;; intersect is a working intersect without mutation
(set! lst (intersect lst lst2))
message-handler)
(define (method-member? value)
(member value lst))
(define (message-handler msg)
(case msg
((insert) method-insert)
((intersect) method-intersect)
((member?) method-member?)
((lst) lst)
(else (error "No such method" msg))))
message-handler)
(define obj (((list-object '(5)) 'insert) 10 20 30))
(obj 'lst) ; ==> (30 20 10 5)
((obj 'intersect) '(10 30 60))
(obj 'lst) ; ==> (20 30)
Imagine you make many objects like this, then you can make (tiny)CLOS type generic methods:
;; generic. Works on any object that has
;; member? method and lists
(define (member? value obj)
(if (procedure? obj)
((obj 'member?) value)
(member value obj)))
;; Another object type that has member?
;; only that it means the values binary bits
;; are set on the object
(define (number-object value)
(define (method-member? value2)
(= value2 (bitwise-and value value2)))
(define (message-handler msg)
(case msg
((member?) method-member?)))
message-handler)
;; test objects
(define num1 (number-object 24))
(define lst1 (list-object '(1 8)))
;; some test
(member? 2 num1); ==> #f
(member? 8 num1); ==> #t
(member? 8 lst1); ==> (8) (true)
(member? 9 lst1); ==> #f
(member? 9 '(1 3 5 9 10)) ; ==> (9 10)
;; map is the ultimate test
(map (lambda (o) (member? 8 o)) (list num1 lst1))
; ==> (#t (8))

how to call to this map function

I saw a code on a book about how to create a map function in Scheme, the code is the following:
(define map (lambda (f L)
(if null? L '()
(cons (f (car L)) (map f (cdr L))))))
(define square (lambda (x)
(* x x)))
(define square-list (lambda (L)
(map square L)))
Supposedly I can call it with:
(map square-list '(1 2 3 4))
but it is throwing me the following error:
SchemeError: too many operands in form: (null? L (quote ()) (cons (f (car L)) (map f (cdr L))))
Current Eval Stack:
-------------------------
0: (map square-list (quote (1 2 3 4)))
How should I call this function?
You have two errors. First, you forgot to surround the null? check with parentheses (and notice a better way to indent your code):
(define map
(lambda (f L)
(if (null? L)
'()
(cons (f (car L))
(map f (cdr L))))))
Second, you're expected to call the procedure like this:
(square-list '(1 2 3 4 5))
=> '(1 4 9 16 25)
You're missing parens around null? L, i.e. your condition should probably look like
(if (null? L) '()
(cons ...))

What is definition of “map” in Racket

What would be the definition of "map" function without using any other high-level functional in Racket?
I need a stack recursion version.
A simple definition of a map function could be:
(define (map f l)
(if (null? l)
'()
(cons (f (car l)) (map f (cdr l)))))
(map (lambda (n) (* n n)) '(1 2 3 4)) ;; => (1 4 9 16)
Usually you'll find map being made with fold, but I prefer doing everything with pair-for-each (maplist in CL). This defines pair-for-each, map, filter-map, filter, zip and unzip compatible with the same procedures in SRFI-1 List library.
#!racket/base
(define-values (pair-for-each map filter-map filter zip unzip)
(let ((%MAP-PASS (list 'MAP-PASS))
(%MAP-END (list 'MAP-END)))
;; pair-for-each-1 applies proc to every cons
;; in order until proc returns %MAP-END
;; when proc evaluates to %MAP-PASS the result is skipped
(define (pair-for-each-1 proc lst (next cdr))
(let loop ((lst lst))
(let ((res (proc lst)))
(cond ((eq? res %MAP-END) '())
((eq? res %MAP-PASS) (loop (next lst)))
(else (cons res
(loop (next lst))))))))
;; Transform a typical map procedure to include
;; a %MAP-END when the list argument is eq? a certain value
(define (stop-at value proc)
(lambda (lst)
(if (eq? value lst)
%MAP-END
(proc lst))))
;; Takes a lists of lists and returns a
;; new list with the cdrs
(define (cdrs lsts)
(pair-for-each-1 (stop-at '() cdar) lsts))
;; Takes a list of lists and returns a
;; new list with the cars except if one of
;; the sublists are nil in which the result is also nil
(define (cars lsts)
(call/cc (lambda (exit)
(pair-for-each-1 (stop-at '()
(lambda (x)
(let ((x (car x)))
(if (null? x)
(exit '())
(car x)))))
lsts))))
;; Takes a list of lists and returns #t if any are null
(define (any-null? lsts)
(if (null? lsts)
#f
(or (null? (car lsts))
(any-null? (cdr lsts)))))
;; Return value definitions starts here
;; pair-for-each is called maplist in CL
(define (pair-for-each proc lst . lsts)
(if (null? lsts)
(pair-for-each-1 (stop-at '() (lambda (x) (proc x))) lst)
(pair-for-each-1 (lambda (args)
(if (any-null? args)
%MAP-END
(apply proc args)))
(cons lst lsts)
cdrs)))
;; Multi arity map
(define (map f lst . lsts)
(if (null? lsts)
(pair-for-each-1 (stop-at '() (lambda (x) (f (car x)))) lst)
(pair-for-each-1 (lambda (x)
(let ((args (cars x)))
(if (null? args)
%MAP-END
(apply f args))))
(cons lst lsts)
cdrs)))
;; filter-map is like map except it skips false values
(define (filter-map proc . lsts)
(apply map (lambda x
(or (apply proc x) %MAP-PASS)))
lsts)
;; filter only takes one list and instead of the result it
;; takes the original argument as value (which may be #f)
(define (filter predicate? lst)
(pair-for-each-1 (stop-at '()
(lambda (x)
(let ((x (car x)))
(if (predicate? x)
x
%MAP-PASS))))
lst))
;; zip (zip '(1 2 3) '(a b c)) ; ==> ((1 a) (2 b) (3 c))
(define (zip lst . lsts)
(apply map list (cons lst lsts)))
;; unzip does the same except it takes a list of lists as argument
(define (unzip lsts)
(apply map list lsts))
;; return procedures
(values pair-for-each map filter-map filter zip unzip)))
It was unclear to me what kind of implementation the OP asked for, so here is yet another variation of map.
; map : function list -> list
; (map f '()) = '()
; (map f (cons x xs)) = (cons (f x) (map f xs))
(define (my-map f xs)
; loop : list list -> list
; (loop (list x1 ... xn) (list y1 ... ym)) = (list (f x1) ... (f xn) ym ... y1)
(define (loop xs ys)
(match xs
['() (reverse ys)]
[(cons x xs) (loop xs (cons (f x) ys))]))
(loop xs '()))
Example:
(my-map sqrt '(1 4 9 16))
'(1 2 3 4)

Resources