reading in a top-level definition - chicken-scheme

Chicken Scheme 4.8.0.5
Greetings all,
Assuming I have a text file containing a top-level definition
topLevelDef.txt
(define techDisplays '(
( AG1 fillerIgnore AG1_fillerIgnore t t nil t nil )
( AG2 drawing AG2_drawing t t nil t t )
)
)
and I bring it in as an include
trythis.scm
(use extras format posix posix-extras regex regex-literals utils srfi-13)
(include "./mytech/mytech.tf.techDisplays") ; works when hard-coded
;include inn-file) ; want to pass it in as an arg
(define write-out-techDisplays
(lambda()
(for-each
(lambda(rule-as-list-of-symbols)
(begin
(set! rule-as-list-of-strings ( map symbol->string rule-as-list-of-symbols))
(print (string-join rule-as-list-of-strings ))
)
)
techDisplays
)
)
)
(define (main args)
(set! inn-file ( car args))
(set! out-file (cadr args))
(with-output-to-file out-file write-out-techDisplays)
0
)
So how can I achieve this? Either by delaying evaluation of the include somehow? Or reading in the contents of inn-file and evaluating the string somehow? Or something else?
TIA,
Still-learning Steve

just pass the list you want as an argument to your outer lambda.
your formatting is misleading, you could try to pretty print your code.
(define write-out-techdisplays
(lambda (techdisps)
(for-each
(lambda (rule)
(begin
(set! rule-string (map symbol->string rule))
(print (string-join rule-string)))) ;inner-lambda closes here
techdisps)))
(define alldisps
(call-with-input-file "./mytech/mytech.tf.techDisplays"
read)))
;since the last arg is thunk the way to invoke it is to wrap
;our call to write-out-techdisplays with a lambda to set the correct list
(with-output-to-file out-file
(lambda ()
(write-output-techdisplays alldisps)))
finally, you could redesign your code to work without sideffects (those set!s).
that for-each could be a map.

Related

Prog can't run on page 113 of <<Lisp in small pieces>>

The code from page 113 of Lisp in small pieces seems can't run on r5rs environment of racket:
(let ((name "Hemo"))
(set! winner (lambda () name))
(set! set-winner! (lambda (new-name) (set! name new-name) name ))
(set-winner! "Me")
(winner) )
and:
(let ((name "Nemo"))
(set! winner (lambda () name))
(winner) )
both got error:
cannot set variable before its definition
variable: winner
is the code of this book wrong?or I should not use scheme?I have to use the lisp this book defined to run this code?Thanks!
You need to bind the variable using define or lambda. For example:
(let ((name "Hemo"))
(define winner #t)
(define set-winner! #t)
(set! winner (lambda () name))
(set! set-winner! (lambda (new-name) (set! name new-name) name ))
(set-winner! "Me")
(winner) )
set! is converted into an scode whose semantics is to mutate a location of memory, not to bind new locations. Forms like let are syntactic sugar for the combination of both operations (bind+mutation) and, because they are so common, Queinnec inserted an scode, fixlet, for this combination.
All these things are explained in the book of Queinnec. Go on reading!

How to parse a function into another function in scheme

I am trying to create a function that takes another function as a parameter and calls the functions in a loop.
The code below should get the function and the number of times the loop should execute:
(define (forLoop loopBody reps)
(let
(
(fun (car loopBody))
(str (cdr loopBody))
)
(cond
((eval (= reps 0) (interaction-environment)) "")
(else (cons str (forLoop '(fun str) (- reps 1))))
)
)
)
The code below is how i am calling the function
(define (printermsg)
(display msg)
)
(forLoop '(printer "text ") 4)
The expected output for the above code:
text text text text
There are several issues with your code:
The way you pass the loopBody parameter to your function is incorrect, a list of symbols will not work: you want to pass along a list with the actual function and its argument.
You are not obtaining the second element in the list, cdr won't work because it returns the rest of the list, you need to use cadr instead.
Avoid using eval, it's not necessary at all for what you want, and in general is a bad idea.
Why are you building a list? cons is not required here.
When calling the recursion, you are again passing a list of symbols instead of the proper argument.
You're not actually calling the function!
This should work:
(define (forLoop loopBody reps)
(let ((fun (car loopBody))
(str (cadr loopBody)))
(cond
((= reps 0) (void)) ; don't do anything when the loop is done
(else
(fun str) ; actually call the function!
(forLoop loopBody (- reps 1))))))
(define (printer msg)
(display msg))
(forLoop (list printer "text ") 4) ; see how to build the loop body
=> text text text text

Achieving name encapsulation while using 'define' over 'let'

In an attempt to emulate simple OOP in scheme (just for fun), I have caught myself repeating the following pattern over and over:
(define my-class ; constructor
(let ((let-for-name-encapsulation 'anything))
; object created from data is message passing interface
(define (this data)
(lambda (m)
(cond ((eq? m 'method1) (method1 data))
((eq? m 'method2) (method2 data))
(else (error "my-class: unknown operation error" m)))))
;
(define (method1 data)
(lambda (arg1 ...)
... )) ; code using internal 'data' of object
;
(define (method2 data)
(lambda (arg2 ...)
... ))
;
; returning three arguments constructor (say)
;
(lambda (x y z) (this (list 'data x y z)))))
I decided to wrap everything inside a let ((let-for-name-encapsulation ... so as to avoid leaking names within the global environment while still
being able to use the define construct for each internal function name, which enhances readability. I prefer this solution to the unsightly construct (let ((method1 (lambda (... but I am still not very happy because of the somewhat artificial let-for-name-encapsulation. Can anyone suggests something simple which would make the code look even nicer?. Do I need to learn macros to go beyond this?
I use that pattern often, but you don't actually need to define any variables:
(define binding
(let ()
(define local-binding1 expression)
...
procedure-expression)))
I've seen it in reference implementations of SRFIs so it's a common pattern. Basically it's a way to make letrec without the extra identation and lambdas. It can easily be made a macro to make it even flatter:
(define-syntax define/lexical
(syntax-rules ()
((_ binding body ...)
(define binding
(let ()
body ...)))))
;; test
(define/lexical my-class
(define (this data)
(lambda (m)
(cond ((eq? m 'method1) (method1 data))
((eq? m 'method2) (method2 data))
(else (error "my-class: unknown operation error" m)))))
(define (method1 data)
(lambda (arg1 ...)
... )) ; code using internal 'data' of object
(define (method2 data)
(lambda (arg2 ...)
... ))
;; returning three arguments constructor (say)
(lambda (x y z) (this (list 'data x y z))))
;; it works for procedures that return procedures as well
(define/lexical (count start end step)
(define ...)
(lambda ...))
Of course you could use macros to simplify your object system as well.

Is there anyway to check if a function return nothing in Scheme?

Is there anyway to check if a function return nothing in Scheme?
For example:
(define (f1)
(if #f #f)
)
or
(define (f2) (values) )
or
(define (f3) (define var 10))
How can I check if f return nothing?
Thanks in advance.
Yes. You can wrap the call in something that makes a list of the values. eg.
(define-syntax values->list
(syntax-rules ()
((_ expression)
(call-with-values (lambda () expression)
(lambda g (apply list g))))))
(apply + 5 4 (values->list (values))) ; ==> 9
(null? (values->list (values))) ; ==> #t
Your procedure f2 does return exactly one value and it's undefined in the report (Scheme standard). That means it can change from call to call and the result of (eq? (display "test1") (display "test2")) is unknown.
Implementations usually choose a singleton value to represent the undefined value, but you can not depend on it. Implementations are free to do anything. eg. I know that in at least one Scheme implementations this happens:
(define test 10)
(+ (display 5) (set! test 15))
; ==> 20 (side effects prints 5, and test bound to 15)
It would be crazy to actually use this, but it's probably useful in the REPL.
In GNU Guile the function for checking this is unspecified?:
(unspecified? (if #f #f)); returns #t
(unspecified? '()); returns #f

How do you return the description of a procedure in Scheme?

Suppose I have something like this:
(define pair (cons 1 (lambda (x) (* x x))
If I want to return the front object of the pair I do this:
(car pair)
And it returns 1. However when the object is a procedure I don't get the exact description of it.
In other words:
(cdr pair)
returns #<procedure> and not (lambda (x) (*x x)).
How do I fix this?
Although there's no way to do this generally, you can rig up something to do it for procedures that you define.
Racket structs can define a prop:procedure that allows the struct to be applied (called) as a procedure. The same struct can hold a copy of your original syntax for the function definition. That's what the sourced struct is doing, below.
The write-sourced stuff is simply to make the output cleaner (show only the original sexpr, not the other struct fields).
The define-proc macro makes it simpler to initialize the struct -- you don't need to type the code twice and hope it matches. It does this for you.
#lang racket
(require (for-syntax racket/syntax))
;; Optional: Just for nicer output
(define (write-sourced x port mode)
(define f (case mode
[(#t) write]
[(#f) display]
[else pretty-print])) ;nicer than `print` for big sexprs
(f (sourced-sexpr x) port))
(struct sourced (proc sexpr)
#:property prop:procedure (struct-field-index proc)
;; Optional: Just to make cleaner output
#:methods gen:custom-write
[(define write-proc write-sourced)])
;; A macro to make it easier to use the `sourced` struct
(define-syntax (define-proc stx)
(syntax-case stx ()
[(_ (id arg ...) expr ...)
#'(define id (sourced (lambda (arg ...) expr ...)
'(lambda (arg ...) expr ...)))]))
;; Example
(define-proc (foo x)
(add1 x))
(foo 1) ; => 2
foo ; => '(lambda (x) (add1 x))
The procedure cons evaluates its arguments: 1 is self-evaluating to 1; (lambda ...) evaluates to an anonymous procedure. If you want to 'prevent' evaluation, you need to quote the argument, as such:
> (define pair (cons 1 '(lambda (x) (* x x))
> (cdr pair)
(lambda (x) (* x x))

Resources