I've started learning contracts and I have such procedure:
(define/contract (foldr-map f a xs)
foldr-map/c
(define (it a xs ys)
(if (null? xs)
(cons ys a)
(let* [(p (it a (cdr xs) ys))
(fc (f (car xs) (cdr p)))]
(cons (cons (car fc) (car p)) (cdr fc)))))
(it a xs null))
(foldr-map (lambda (x a) (cons a (+ a x))) 0 `(1 2 3))
And I have flodr-map/c contract defined as:
(define foldr-map/c
(parametric->/c [x a] (->
(-> x a (cons/c a number?))
a
(listof x)
(cons/c (listof a) a))))
But I see such error:
foldr-map: broke its own contract
promised: a
produced: 3
in: the 2nd argument of
the 1st argument of
(parametric->/c
(x a)
(->
(-> x a (cons/c a number?))
a
(listof x)
(cons/c (listof a) a)))
contract from: (function foldr-map)
blaming: (function foldr-map)
(assuming the contract is correct)
I know that the procedure works correctly so the contract has to be wrong. The procedure takes the argument f which is a function.
The contract has 2 parameters:
x is an element of list xs
a is an accummulator
When I change the contract to be:
(define foldr-map/c
(parametric->/c [x a] (->
(-> x number? (cons/c number? number?))
a
(listof x)
(cons/c (listof a) a))))
I get such error:
foldr-map: broke its own contract
promised: number?
produced: #<a>
in: the 2nd argument of
the 1st argument of
(parametric->/c
(x a)
(->
(-> x number? (cons/c number? number?))
a
(listof x)
(cons/c (listof a) a)))
contract from: (function foldr-map)
blaming: (function foldr-map)
(assuming the contract is correct)
So at this point I got lost.
I found a solution:
(define foldr-map/c
(parametric->/c [x a] (->
(-> x a (cons/c a a))
a
(listof x)
(cons/c (listof a) a))))
It makes sense and seems kinda obvious but it took quite some debugging time to figure it out.
Related
If I have a recursive function like this:
(define (double-n-times x n)
(if (= n 0)
x
(double-n-times (* 2 x) (- n 1))))
How can I make a lambda version of it and never give it a name? ... like if i want to inline it somewhere. Is that possible? (I mean in this case I could use fold - so maybe the example isn't that great) - Is there some kind of symbol or placeholder for "self" that I haven't been able to find? Or do you just have to give it a name.
The Y-Combinator in Racket is:
(lambda (f)
((lambda (h) (h h))
(lambda (g) (f (lambda args (apply (g g) args))))))
This function can take any anonymous function and apply it on themselves recursively.
Let us define your function's part. double-n-times-part written only with lambdas:
(lambda (f)
(lambda (x n)
(if (= n 0) x (f (* 2 x) (- n 1))))))
where f we could name as we want - so we could also call it double-n-part.
If we apply the Y-Combinator on this, we get:
((lambda (f)
((lambda (h) (h h))
(lambda (g) (f (lambda args (apply (g g) args))))))
(lambda (f)
(lambda (x n)
(if (= n 0) x (f (* 2 x) (- n 1))))))
This spits out a function which takes the arguments x and n and applies the inner function of the second definiton on them.
So now, without any named functions - only using lambda expressions - you can apply on your arguments - let's say x=3 and n=4:
(((lambda (f)
((lambda (h) (h h))
(lambda (g) (f (lambda args (apply (g g) args))))))
(lambda (f)
(lambda (x n)
(if (= n 0) x (f (* 2 x) (- n 1))))))
3 4)
;;=> 48 ; as expected (3 * 2 * 2 * 2 * 2)
This is more convenient to read.
But we could also define the Y combinator without apply and args when we allow only monadic functions (functions with one arguments) instead of variadic ones. Then it looks like this (and we have to give the arguments one after another like this):
((((lambda (f)
((lambda (h) (h h))
(lambda (g) (f (lambda (x) ((g g) x))))))
(lambda (f)
(lambda (x)
(lambda (n)
(if (= n 0) x ((f (* 2 x)) (- n 1)))))))
3) 4)
;;=> 48
The answer to your question is yes, by using macros. But before I talk about that, I have to ask this first: do you ask because you are just curious? Or do you ask because there are some issues, like you don't want to pollute the namespace with names?
If you don't want to pollute the namespace with names, you can simply use local constructs like named let, letrec, or even Y combinator. Alternatively, you can wrap define inside (let () ...).
(let ()
(define (double-n-times x n)
(if (= n 0)
x
(double-n-times (* 2 x) (- n 1))))
(double-n-times 10 10))
;; double-n-times is not in scope here
For the actual answer: here's a macro rlam that is similar to lambda, but it allows you to use self to refer to itself:
#lang racket
(require syntax/parse/define)
(define-syntax-parse-rule (rlam args body ...+)
#:with self (datum->syntax this-syntax 'self)
(letrec ([self (λ args body ...)])
self))
;; compute factorial of 10
((rlam (x)
(if (= 0 x)
1
(* x (self (sub1 x))))) 10) ;=> 3628800
Yes. Being a placeholder for a name is what lambda function's parameters are there for:
(define (double-n-times x n)
(if (= n 0)
x
(double-n-times (* 2 x) (- n 1))))
=
(define double-n-times (lambda (x n)
(if (= n 0)
x
(double-n-times (* 2 x) (- n 1)))))
=
(define double-n-times (lambda (self) ;; received here
(lambda (x n)
(if (= n 0)
x
(self (* 2 x) (- n 1)))))) ;; and used, here
but what is this "self" parameter? It is the lambda function itself :
= ;; this one's in error...
(define double-n-times ((lambda (u) ;; call self with self
(u u)) ;; to receive self as an argument
(lambda (self)
(lambda (x n)
(if (= n 0)
x
(self (* 2 x) (- n 1)))))))
;; ...can you see where and why?
= ;; this one isn't:
(define double-n-times ((lambda (u) (u u))
(lambda (self)
(lambda (x n)
(if (= n 0)
x
((self self) (* 2 x) (- n 1)))))))
;; need to call self with self to actually get that
;; (lambda (x n) ... ) thing to be applied to the values!
And now it works: (double-n-times 1.5 2) returns 6.0.
This is already fine and dandy, but we had to write ((self self) ... ...) there to express the binary recursive call. Can we do better? Can we write the lambda function with the regular (self ... ...) call syntax as before? Let's see. Is it
= ;; erroneous
(define double-n-times ((lambda (u) (u u))
(lambda (self)
(lambda (x n)
(lambda (rec body) (self self)
(if (= n 0)
x
(rec (* 2 x) (- n 1))))))))
(no) Or is it
= ;; also erroneous...
(define double-n-times ((lambda (u) (u u))
(lambda (self)
(lambda (x n)
((lambda (rec body) body)
(self self)
(if (= n 0)
x
(rec (* 2 x) (- n 1)))))))) ;; ...can you see why?
(still no) Or is it perhaps
= ;; still erroneous...
(define double-n-times ((lambda (u) (u u))
(lambda (self)
((lambda (rec)
(lambda (x n)
(if (= n 0)
x
(rec (* 2 x) (- n 1)))))
(self self) ))))
(no yet again ... in an interesting way) Or is it actually
=
(define double-n-times ((lambda (u) (u u))
(lambda (self)
((lambda (rec)
(lambda (x n)
(if (= n 0)
x
(rec (* 2 x) (- n 1)))))
(lambda (a b) ((self self) a b)) ))))
(yes!) such that it can be abstracted and separated into
(define (Y2 g) ((lambda (u) (u u))
(lambda (self)
(g
(lambda (a b) ((self self) a b))))))
(define double-n-times (Y2
(lambda (rec) ;; declare the rec call name
(lambda (x n)
(if (= n 0)
x
(rec (* 2 x) (- n 1))))))) ;; and use it to make the call
and there we have it, the Y combinator for binary functions under strict evaluation strategy of Scheme.
Thus we first close over our binary lambda function with our chosen recursive call name, then use the Y2 combinator to transform this "rec spec" nested lambdas into a plain callable binary lambda function (i.e. such that expects two arguments).
Or course the name rec itself is of no importance as long as it does not interfere with the other names in our code. In particular the above could also be written as
(define double-n-times ;; globally visible name
(Y2
(lambda (double-n-times) ;; separate binding,
(lambda (x n) ;; invisible from
(if (= n 0) ;; the outside
x
(double-n-times (* 2 x) (- n 1))))))) ;; original code, unchanged
defining exactly the same function as the result.
This way we didn't have to change our original code at all, just close it over with another lambda parameter with the same name as the name of our intended recursive call, double-n-times, thus making this binding anonymous, i.e. making that name unobservable from the outside; and then passing that through the Y2 combinator.
Of course Scheme already has recursive bindings, and we can achieve the same effect by using letrec:
(define double-n-times ;; globally visible name
(letrec ((double-n-times ;; internal recursive binding:
(lambda (x n) ;; its value, (lambda (x n) ...)
(if (= n 0)
x
(double-n-times (* 2 x) (- n 1))))))
double-n-times)) ;; internal binding's value
Again the internal and the global names are independent of each other.
I need some help trying to figure out how to make the code below recursive using only lambdas.
(define (mklist2 bind pure args)
(define (helper bnd pr ttl lst)
(cond [(empty? lst) (pure ttl)]
[else (define (func t) (helper bnd pr (append ttl (list t)) (rest lst)))
(bind (first lst) func)])
)
(helper bind pure empty args))
Given a sample factorial program -
(define fact
(lambda (n)
(if (= n 0)
1
(* n (fact (- n 1)))))) ;; goal: remove reference to `fact`
(print (fact 7)) ; 5040
Above fact is (lambda (n) ...) and when we call fact we are asking for this lambda so we can reapply it with new arguments. lambda are nameless and if we cannot use top-level define bindings, the only way to bind a variable is using a lambda's parameter. Imagine something like -
(lambda (r)
; ...lambda body...
; call (r ...) to recur this lambda
)
We just need something to make our (lambda (r) ...) behave this way -
(something (lambda (r)
(print 1)
(r)))
; 1
; 1
; 1
; ... forever
introducing U
This something is quite close to the U combinator -
(define u
(lambda (f) (f f)))
(define fact
(lambda (r) ;; wrap in (lambda (r) ...)
(lambda (n)
(if (= n 0)
1
(* n ((r r) (- n 1))))))) ;; replace fact with (r r)
(print ((u fact) 7))
; => 5040
And now that recursion is happening thru use of a parameter, we could effectively remove all define bindings and write it using only lambda -
; ((u fact) 7)
(print (((lambda (f) (f f)) ; u
(lambda (r) ; fact
(lambda (n)
(if (= n 0)
1
(* n ((r r) (- n 1)))))))
7))
; => 5040
Why U when you can Y?
The U-combinator is simple but having to call ((r r) ...) inside the function is cumbersome. It'd be nice if you could call (r ...) to recur directly. This is exactly what the Y-combinator does -
(define y
(lambda (f)
(f (lambda (x) ((y f) x))))) ;; pass (y f) to user lambda
(define fact
(lambda (recur)
(lambda (n)
(if (= n 0)
1
(* n (recur (- n 1))))))) ;; recur directly
(print ((y fact) 7))
; => 5040
But see how y has a by-name recursive definition? We can use u to remove the by-name reference and recur using a lambda parameter instead. The same as we did above -
(define u
(lambda (f) (f f)))
(define y
(lambda (r) ;; wrap in (lambda (r) ...)
(lambda (f)
(f (lambda (x) (((r r) f) x)))))) ;; replace y with (r r)
(define fact
(lambda (recur)
(lambda (n)
(if (= n 0)
1
(* n (recur (- n 1)))))))
(print (((u y) fact) 7)) ;; replace y with (u y)
; => 5040
We can write it now using only lambda -
; (((u y) fact) 7)
(print ((((lambda (f) (f f)) ; u
(lambda (r) ; y
(lambda (f)
(f (lambda (x) (((r r) f) x))))))
(lambda (recur) ; fact
(lambda (n)
(if (= n 0)
1
(* n (recur (- n 1)))))))
7))
; => 5040
need more parameters?
By using currying, we can expand our functions to support more parameters, if needed -
(define range
(lambda (r)
(lambda (start)
(lambda (end)
(if (> start end)
null
(cons start ((r (add1 start)) end)))))))
(define map
(lambda (r)
(lambda (f)
(lambda (l)
(if (null? l)
null
(cons (f (car l))
((r f) (cdr l))))))))
(define nums
((((u y) range) 3) 9))
(define squares
((((u y) map) (lambda (x) (* x x))) nums))
(print squares)
; '(9 16 25 36 49 64 81)
And as a single lambda expression -
; ((((u y) map) (lambda (x) (* x x))) ((((u y) range) 3) 9))
(print (((((lambda (f) (f f)) ; u
(lambda (r) ; y
(lambda (f)
(f (lambda (x) (((r r) f) x))))))
(lambda (r) ; map
(lambda (f)
(lambda (l)
(if (null? l)
null
(cons (f (car l))
((r f) (cdr l))))))))
(lambda (x) (* x x))) ; square
(((((lambda (f) (f f)) ; u
(lambda (r) ; y
(lambda (f)
(f (lambda (x) (((r r) f) x))))))
(lambda (r) ; range
(lambda (start)
(lambda (end)
(if (> start end)
null
(cons start ((r (add1 start)) end)))))))
3) ; start
9))) ; end
; => '(9 16 25 36 49 64 81)
lazY
Check out these cool implementations of y using lazy
#lang lazy
(define y
(lambda (f)
(f (y f))))
#lang lazy
(define y
((lambda (f) (f f)) ; u
(lambda (r)
(lambda (f)
(f ((r r) f))))))
#lang lazy
(define y
((lambda (r)
(lambda (f)
(f ((r r) f))))
(lambda (r)
(lambda (f)
(f ((r r) f))))))
In response to #alinsoar's answer, I just wanted to show that Typed Racket's type system can express the Y combinator, if you put the proper type annotations using Rec types.
The U combinator requires a Rec type for its argument:
(: u (All (a) (-> (Rec F (-> F a)) a)))
(define u
(lambda (f) (f f)))
The Y combinator itself doesn't need a Rec in its type:
(: y (All (a b) (-> (-> (-> a b) (-> a b)) (-> a b))))
However, the definition of the Y combinator requires a Rec type annotation on one of the functions used within it:
(: y (All (a b) (-> (-> (-> a b) (-> a b)) (-> a b))))
(define y
(lambda (f)
(u (lambda ([g : (Rec G (-> G (-> a b)))])
(f (lambda (x) ((g g) x)))))))
Recursion using only lambdas can be done using fixed point combinators, the simplest one being Ω.
However, take into account that such a combinator has a type of infinite length, so if you program with types, the type is recursive and has infinite length. Not every type checker is able to compute the type for recursive types. The type checker of Racket I think it's Hindley-Miller and I remember typed racket it's not able to run fixed point combinators, but not sure. You have to disable the type checker for this to work.
I am writing a function called count-if, which takes in a predicate, p?, and a list, ls. The function returns the number of occurrences of elements in the nested list that satisfy p?
For example: (count-if (lambda (x) (eq? 'z x)) '((f x) z (((z x c v z) (y))))) will return 3. This is what I have written:
(define (count-if p ls) (cond
((null? ls) '())
((p (car ls))
(+ 1 (count-if p (cdr ls))))
(else
(count-if p (cdr ls)))))
But I just get an error. I could use some help finding a better way to go about this problem. Thanks!
What is the signature of count-if? It is:
[X] [X -> Boolean] [List-of X] -> Number
What does the first cond clause return? It returns:
'()
This is a simple type error. Just change the base case to 0 and count-if works.
Edit (for nested).
First we define the structure of the date as Nested.
A symbol is just fed into the score helper function. Otherwise the recursive call is applied on all nested sub-nesteds, and the results are summed up.
#lang racket
; Nested is one of:
; - Number
; - [List-of Nested]
; Nested -> Number
(define (count-if pred inp)
; Symbol -> Number
(define (score n) (if (pred n) 1 0))
; Nested -> Number
(define (count-if-h inp)
(if (symbol? inp)
(score inp)
(apply + (map count-if-h inp))))
(count-if-h inp))
(count-if (lambda (x) (eq? 'z x)) '((f x) z (((z x c v z) (y)))))
; => 3
Dynamic versus lexical scope.
; One expects lexical scope.
(let (( a '(a)))
(defun func1 (x)
(setq a (cons x (cons (func2 x) a))))
(defun func2 (y)
(setq a (cons y a))))
(func1 'b)
=> (B (B A) B A)
Doing it lexically, one would expect
the following.
Substitute (a) for the a in func2.
func2 is called with x, i.e. the value b.
func2 also attaches the value of a with (a).
So the (cons y a) evaluates to (b a).
(setq a (cons y a))) is (b a).
So func1 will cons (b a) with (a).
x is then consed (b (b a) a)).
End result (b (b a) a)? Is this a contradiction?
Let us try a dynamical version.
; dynamic scope
(defparameter a '(a))
(defun func1 (x)
(setq a (cons x (cons (func2 x) a))))
(defun func2 (y)
(setq a (cons y a)))
(func1 'b)
=>(B (B A) B A)
This works as is to be expected but is the same as in lexical scope?
But the following is not accepted at all.
; This won't work.
(let (( a '(a)))
(defun func1 (x)
(declare (special a))
(setq a (cons x (cons (func2 x) a))))
(defun func2 (y)
(declare (special a))
(setq a (cons y a))))
(func1 'b)
Error: Attempt to take the value of the unbound variable `A'.
What is going on?
Thanks for the keen eyes. This example is from a 31 years old printed Lisp textbook straight out of the chapter "dynamic versus lexical scoping". The explanation comes also straight out of that book. I guess that the lexical scoping was not checked, because the authors explicitly warn the readers that lexical scoping was not done in Lisp. I am happy that this is solved. I stared some time on it, without understanding what was really going on. It seemed to be an odd contradiction.
(define-struct pizza (size toppings))
;; Constants for testing
(define (meat item)
(symbol=? 'meat item))
(define (tomatoes item)
(symbol=? 'tomatoes item))
(define (cheese item)
(symbol=? 'cheese item))
(define (pepperoni item)
(symbol=? 'pepperoni item))
(define (hot-peppers item)
(symbol=? 'hot-peppers item))
(define (count-toppings order topping)
(cond [(empty? order) 0]
[else
(local
[(define (single-pizza-tops pizza top)
(length (filter top (pizza-toppings pizza))))
(define (list-of-nums lop tops)
(list (single-pizza-tops (first lop) tops)
(single-pizza-tops (first (rest lop)) tops)
(single-pizza-tops (first (rest (rest lop))) tops)))]
(foldr + 0 (list-of-nums order topping)))]))
Turns out my code works fine with the defined constants, but count-toppings wont work with a symbol for 'topping?
Does anyone know a way to modify my filter function so that if I input a symbol for toppings, this code will work the same way?
Map and filter can be implemented in terms of foldr and cons. Since you aren't building a list you can disregard filter and map. In general though to map recursion to higher-order function you can look at type signatures. The more difficult way is to manually match your code to that of the functions.
Map takes a list, a function or arity one, and returns a list of the function mapped to each element of the list or (a -> b) -> [a] -> [b] in Haskell notaion.
(define (map f L) ;niave implementation pared down for simplicity
(if (null? L)
'()
(cons (f (car L)) (map f (cdr L)))))
Filter takes a predicate of arity one, and a list, and returns a list that safisfies that predicate. or (a -> bool) -> [a] -> [a] in Haskell.
(define (filter pred L) ;dirro
(cond ((null? L) '())
((pred (car L))
(cons (car L)
(filter pred (cdr L))))
(else (filter pred (cdr L)))))
Foldr takes an a function that that has arity two, an accumulator value, and a list and returns the accumulator. or (a -> b -> b) -> b -> [a] -> b in haskell.
(define (foldr kons knil L) ;ditto
(if (null? L)
knil
(kons (car L) (foldr kons knil (cdr L)))))
So the trick of it at first is assuaging the argument from your function to fit. In both your funcitons you have a cond clause [(empty? topping-list) 0], which suggests knil should be 0.
In count-topping's else statement you call +, which at first glance suggests kons should be a +, however your list isn't numbers directly, meaning youll have to wrap in in a lambda statement, or create a helper function. (lambda (x acc) (+ (single-pizza-toppings (pizza-toppings x) atop) acc))
To put it together
(define (count-topping alop atop)
(foldr (lambda (x acc)
(+ (single-pizza-toppings (pizza-toppings x) atop)
acc))
0
alop))
Now the interesting one, single-pizza-toppings will look very similar. Execpt that the lambda statement will contain an if statment that returns 1 if x is a symbol equal to topping and 0 otherwise. Or you can do something even simpler.
(define (single-pizza-toppings topping-list topping)
(foldr (lambda (x acc)
(+ 1 acc))
0
(filter (lammba (x) (symbol=? x topping))
topping-list)))
That filter filter insures every x going to the foldr is a topping so you can just ignore it and add to the accumulator.
Assuming that we have the first, we can define the second by
Count the occurrences of the topping in each pizza using the first function, by way of map
Compute the sum of the resulting list
That is,
(define (count-toppings pizzas topping)
(sum (map (lambda (p) (single-pizza-toppings (pizza-toppings p) topping)) pizzas)))
For the first function, we can use filter to get a list of all occurrences of the given topping.
The number of occurrences is the length of the result:
(define (single-pizza-toppings toppings topping)
(length (filter (lambda (t) (symbol=? t topping)) toppings)))
Both functions consist of a transformation of the input into the data we're interested in, map and filter, followed by a "reduction", sum and length.
This is a very common pattern.
And if you don't have sum:
(define (sum ts)
(foldr (lambda (x acc) (+ x acc)) 0 ts))
Looks like your first step will be to put together a complete set of test cases. If you're using DrRacket, you might want to enable "Syntactic Test Suite Coverage" in the "Choose Language..." menu to make sure you have a good set of tests. That's the first step....