I'm writing a function to partially-apply arguments to functions, such that
(define mapeven (partial-apply map even?))
(mapeven (list 1 2 3 4)) ; '(#f #t #f #t)
To that end, I have
(define (partial-apply* func . args)
(define (apply-one func arg)
(λ args (apply func (cons arg args))))
(foldl (λ (new carry) (apply-one carry new)) func args))
which seems to work fine. However, I'd also like to be able to "skip" args (probably by use of a sentinel value, like 'λ). I.E.:
(define apply-to-four (partial-apply map 'λ (list 1 2 3 4))
(apply-to-four even?) ; '(#f #t #f #t)
That is to say, when partial-apply encounters 'λ, it does NOT bind a value to that position, instead leaving it as a free variable. And when a partially applied function is called, first it will fill in arguments skipped by this mechanism of 'λ, then it will apply any remaining arguments to the end.
To this end, I have written:
(define (partial-apply func . args)
(define (apply-one func arg)
(if (equal? arg 'λ)
(λ args (λ (x) (apply func (cons x args)))))
(λ args (apply func (cons arg args)))))
(foldl (λ (new carry) (apply-one carry new)) func args))
However, it doesn't work.
> (define apply-to-4 (partial-apply map 'λ (list 1 2 3 4)))
> (apply-to-4 even?)
#<procedure>
It seems like the problem is in the affirmative branch of the if statement, but I'm having trouble nailing it down. Any advice?
Related
I have this curry function:
(define curry
(lambda (f) (lambda (a) (lambda (b) (f a b)))))
I think it's like (define curry (f a b)).
my assignment is to write a function consElem2All using curry,which should work like
(((consElem2All cons) 'b) '((1) (2 3) (4)))
>((b 1) (b 2 3) (b 4))
I have wrote this function in a regular way:
(define (consElem2All0 x lst)
(map (lambda (elem) (cons x elem)) lst))
but still don't know how to transform it with curry. Can anyone help me?
thanks in advance
bearzk
You should begin by reading about currying. If you don't understand what curry is about, it may be really hard to use it... In your case, http://www.engr.uconn.edu/~jeffm/Papers/curry.html may be a good start.
One very common and interesting use of currying is with functions like reduce or map (for themselves or their arguments).
Let's define two currying operators!
(define curry2 (lambda (f) (lambda (arg1) (lambda (arg2) (f arg1 arg2)))))
(define curry3 (lambda (f) (lambda (arg1) (lambda (arg2) (lambda (arg3) (f arg1 arg2 arg3))))))
Then a few curried mathematical functions:
(define mult (curry2 *))
(define double (mult 2))
(define add (curry2 +))
(define increment (add 1))
(define decrement (add -1))
And then come the curried reduce/map:
(define creduce (curry3 reduce))
(define cmap (curry2 map))
Using them
First reduce use cases:
(define sum ((creduce +) 0))
(sum '(1 2 3 4)) ; => 10
(define product (creduce * 1))
(product '(1 2 3 4)) ; => 24
And then map use cases:
(define doubles (cmap double))
(doubles '(1 2 3 4)) ; => (2 4 6 8)
(define bump (cmap increment))
(bump '(1 2 3 4)) ; => (2 3 4 5)
I hope that helps you grasp the usefulness of currying...
So your version of curry takes a function with two args, let's say:
(define (cons a b) ...)
and turns that into something you can call like this:
(define my-cons (curry cons))
((my-cons 'a) '(b c)) ; => (cons 'a '(b c)) => '(a b c)
You actually have a function that takes three args. If you had a curry3 that managed 3-ary functions, you could do something like:
(define (consElem2All0 the-conser x lst) ...)
(like you did, but allowing cons-like functions other than cons to be used!)
and then do this:
(define consElem2All (curry3 consElem2All0))
You don't have such a curry3 at hand. So you can either build one, or work around it by "manually" currying the extra variable yourself. Working around it looks something like:
(define (consElem2All0 the-conser)
(lambda (x lst) ...something using the-conser...))
(define (consElem2All the-conser)
(curry (consElem2All0 the-conser)))
Note that there's one other possible use of curry in the map expression itself, implied by you wrapping a lambda around cons to take the element to pass to cons. How could you curry x into cons so that you get a one-argument function that can be used directly to map?...
Perhaps better use a generalized version:
(define (my-curry f)
(lambda args
(cond ((= (length args) 1)
(lambda lst (apply f (cons (car args) lst))))
((>= (length args) 2)
(apply f (cons (car args) (cdr args)))))))
(define (consElem2All0 x lst)
(map ((curry cons) x) lst))
I am new in Lisp and i need some help.
I need to simplify next expressions:
from (+ (+ A B) C) to (+ A B C)
and from (- (- A B) C) to (- A B C).
If you could help me with one of them I'll understand how i need to do this to the next one.
Thanks a lot.
Assuming you have an input that matches this pattern, (+ e1 ... en), you want to recursively simplify all e1 to en, which gives you s1, ..., sn, and then extract all the si that start with a + to move their arguments one level up, to the simplified expression you are building.
An expression e matches the above pattern if (and (consp e) (eq '+ (car e))).
Then, all the ei are just given by the list that is (cdr e).
Consider the (+) case, how could you simplify it?
To apply a function f to a list of values, call (mapcar #'f list).
To split a list into two lists, based on a predicate p, you might use a loop:
(let ((sat nil) (unsat nil))
(dolist (x list (values sat unsat))
(if (funcall predicate x)
(push x sat)
(push x unsat))))
There is a purely functional way to write this, can you figure it out?
Here is a trivial simplifier written in Racket, with an implementation of a rather mindless simplifier for +. Note that this is not intended as anything serious: it's just what I typed in when I was thinking about this question.
This uses Racket's pattern matching, probably in a naïve way, to do some of the work.
(define/match (simplify expression)
;; simplifier driver
(((cons op args))
;; An operator with some arguments
;; Note that this assumes that the arguments to operators are always
;; expressions to simplify, so the recursive level can be here
(simplify-op op (map simplify args)))
((expr)
;; anything else
expr))
(define op-table (make-hash))
(define-syntax-rule (define-op-simplifier (op args) form ...)
;; Define a simplifier for op with arguments args
(hash-set! op-table 'op (λ (args) form ...)))
(define (simplify-op op args)
;; Note the slightly arcane fallback: you need to wrap it in a thunk
;; so hash-ref does not try to call it.
((hash-ref op-table op (thunk (λ (args) (cons op args)))) args))
(define-op-simplifier (+ exprs)
;; Simplify (+ ...) by flattening + in its arguments
(let loop ([ftail exprs]
[results '()])
(if (null? ftail)
`(+ ,#(reverse results))
(loop (rest ftail)
(match (first ftail)
[(cons '+ addends)
(append (reverse addends) results)]
[expr (cons expr results)])))))
It is possible to be more aggressive than this. For instance we can coalesce runs of literal numbers, so we can simplify (+ 1 2 3 a 4) to
(+ 6 a 4) (note it is not safe in general to further simplify this to (+ 10 a) unless all arithmetic is exact). Here is a function which does this coalescing for for + and *:
(define (coalesce-literal-numbers f elts)
;; coalesce runs of literal numbers for an operator f.
;; This relies on the fact that (f) returns a good identity for f
;; (so in particular it returns an exact number). Thisis true for Racket
;; and CL and I think any Lisp worth its salt.
;;
;; Note that it's important here that (eqv? 1 1.0) is false.
;;;
(define id (f))
(let loop ([tail elts]
[accum id]
[results '()])
(cond [(null? tail)
(if (not (eqv? accum id))
(reverse (cons accum results))
(reverse results))]
[(number? (first tail))
(loop (rest tail)
(f accum (first tail))
results)]
[(eqv? accum id)
(loop (rest tail)
accum
(cons (first tail) results))]
[else
(loop (rest tail)
id
(list* (first tail) accum results))])))
And here is a modified simplifier for + which uses this. As well as coalescing it notices that (+ x) can be simplified to x.
(define-op-simplifier (+ exprs)
;; Simplify (+ ...) by flattening + in its arguments
(let loop ([ftail exprs]
[results '()])
(if (null? ftail)
(let ([coalesced (coalesce-literal-numbers + (reverse results))])
(match coalesced
[(list something)
something]
[exprs
`(+ ,#exprs)]))
(loop (rest ftail)
(match (first ftail)
[(cons '+ addends)
(append (reverse addends) results)]
[expr (cons expr results)])))))
Here is an example of using this enhanced simplifier:
> (simplify 'a)
'a
> (simplify 1)
1
> (simplify '(+ 1 a))
'(+ 1 a)
> (simplify '(+ a (+ b c)))
'(+ a b c)
> (simplify '(+ 1 (+ 3 c) 4))
'(+ 4 c 4)
> (simplify '(+ 1 2 3))
6
For yet more value you can notice that the simplifier for * is really the same, and change things to this:
(define (simplify-arith-op op fn exprs)
(let loop ([ftail exprs]
[results '()])
(if (null? ftail)
(let ([coalesced (coalesce-literal-numbers fn (reverse results))])
(match coalesced
[(list something)
something]
['()
(fn)]
[exprs
`(,op ,#exprs)]))
(loop (rest ftail)
(match (first ftail)
[(cons the-op addends)
#:when (eqv? the-op op)
(append (reverse addends) results)]
[expr (cons expr results)])))))
(define-op-simplifier (+ exprs)
(simplify-arith-op '+ + exprs))
(define-op-simplifier (* exprs)
(simplify-arith-op '* * exprs))
And now
(simplify '(+ a (* 1 2 (+ 4 5)) (* 3 4) 6 (* b)))
'(+ a 36 b)
Which is reasonably neat.
You can go further than this, For instance when coalescing numbers for an operator you can simply elide sequences of the identity for that operator: (* 1 1 a 1 1 b) can be simplified to (* a b), not (* 1 a 1 b). It may seem silly to do that: who would ever write such an expression, but they can quite easily occur when simplifying complicated expressions.
There is a gist of an elaborated version of this code. It may still be buggy.
Say I have a macro like this:
(define-syntax (choose stx)
(define data (syntax->datum stx))
(define args (cadr data))
(define body (cddr data))
(define output
`(apply (case (car ,args)
,(map (lambda (choice)
`((,(car choice)) ,(cadr choice)))
body)
(else (displayln "error")))
(cdr ,args)))
(println output)
#'(void))
If I use this on something like this (there could be more options):
(choose args
("run" runsomething)
("del" delsomethingelse))
It transforms it to
(apply
(case (car args)
((("run") runsomething)
(("del") delsomethingelse))
(else (displayln "error")))
(cdr args))
Which is not valid code, because the map gave it extra parentheses. Instead I want it to give me this:
(apply
(case (car args)
(("run") runsomething)
(("del") delsomethingelse)
(else (displayln "error")))
(cdr args))
How could I do something like this?
Use unquote-splicing (aka ,#) to get rid of the list surrounding map.
Example:
(define xs '(a b c))
`(1 2 ,xs 3 4) ; => '(1 2 (a b c) 3 4)
`(1 2 ,#xs 3 4) ; => '(1 2 a b c 3 4)
However I notice that you use syntax->datum on the input stx
of the syntax transformer. That removes lexical information, which
could end up causing problems. It recommend using either syntax-case
or syntax-parse, which use pattern matching to pick out the elements
of the input syntax and templates to generate the output.
(define-syntax (choose stx)
(syntax-case stx ()
[(_choose args
(datum fun-expr)
...)
#'(apply (case (car args)
[(datum) fun-expr]
...)
(cdr args))]))
(define (run-it . xs) (list 'ran-it xs))
(define (del-it . xs) (list 'delt-it xs))
(choose (list "run" 1 2 3)
("run" run-it)
("del" del-it))
Output: '(ran-it (1 2 3))
The map! procedure should modify the existing list to have the values of the operator applied to the original values.
For example:
(define a '(1 2 3 4 5))
(define double (lambda (x) (* x 2)))
(map! double a)
returns
done
Then when a is evaluated, a should return
(2 4 6 8 10)
map! procedure must do that work.
(define (map! operator given-list)
(if (null? given-list) 'done
(<the procedure that does the modification>)))
My guess1:
(map (lambda (x) (set! x (operator x))) given-list)
(map! double a)
returns:
'(#<void> #<void> #<void> #<void> #<void>)
My guess2:
(cons (operator (car given-list)) (map! double (cdr given-list)))
(map! double a)
returns:
'(2 4 6 8 10 . done)
My guess3:
(set! given-list (map operator given-list))
(map! double a)
returns:
'(2 4 6 8 10)
My guess4:
(let ((element (car given-list)))
(set! element (operator given-list) (map! operator (cdr given-list)))
(map! double a)
returns:
'done
but, when "a" is evaluated, it still says:
'(1 2 3 4 5)
What do I have to do for this?????
You cannot use set! for this. You need to use set-car! on the cons cell you're changing. Here's how you might write it:
(define (map! f lst)
(let loop ((rest lst))
(unless (null? rest)
(set-car! rest (f (car rest)))
(loop (cdr rest)))))
If you have SRFI 1, it's even easier (if we ignore for a moment that SRFI 1 already defines map! ;-)):
(define (map! f lst)
(pair-for-each (lambda (pair)
(set-car! pair (f (car pair))))
lst))
This question already has answers here:
Using AND with the apply function in Scheme
(9 answers)
Closed 9 years ago.
I tried it in Racket like this
> (apply and '(1 2 3))
. and: bad syntax in: and
> (and 1 2 3)
3
Does anyone have ideas about this?
and is not a function, it's a macro, so you cannot pass it around like a function.
The reason and is a macro, is to enable short-circuiting behaviour. You can make your own non-short-circuiting version:
(define (my-and . items)
(if (null? items) #t
(let loop ((test (car items))
(rest (cdr items)))
(cond ((null? rest) test)
(test (loop (car rest) (cdr rest)))
(else #f)))))
and my-and can be used with apply.
For comparison, here's what the macro (which does do short-circuiting) looks like:
(define-syntax and
(syntax-rules ()
((and) #t)
((and test) test)
((and test rest ...) (if test
(and rest ...)
#f))))
Chris Jester-Young's answer is right, but there's one other point I want to highlight. The standard and operator is a macro which delays the evaluation of its arguments, by (essentially, if not exactly) turning (and a b c) into (if a (if b c #f) #f). This means that if a is false, b and c do not get evaluated.
We also have the option of defining an and-function such that (and-function a b c) evaluates a, b, and c, and returns true when the values are all true. This means that all of a, b, and c get evaluated. and-function has the nice property that you can pass it around as function because it is a function.
There's still one option that seems to be missing: an and-function-delaying-evaluation that returns return if and only if a, b, and c all return true, but that doesn't evaluate, e.g., b and c if a produces false. This can be had, actually, with a function and-funcalling-function that requires its arguments to be a list of functions. For instance:
(define (and-funcalling-function functions)
(or (null? functions)
(and ((car functions))
(and-funcalling-function (cdr functions)))))
(and-funcalling-function
(list (lambda () (even? 2))
(lambda () (odd? 3))))
; => #t
(and-funcalling-function
(list (lambda () (odd? 2))
(lambda () (even? 3)))) ; (even? 3) does not get evaluated
; => #f
Using a macro and this idiom, we can actually implement something with the standard and semantics:
(define-syntax standard-and
(syntax-rules ()
((standard-and form ...)
(and-funcalling-function (list (lambda () form) ...)))))
(macroexpand '(standard-and (odd? 2) (even? 3)))
; =>
; (and-funcalling-function
; (list (lambda () (odd? 2))
; (lambda () (even? 3))))
The lesson to take away from this, of course, is that you can have an and-like function that you can pass around and still get delayed evaluation; you just need to delay evaluation by wrapping things in functions and letting the and-like function call those functions to produce values. (In Scheme, this might be an opportunity to use promises.)