Threading functions - scheme

Is there a simpler way to achieve threading functionality in racket? I know about the threading library but it seems like such a basic functionality that I wonder if there is not some builtin way to do this.
(define (thread x . fns)
(foldl (lambda (f a) (f a))
thread
fns))
Also, can you express (lambda (f a) (f a)) in a simpler fashion?

There are lots of ways of doing this. A nice one is to use a macro, a simple (and perhaps not completely correct) version of which is:
(define-syntax (/> stx)
(syntax-case stx ()
[(_ x)
#'x]
[(_ x f)
#'(f x)]
[(/> x f fs ...)
#'(/> (f x) fs ...)]
[/>
(identifier? #'/>)
#'(λ (x . fns)
(for/fold ([r x]) ([f fns])
(f r)))]))
Now, for instance (/> x sin cos) is expanded to (cos (sin x)): there is no run-time overhead at all. The last clause means that (apply /> 1 (list sin cos)) will work.
I'm not sure the above macro is completely correct, particularly the last clause.

Related

Why does "disj" from miniKanren work in Scheme but not in Racket?

I was working with the minikanren library for Racket, but wanted to use the "disj" and "conj" operators. I want to be able to more explicitly declare whether I am using disj or conj for the sake of legibility rather than have to parse through a conde expression, especially once the expressions become more complicated. I copied the source from "The Reasoned Schemer":
(define (append∞ s∞ t∞)
(cond
((null? s∞) t∞)
((pair? s∞)
(cons (car s∞)
(append∞ (cdr s∞) t∞)))
(else (λ ()
(append∞ t∞ (s∞))))))
(define (disj2 g1 g2)
(λ (s)
(append∞ (g1 s) (g2 s))))
(define-syntax disj
(syntax-rules ()
[(disj) '()]
[(disj g) g]
[(disj g0 g ...) (disj2 g0 (disj g ...))]))
This works properly with the first two cases
> (run* (x) (disj (== 'foo x)))
'(foo)
but only returns the first result when using more than one goal:
> (run* (x) (disj (== 'foo x) (== 'bar x) (== 'foobar x)))
'(foo)
Why is this?
Hrmph. I can't seem to reproduce that behavior.
When I clone the TRS/2e repo, add both
#lang racket
(provide (all-defined-out))
to the top of trs2-impl.scm, run that file, and then try your test program I see the expected result:
;
; Welcome to Racket v7.9.0.3 [cs].
;
trs2-impl.scm> (run* (x) (disj (== 'foo x) (== 'bar x) (== 'foobar x)))
'((foo) (bar) (foobar))
Do you see different behavior? If so, then we could look deeper. Do you know which version of Racket you're using? I don't think that will matter, but just in case.

How to fix the 'cannot change constant' error

I have this code so far
(define (max f g)
(define (int-max x y)
(if (> x y) x y))
(lambda (x) (int-max (f x) (g x))))
it gives me the error define-values: assignment disallowed;
cannot change constant
constant: max
I'm not sure how to fix this or what it means.
In DrRacket in the bottom left there is a dropdown where you can select lanaguage. From there you can select "Choose language" and click "Show details". For legacy languages such as R5RS you have the option "Disallow redefinition of initial bindings".
Now according to the R5RS your redefinition can only extend the functionality and that for the data types the original binding worked with should work the same in the new definition. The reason for this is the ability to constant fold the code. Thus the code below is invalid:
(define + -)
(+ 5 3)
; ==> 7
This might look strange but the program is in violation with the report and because of that the result might as well have been the string "banana" as far as the report is concerned. In R5RS you need to make it compatible for it to be Scheme:
(define numeric-max max)
(define max
(lambda (v1 . vs)
(if (number? v1)
(apply numeric-max v1 vs)
(lambda (x) (numeric-max (v1 x) ((car vs) x))))))
With R6RS you are free of this by not importing the binding at all:
#!r6rs
(import (except (rnrs base) max))
(define (max f g)
(define (int-max x y)
(if (> x y) x y))
(lambda (x) (int-max (f x) (g x))))
If you want to make max available you can do the same as in R5RS with named imports:
#!r6rs
(import (except (rnrs base) max)
(only (rnrs control) case-lambda)
(rename (rnrs base) (max numeric-max)))
(define max
(case-lambda
((v1 v2)
(if (number? v1)
(numeric-max v1 v2)
(lambda (x) (numeric-max (v1 x) (v2 x)))))
(args
(apply numeric-max args))))
And of coruse this works in #lang racket as well:
#lang racket
(require (rename-in racket/base [max numeric-max]))
(define max
(case-lambda
((v1 v2)
(if (number? v1)
(numeric-max v1 v2)
(lambda (x) (numeric-max (v1 x) (v2 x)))))
(args
(apply numeric-max args))))
The problem you are facing is that max is already defined and you are trying to re-define it.
More importantly, name max is not appropriate for what you are trying to use it for. You are calling max with couple of arguments that are functions. It returns a lambda that can be invoked with a variable.
Your envisioning usage such as
((max sin cos) 10)
A name such as max-proc-value would be more appropriate and will avoid the problem that you have run into.
If you put this in the definition window (the upper one) everything works.
#lang racket
(define (max f g)
(define (int-max x y)
(if (> x y) x y))
(lambda (x) (int-max (f x) (g x))))

Understanding extra arguments in the Y Combinator in Scheme

According to RosettaCode, the Y Combinator in Scheme is implemented as
(define Y
(λ (h)
((λ (x) (x x))
(λ (g)
(h (λ args (apply (g g) args)))))))
Of course, the traditional Y Combinator is λf.(λx. f(x x))(λx. f(x x))
My question, then, is about h and args, which don't appear in the mathematical definition, and about apply, which seems like it should either be in both halves of the Combinator or in neither.
Can someone help me understand what is going on here?
Lets start off with the lambda calculus version traslated to Scheme:
(λ (f)
((λ (x) (f (x x)))
(λ (x) (f (x x)))))
I'd like to simplify this since I see (λ (x) (f x x)) is repeated twice. You can substitute the beginning there to this:
(λ (f)
((λ (b) (b b))
(λ (x) (f (x x)))))
Scheme is an eager language so it will go into an infinite loop. In order to avoid that we make a proxy.. Imagine you have + that takes two numbers, you can substitute it with (λ (a b) (+ a b)) without the result being changed. Lets do that with the code:
(λ (f)
((λ (b) (b b))
(λ (x) (f (λ (p) ((x x) p))))))
Actully this has its own name. It's called the Z combinator. (x x) is not done when f is applied only when the supplied proxy is applied. Delayed one step. It might look strange but I know (x x) becomes a function so this is exactly the same as my + substitution above.
In Lambda calculus all functions takes one argument. If you see f x y it's actually the same as ((f x) y) in Scheme. If you want it to work with functions of all arities your substitution needs to reflect that. In Scheme we have rest arguments and apply to do this.
(λ (f)
((λ (b) (b b))
(λ (x) (f (λ p (apply (x x) p))))))
This isn't neede if you only are going to use one arity functions as in lambda calculus.
Notice that in your code you use h instead of f. It doesn't really matter what you call the variables. This is the same code with different names. So this is the same:
(λ (rec-fun)
((λ (yfun) (yfun yfun))
(λ (self) (rec-fun (λ args (apply (self self) args))))))
Needless to say (yfun yfun) and (self self) does the same thing.

The code of the build-in Scheme procedure "pair?"

I started to study the Scheme and curious of how the built-in procedure "pair?" works. I mean the code obviously, since I couldn't find a way to see the code of the built-in procedures and don't know how to write it I'm here.
Had the same question with the "List?" procedure but managed to write it myself, but in case of "pair?" have no idea. Thx!
I think you're looking for the implementation of the 'pair?' primitive in Racket. If so: it's currently in list.c:
https://github.com/racket/racket/blob/master/racket/src/racket/src/list.c
Specifically, look at the definition of pair_p_prim.
Hope this helps!
EDIT: why isn't it written in Racket?
Answer: pair? is a primitive in Racket and Scheme. This means that in Racket, it's not implemented in Racket, it's implemented in the language that Racket is implemented in. For this part of the language, that's C. Keep in mind that this can change; if the Racket implementation gets updated to provide a lower-level set of primitives, then the pair? function might no longer be a primitive. Finally, it's worth noting that for some languages, implementors leverage the existence of an older compiler in order to provide a 'bootstrapping' implementation where the implementation language is the same as the language
being developed.
Hope this helps!
pair? can be implemented in Scheme; Scheme is Turing complete, my friend!
But instead of doing your hw for you and to get your head spinning I will encode pair? in the lambda calculus using Scheme; from here, follow the white rabbit!
cpair? = λm. m (λx. λy. tru) fls
In Scheme:
(define c-pair?
(lambda (m)
((m (lambda (x) (lambda (y) tru))) (lambda (x) fls))))
(define tru
(lambda (t) (lambda (f) t)))
(define fls
(lambda (t) (lambda (f) f)))
Procedures for testing:
(define kons
(lambda (h)
(lambda (t)
(lambda (c)
(lambda (n)
((c h) ((t c) n)))))))
(define c-equal?
(lambda (m)
(lambda (n)
((c-and (iszero ((m prd) n)))
(iszero ((n prd) m))))))
(define c-and
(lambda (b)
(lambda (c)
((b c) fls))))
(define iszero (lambda (m) ((m (lambda (x) fls)) tru)))
(define prd (lambda (m) (fst ((m ss) zz))))
(define fst (lambda (p) (p tru)))
;; church-boolean -> real boolean
(define real-bool (lambda (b) ((b true) false)))
(define nil (lambda (c) (lambda (n) n)))
;; representation of number 1
(define c1 (lambda (s) (lambda (z) (s z))))
Test:
;; some list - in Scheme this would be: (cons 1 '())
(define d ((kons c1) nil)
(real-bool ((c-equal? (c-pair? d)) tru)) ;; -> #t
(real-bool ((c-equal? (c-pair? c1)) fls)) ;; -> #f
In other words; you can definitely write pair? in Scheme even if pair? is a primitive.

Why Scheme requires apply in Y-combinator implementation, but Racket doesn't?

Here is the Y-combinator in Racket:
#lang lazy
(define Y (λ(f)((λ(x)(f (x x)))(λ(x)(f (x x))))))
(define Fact
(Y (λ(fact) (λ(n) (if (zero? n) 1 (* n (fact (- n 1))))))))
(define Fib
(Y (λ(fib) (λ(n) (if (<= n 1) n (+ (fib (- n 1)) (fib (- n 2))))))))
Here is the Y-combinator in Scheme:
(define Y
(lambda (f)
((lambda (x) (x x))
(lambda (g)
(f (lambda args (apply (g g) args)))))))
(define fac
(Y
(lambda (f)
(lambda (x)
(if (< x 2)
1
(* x (f (- x 1))))))))
(define fib
(Y
(lambda (f)
(lambda (x)
(if (< x 2)
x
(+ (f (- x 1)) (f (- x 2))))))))
(display (fac 6))
(newline)
(display (fib 6))
(newline)
My question is: Why does Scheme require the apply function but Racket does not?
Racket is very close to plain Scheme for most purposes, and for this example, they're the same. But the real difference between the two versions is the need for a delaying wrapper which is needed in a strict language (Scheme and Racket), but not in a lazy one (Lazy Racket, a different language).
That wrapper is put around the (x x) or (g g) -- what we know about this thing is that evaluating it will get you into an infinite loop, and we also know that it's going to be the resulting (recursive) function. Because it's a function, we can delay its evaluation with a lambda: instead of (x x) use (lambda (a) ((x x) a)). This works fine, but it has another assumption -- that the wrapped function takes a single argument. We could just as well wrap it with a function of two arguments: (lambda (a b) ((x x) a b)) but that won't work in other cases too. The solution is to use a rest argument (args) and use apply, therefore making the wrapper accept any number of arguments and pass them along to the recursive function. Strictly speaking, it's not required always, it's "only" required if you want to be able to produce recursive functions of any arity.
On the other hand, you have the Lazy Racket code, which is, as I said above, a different language -- one with call-by-need semantics. Since this language is lazy, there is no need to wrap the infinitely-looping (x x) expression, it's used as-is. And since no wrapper is required, there is no need to deal with the number of arguments, therefore no need for apply. In fact, the lazy version doesn't even need the assumption that you're generating a function value -- it can generate any value. For example, this:
(Y (lambda (ones) (cons 1 ones)))
works fine and returns an infinite list of 1s. To see this, try
(!! (take 20 (Y (lambda (ones) (cons 1 ones)))))
(Note that the !! is needed to "force" the resulting value recursively, since Lazy Racket doesn't evaluate recursively by default. Also, note the use of take -- without it, Racket will try to create that infinite list, which will not get anywhere.)
Scheme does not require apply function. you use apply to accept more than one argument.
in the factorial case, here is my implementation which does not require apply
;;2013/11/29
(define (Fact-maker f)
(lambda (n)
(cond ((= n 0) 1)
(else (* n (f (- n 1)))))))
(define (fib-maker f)
(lambda (n)
(cond ((or (= n 0) (= n 1)) 1)
(else
(+ (f (- n 1))
(f (- n 2)))))))
(define (Y F)
((lambda (procedure)
(F (lambda (x) ((procedure procedure) x))))
(lambda (procedure)
(F (lambda (x) ((procedure procedure) x))))))

Resources