SRFI 105 as a Racket language, how to parse include files? - scheme

i'm porting SRFI 105 "Curly infix" to Racket.
I wrote a "reader" that works and the SRFI 105 is packaged with a REPL that works already with little change (only one line modified as far as ia can remember) but i'm facing a difficulty, being not easy with the Racket ecosytem of building lanaguages:
-first how can i make my implementation parse, not only the main program, but possibly include files? i.e if i have a (include "infix-file.scm") i want the reader/parser to load and parse it before the expansion step which is too late and more difficult
here the beginning of my specialised code (the rest is as the official SRFI 105) file SRFI-105.rkt:
#lang racket
(require syntax/strip-context)
(provide (rename-out [literal-read read]
[literal-read-syntax read-syntax]))
(define (literal-read in)
(syntax->datum
(literal-read-syntax #f in)))
(define (literal-read-syntax src in)
(define lst-code (process-input-code-rec in))
`(module anything racket ,#lst-code))
;; read all the expression of program
;; a tail recursive version
(define (process-input-code-tail-rec in) ;; in: port
(define (process-input acc)
(define result (curly-infix-read in)) ;; read an expression
(if (eof-object? result)
(reverse acc)
(process-input (cons result acc))))
(process-input '()))
; ------------------------------
; Curly-infix support procedures
; ------------------------------
and here is an example of source file using it:
#lang reader "SRFI-105.rkt"
(- (+ 3 3)
{2 + 2})
{5 + 2}
(define (fibonacci n)
(if (< n 2)
n
(+ (fibonacci (- n 1)) (fibonacci (- n 2)))))
(fibonacci 7)
(define (fib n)
(if {n < 2}
n
{(fib {n - 1}) + (fib {n - 2})} ))
(fib 11)
and the obvious results:
Welcome to DrRacket, version 8.2 [cs].
Language: reader "SRFI-105.rkt", with debugging; memory limit: 128 MB.
2
7
13
89
>
-second, i know how to make a #lang "my language.rkt" parse the following code but i do not know how to integrate the working SRFI 105 REPL in Racket ecosystem (for now it works in a separate file than parser).
here the official SRFI 105 that already work in Racket with minor changes:
; --------------
; Demo of reader
; --------------
(define-namespace-anchor a)
(define ns (namespace-anchor->namespace a))
;{1 + 1}
;(+ 1 1)
;2
;(define k {1 + 1})
;(define k (+ 1 1))
;#<void>
;k
;k
;2
; repeatedly read in curly-infix and write traditional s-expression.
(define (process-input)
(let ((result (curly-infix-read)))
(cond ((not (eof-object? result))
(let ((rv (eval result ns)))
(write result) (display "\n")
(write rv)
(display "\n"))
;; (force-output) ; flush, so can interactively control something else
(process-input)) ;; no else clause or other
)))
(process-input)
Damien

a possible solution is to use 'require' instead of 'include' for loading a source file from another and adding one more
#lang reader "SRFI-105.rkt" at the beginning of each loaded file.
example of main file loading another .rkt file
#lang reader "SRFI-105.rkt"
(require "examples-curly-infix2.rkt")
(- (+ 3 3)
{2 + 2})
{5 + 2}
(define (fibonacci n)
(if (< n 2)
n
(+ (fibonacci (- n 1)) (fibonacci (- n 2)))))
(fibonacci 7)
(define (fib n)
(if {n < 2}
n
{(fib {n - 1}) + (fib {n - 2})} ))
(fib 11)
and here is the loaded file:
#lang reader "SRFI-105.rkt"
{7 * 3}
execution will output this:
Welcome to DrRacket, version 8.2 [cs].
Language: reader "SRFI-105.rkt", with debugging; memory limit: 128 MB.
21
2
7
13
89
21 is coming from the 'required' file,
note that instead of include you can not control at which line number the file will be loaded with require (they are loaded at the beginning)

Related

How to implement Fibonacci with generators?

I'm trying to implement generators to make a list of fibonacci numbers in Scheme, but i can't do it.
I have two functions, the first is a function that returns the Fibonacci numbers in the form of a list and the second is the generator function.
What I have to do is finally transform the Fibonacci function into a generator from a list of Fibonacci numbers.
;FIBONACCI NUMBERS
(define (fib n a b i)
(if
(= i n)
(list b)
(cons b (fib n b (+ a b) (+ i 1)))
)
)
(define (fibonacci n)
(cond
((= n 1) (list 1))
(else (fib n 0 1 1))
)
)
;GENERATOR
(define (generator start stop step)
(let ((current (- start 1)))
(lambda ()
(cond ((>= current stop) #f)
(else
(set! current (+ current step))
current)))))
(define (next generator)
(generator))
When you write generators people will think about the concept of generators in other lamnguages which can easily be implemented in Scheme withcall/cc.
(define-coroutine (fib)
(let loop ((a 0) (b 1))
(yield a)
(loop b (+ a b))))
(fib) ; ==> 0
(fib) ; ==> 1
(fib) ; ==> 1
(fib) ; ==> 2
(fib) ; ==> 3
Now this is kind of like making a stepper out of an iteration. It's up there with streams and transducers. You can make mapping functions that compose operations in series which does the calculations per item instead of doing separate processes generating lots of collections in between each one like chaining map would do. One of the big things in JavaScript the last years has been linked to generators since an early version of await and async were a combination of generators and promises.
Now if you are thinking more in the more general sense a procedure that proces the next value. You could have that as well:
(define fib
(let ((a 0) (b 1))
(lambda ()
(let ((result a))
(set! a b)
(set! b (+ result b))
result))))
(fib) ; ==> 0
(fib) ; ==> 1
(fib) ; ==> 1
(fib) ; ==> 2
(fib) ; ==> 3
As you see this does the deed by updating private bindings. It's more OO than the fancy real generators.
Since Sylwester mentioned streams, here's a stream solution -
(define fib
(stream-cons 0
(stream-cons 1
(stream-add fib
(stream-rest fib)))))
(stream->list (stream-take fib 20))
; '(0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181)
stream-add will add two (2) streams together using + and stream primitives -
(define (stream-add s1 s2)
(if (or (stream-empty? s1)
(stream-empty? s2))
empty-stream
(stream-cons (+ (stream-first s1)
(stream-first s2))
(stream-add (stream-rest s1)
(stream-rest s2)))))
Or you can take a more generalised approach that allows use of any procedure and any number of streams -
(define ((stream-lift f) . s)
(if (ormap stream-empty? s)
empty-stream
(stream-cons (apply f (map stream-first s))
(apply (stream-lift f) (map stream-rest s)))))
(define stream-add (stream-lift +))

Increment and Decrement operators in scheme programming language

What are the increment and decrement operators in scheme programming language.
I am using "Dr.Racket" and it is not accepting -1+ and 1+ as operators.
And, I have also tried incf and decf, but no use.
They are not defined as such since Scheme and Racket try to avoid mutation; but you can easily define them yourself:
(define-syntax incf
(syntax-rules ()
((_ x) (begin (set! x (+ x 1)) x))
((_ x n) (begin (set! x (+ x n)) x))))
(define-syntax decf
(syntax-rules ()
((_ x) (incf x -1))
((_ x n) (incf x (- n)))))
then
> (define v 0)
> (incf v)
1
> v
1
> (decf v 2)
-1
> v
-1
Note that these are syntactic extensions (a.k.a. macros) rather than plain procedures because Scheme does not pass parameters by reference.
Your reference to “DrRacket” somewhat suggests you’re in Racket. According to this, you may already be effectively using #lang racket. Either way, you’re probably looking for add1 and sub1.
-> (add1 3)
4
-> (sub1 3)
2
The operators 1+ and -1+ do /not/ mutate, as a simple experiment in MIT Scheme will show:
1 ]=> (define a 3)
;Value: a
1 ]=> (1+ a)
;Value: 4
1 ]=> (-1+ a)
;Value: 2
1 ]=> a
;Value: 3
So you can implement your own function or syntactic extensions of those functions by having them evaluate to (+ arg 1) and (- arg 1) respectively.
It's easy to just define simple functions like these yourself.
;; Use: (increment x)
;; Before: x is a number
;; Value: x+1
(define (increment x)
(+ 1 x)
)

Tonumber function (tonumber ‘(one two three) --> 123

After the solution of how to spell a number in racket? (spellNum) ,now I am trying to write a function which is opposite of this function. i.e
(tonumber ‘(one two three) --> 123
so far I have written this working code
(define (symbol->digit n)
(case n
('zero 0)
('one 1)
('two 2)
('three 3)
('four 4)
('five 5)
('six 6)
('seven 7)
('eight 8)
('nine 9)
(else (error "unknown symbol:" n))))
(define (numlist n)
(map symbol->digit n))
(numlist '(one two three))
From numlist, I got '(1 2 3). But to there is some problem in the function below in which I want to convert list to number
(define (list->number l)
(set! multiplier (* 10 (lenght l)))
(for/list [(c l)]
(* multiplier c))
(set! multiplier (/ multiplier 10)))
(list->number '(1 2 3))
any help will be appreciated. I can't find documentation of all kind of loops online. at
http://docs.racket-lang.org/ts-reference/special-forms.html?q=loop#%28part._.Loops%29
I want to become familiar with Racket so I want to avoid builtin conversion functions. In list->number,I am trying to take digits one by one from list and then i want to multiply them with 10,100,1000 so on depending on the length of list. so that it can return a number. For example '(1 2 3) = 1*100+2*10+3*1
Here's the exact opposite of my previous solution, once again using tail recursion for the list->number procedure:
(define (symbol->digit n)
(case n
('zero 0)
('one 1)
('two 2)
('three 3)
('four 4)
('five 5)
('six 6)
('seven 7)
('eight 8)
('nine 9)
(else (error "unknown symbol:" n))))
(define (list->number lst)
(let loop ((acc 0) (lst lst))
(if (null? lst)
acc
(loop (+ (car lst) (* 10 acc)) (cdr lst)))))
(define (toNumber lst)
(list->number (map symbol->digit lst)))
It works as expected:
(toNumber '(four six seven))
=> 467
Just for fun, in Racket we can write a function like list->number using iteration and comprehensions. Even so, notice that we don't use set! anywhere, mutating state is the norm in a language like Python but in Scheme in general and Racket in particular we try to avoid modifying variables inside a loop - there are more elegant ways to express a solution:
(define (list->number lst)
(for/fold ([acc 0]) ([e lst])
(+ e (* 10 acc))))
(define (symbol->digit n)
(case n
('zero "0")
('one "1")
('two "2")
('three "3")
('four "4")
('five "5")
('six "6")
('seven "7")
('eight "8")
('nine "9")
(else (error "unknown symbol:" n))))
(define (symbols->number symb)
(string->number (string-join (map symbol->digit symb) "")))
(symbols->number '(one two three))
Lots of ways to skin a cat. Here is version that uses fold-left. Like Óscar's solution it uses math rather than chars and strings.
#!r6rs
(import (rnrs))
;; converts list with worded digits into
;; what number they represent.
;; (words->number '(one two zero)) ==> 120
(define (words->number lst)
(fold-left (lambda (acc x)
(+ x (* acc 10)))
0
(map symbol->digit lst)))
For a #!racket version just rename fold-left to foldl and switch the order of x and acc.

How to write parallel-map using Places?

I would like to have a parallel-map function implemented in Racket. Places seem like the right thing to build off of, but they're uncharted territory for me. I'm thinking the code should look something like shown below.
#lang racket
; return xs split into n sublists
(define (chunk-into n xs)
(define N (length xs))
(cond [(= 1 n) (list xs)]
[(> n N)
(cons empty
(chunk-into (sub1 n) xs))]
[else
(define m (ceiling (/ N n)))
(cons (take xs m)
(chunk-into (sub1 n) (drop xs m)))]))
(module+ test
(check-equal? (length (chunk-into 4 (range 5))) 4)
(check-equal? (length (chunk-into 2 (range 5))) 2))
(define (parallel-map f xs)
(define n-cores (processor-count))
(define xs* (chunk-into n-cores xs))
(define ps
(for/list ([i n-cores])
(place ch
(place-channel-put
ch
(map f
(place-channel-get ch))))))
(apply append (map place-channel-put ps xs*)))
This gives the error:
f: identifier used out of context in: f
All of the examples I've seen show a design pattern of providing a main function with no arguments which somehow get's used to instantiate additional places, but that's really cumbersome to use, so I'm actively trying to avoid it. Is this possible?
Note: I also tried to make a parallel-map using futures. Unfortunately, for all my tests it was actually slower than map (I tried testing using a recursive process version of fib), but here it is in case you have any suggestions for making it faster.
(define (parallel-map f xs)
(define xs** (chunk-into (processor-count) xs))
(define fs (map (λ (xs*) (future (thunk (map f xs*)))) xs**))
(apply append (map touch fs)))
I have used places before but never had to pass a function as a parameter to a place. I was able to come up with the following, rather crufty code, which uses eval:
#!/usr/bin/env racket
#lang racket
(define (worker pch)
(define my-id (place-channel-get pch)) ; get worker id
(define wch-w (place-channel-get pch)) ; get work channel (shared between controller and all workers) - worker side
(define f (place-channel-get pch)) ; get function
(define ns (make-base-namespace)) ; for eval
(let loop ()
(define n (place-channel-get wch-w)) ; get work order
(let ((res (eval `(,f ,n) ns))) ; need to use eval here !!
(eprintf "~a says ~a\n" my-id res)
(place-channel-put wch-w res) ; put response
(loop)))) ; loop forever
(define (parallel-map f xs)
(define l (length xs))
(define-values (wch-c wch-w) (place-channel)) ; create channel (2 endpoints) for work dispatch (a.k.a. shared queue)
(for ((i (in-range (processor-count))))
(define p (place pch (worker pch))) ; create place
(place-channel-put p (format "worker_~a" i)) ; give worker id
(place-channel-put p wch-w) ; give response channel
(place-channel-put p f)) ; give function
(for ((n xs))
(place-channel-put wch-c n)) ; create work orders
(let loop ((i 0) (res '())) ; response loop
(if (= i l)
(reverse res)
(let ((response (sync/timeout 10 wch-c))) ; get answer with timeout (place-channel-get blocks!)
(loop
(+ i 1)
(if response (cons response res) res))))))
(module+ main
(displayln (parallel-map 'add1 (range 10))))
Running in a console gives, for example:
worker_1 says 1
worker_1 says 3
worker_1 says 4
worker_1 says 5
worker_1 says 6
worker_1 says 7
worker_1 says 8
worker_1 says 9
worker_1 says 10
worker_0 says 2
(1 3 4 5 6 7 8 9 10 2)
As I said, crufty. All suggestions are welcome!

binary trees searching inside

Can anyone tell me what I need to do here?
(define (count-values abst v)
(cond [(empty? abst) 0]
[else (+ (cond [(equal? v (bae-fn abst)) 1]
(else 0))
(count-values .... v)
(count-values .... v ))]))
I basically need a function that counts the amount of symbols v inside a binary tree
(define bae
(make-bae '+
(make-bae '* (make-bae '+ 4 1)
(make-bae '+ 5 2))
(make-bae '- 6 3)))
(count-values bae '+) => 3
because there are 3 '+ in bae
You need to:
Post the definition of the tree - I'm guessing bae is a struct - don't assume we know your code, post all the relevant information as part of the question
Make sure that the code you post works at least in part - for instance, the (define bae ...) part won't work even if you provided the definition of bae, because of a naming conflict
Follow the recipe for traversing a binary tree, I bet it's right in the text book
The general idea for the solution goes like this, without taking a look at the actual implementation of the code you've done so far is the only help I can give you:
If the tree is empty, then return 0
If the current element's value equals the searched value, add 1; otherwise add 0
Either way, add the value to the result of recursively traversing the left and right subtrees
If you define your data structure recursively, then a recursive count algorithm will naturally arise:
;; Utils
(define (list-ref-at n)
(lambda (l) (list-ref l n)))
(define (eq-to x)
(lambda (y) (eq? x y)))
;; Data Type
(define (make-bae op arg1 arg2)
`(BAE ,op, arg1, arg2))
(define (bae? thing)
(and (list? thing) (eq? 'BAE (car thing)) (= 4 (length thing))))
(define bae-op (list-ref-at 1))
(define bae-arg1 (list-ref-at 2))
(define bae-arg2 (list-ref-at 3))
;; Walk
(define (bae-walk func bae) ;; 'pre-ish order'
(if (not (bae? bae))
(func bae)
(begin
(func (bae-op bae))
(bae-walk func (bae-arg1 bae))
(bae-walk func (bae-arg2 bae)))))
;; Count
(define (bae-count-if pred bae)
(let ((count 0))
(bae-walk (lambda (x)
(if (pred x)
(set! count (+ 1 count))))
bae)
count))
(define (bae-count-if-plus bae)
(bae-count-if (eq-to '+) bae))
> bae
(BAE + (BAE * (BAE + 4 1) (BAE + 5 2)) (BAE - 6 3))
> (bae-count-if-plus bae)
3
;; Find
(define (bae-find-if pred bae)
(call/cc (lambda (exit)
(bae-walk (lambda (x)
(if (pred x) (exit #t)))
bae)
#f)))

Resources