According to the following example from the struct/dc entry in the Racket reference manual, the bst/c function below returns a contract such as every node in bt has its value bound between lo and hi.
(struct bt (val left right))
(define (bst/c lo hi)
(or/c #f
(struct/dc bt
[val (between/c lo hi)]
[left (val) #:lazy (bst lo val)]
[right (val) #:lazy (bst val hi)])))
That definition looks perfect to me, except for one thing: what is the purpose of the (or/c #f [...]) construct here ? Since #f is a constant that always evaluates to false, why not just remove the or/c logic altogether, and simply define bst/c as:
(define (bst/c lo hi)
(struct/dc bt
[val (between/c lo hi)]
[left (val) #:lazy (bst lo val)]
[right (val) #:lazy (bst val hi)]))
A binary search tree with a single value is constructed as:
(bst 42 #f #f)
Here #f is used to indicated that the left and right subtrees are empty.
Since we want the left and right subtrees also to be binary search trees, we need to include the value #f as a legal bst. The contract (or/c #f ...) says just that.
Related
Suppose I define a struct for a set with its "center".
(struct centered-set (center elems))
I want to guarantee the following conditions.
elems is a set.
center is an member of elems.
I can express the conditions with #:guard. Is there a way to express the same conditions as a contract?
For functions, ->i works as a combinator for that kind of dependent contracts. How to express dependent contracts for structs?
IIUC, contract-out doesn't support anything like that. However, you can simulate the functionality by providing the constructor and accessors manually with the contract attached:
#lang racket
(module foo racket
(provide (contract-out [bt (-> any/c any/c any/c (bst/c 1 10))]
[bt-val (-> (bst/c 1 10) any/c)]
[bt-left (-> (bst/c 1 10) any/c)]
[bt-right (-> (bst/c 1 10) any/c)]))
(define (bst/c lo hi)
(or/c #f
(struct/dc bt
[val (between/c lo hi)]
[left (val) #:lazy (bst/c lo val)]
[right (val) #:lazy (bst/c val hi)])))
(struct bt (val left right)))
(require 'foo)
(bt 11 #f #f)
It should be possible to write a provide transformer to automate this process.
I have one more questions about Hygienic macros in Scheme, consider example from R5RS
(let-syntax ((when (syntax-rules ()
((when test stmt1 stmt2 ...)
(if test
(begin stmt1
stmt2 ...))))))
(let ((if #t))
(when if (set! if 'now))
if))
Why it match if the pattern have 3 arguments and ellipsis that can match empty list?
It's called with 2 arguments if and (set! if 'now). What should be ... bind to, if stmt2 can be bind to empty list? This is kind of non Lispy if ... is just nothing. Is that true?
What should be the expansion of when in this context? What is the value of stmt2?
Why this don't work but the first code does?
(let-syntax ((when (syntax-rules ()
((when test stmt1 stmt2 ...)
(if test
(begin stmt1
stmt2 ...))))))
(when if 10))
it work in Kawa but not in Guile, is that the bug in Guile and it should in fact work like in Kawa?
And one more question why it don't evaluate to nil? If next element in list after 10, is nil so stmt2 should be nil? R5RS is not very helpful in that regard.
I'm asking this because I've just finsihed renaming scheme for my macro system in LIPS Scheme and when I'm pattern matching I've got comparison of stmt2 and nil and there is also ... left. Should in this case ... just be ignored and stmt2 should be nil? And it should match even that there is one less symbol in pattern? This is really confusing.
What should be the expansion of last snippet of code?
EDIT:
One more thought
(let-syntax ((when (syntax-rules ()
((when test stmt1 . stmt2)
(if test
(begin stmt1
stmt2))))))
(when if 10))
This works in Kawa and return nil as expected but in Guile it throw exception, I consider Kawa Scheme to be better in following spec.
But why it even match the pattern if there are not enough arguments?
Yes. It is very non lispy that we have a modifier ... that changes the meaning of element in front. eg. something ... is basically similar to . something except it works with structures like this:
(define-syntax my-let
(syntax-rules ()
((_ ((a b) ...)
body1 bodyn ...)
((lambda (a ...)
body1 bodyn ...)
b ...))))
Notice I use body1 ro require at least one expression in the body since bodyn ... can be zero or more elements. This will turn:
(my-let ()
test)
==>
((lambda () test))
As well as
(my-let ((a b) (c d))
test1 test2)
==>
((lambda (a c)
test1 test2)
b
d)
My example cannot be rewritten with cons syntax, but basically using . works the same way as rest arguments in the pattern and . in a quote:
'(a b . (c d))
; ==> (a b c d)
Your when would not work with more than one expression.
eg.
(let-syntax ((when (syntax-rules ()
((when test stmt1 . stmt2)
(if test
(begin stmt1
stmt2))))))
(define if #t)
(when if (display 'true) #t))
Imagine that all report bindings also exist under r5rs: prefix. The expansion will become:
(r5rs:if if
(begin (display 'true)
(#t)))
; ERROR: Application not a procedure: #t
This is correct:
(let-syntax ((when (syntax-rules ()
((when test stmt1 . stmt2)
(if test
(begin stmt1
. stmt2))))))
(define if #t)
(when if (display 'true) #t))
; ==> #t (prints true)
I'm trying to experiment with what I can do in Racket, and I want to suffix numbers with letters.
For this example, I'd simply like to represent 10000 as 10K, and 1000000 as 1M.
Is there way (with macros or otherwise) that I can expand 1M to:
(* 1 1000000)
Or something to that effect?
In Racket, things like 10K are identifiers, which normally would refer to variables. There are two ways to make them into numbers:
1: redefine what "undefined" identifiers mean
You can redefine what to do on an undefined identifier by defining a #%top macro.
#lang racket
(require syntax/parse/define
(only-in racket [#%top old-#%top]))
(define-syntax-parser #%top
[(_ . x:id)
#:when (id-has-a-k-at-the-end? #'x)
(transform-id-into-number #'x)]
[(_ . x)
#'(old-#%top . x)])
However, this has a subtle problem. If there are any identifiers or variables in your program with K's on the end, they could override any numbers that were written that way. You would need to be careful not to accidentally override something that was intended to be a number.
2: make a reader extension that turns them into numbers instead of identifiers
This will take more time, but it's closer to the "right way" to do this, since it avoids conflicts when variables happen to have K's on the end.
One of the easier ways to extend the reader is with a readtable. You can make a function that extends a readtable like this:
;; Readtable -> Readtable
(define (extend-readtable orig-rt)
;; Char InputPort Any Nat Nat Nat -> Any
(define (rt-proc char in src ln col pos)
....)
...
(make-readtable orig-rt
#f 'non-terminating-macro rt-proc
...))
To use this to define a #lang language, you need to put the reader implementation in your-language/lang/reader.rkt. Here that's number-with-k/lang/reader.rkt, where the number-with-k directory is installed as a single-collection package (raco pkg install path/to/number-with-k).
number-with-k/lang/reader.rkt
#lang racket
(provide (rename-out [-read read]
[-read-syntax read-syntax]
[-get-info get-info]))
(require syntax/readerr
syntax/module-reader)
;; Readtable -> Readtable
(define (extend-readtable orig-rt)
;; Char InputPort Any Nat Nat Nat -> Any
(define (rt-proc char in src ln col pos)
....)
...
(make-readtable orig-rt
#f 'non-terminating-macro rt-proc))
;; [X ... -> Y] -> [X ... -> Y]
(define ((wrap-reader rd) . args)
(parameterize ([current-readtable (extend-readtable (current-readtable))])
(apply rd args)))
(define-values [-read -read-syntax -get-info]
(make-meta-reader 'number-with-k
"language path"
lang-reader-module-paths
wrap-reader
wrap-reader
identity))
The main work goes into filling in the .... holes in the extend-readtable function. For example, you can make it recognize identifiers that end with K like this:
;; Readtable -> Readtable
(define (extend-readtable orig-rt)
;; Char InputPort Any Nat Nat Nat -> Any
(define (rt-proc char in src ln col pos)
(define v (read-syntax/recursive src in char orig-rt #f))
(cond
[(and (identifier? v) (id-has-a-k-at-the-end? v))
(transform-id-into-number v)]
[else
v]))
(make-readtable orig-rt
#f 'non-terminating-macro rt-proc))
Once this is done, and you have the number-with-k directory installed as a package, you should be able to use #lang number-with-k like this:
#lang number-with-k racket
(+ 12K 15)
; => 12015
The simplest to is to define the suffixes you need.
(define K 1000)
(define M 1000000)
Then write (* 3.14 M) for 3.14 millions.
As others mention, Racket supports scientific notation 3.14E6 is also 3.14 million.
Yet another alternative is to define functions K, M etc like:
(define (M x) (* x 1000000))
Then you can write
(M 3.14)
to mean 3.14 million.
Racket does already have built in support for this, kind of, via scientific notation:
1e6 ; 1000000.0 ("1M")
2e7 ; 20000000.0
I have lisp in javascript which is similar to scheme. It can be used with lexical and dynamic scopes. I was not sure how dynamic scope works and it's seems ok but this code don't work when scope is dynamic:
(define Y
(lambda (h)
((lambda (x) (x x))
(lambda (g)
(h (lambda args (apply (g g) args)))))))
(define (trampoline f)
(lambda args
(let ((result (apply f args)))
(while (eq? (type result) "function")
(set result (result)))
result)))
(define (! n)
((trampoline (Y (lambda (f)
(lambda (n acc)
(if (== n 0)
acc
(lambda ()
(f (- n 1) (* n acc)))))))) n 1))
(print (! 1000))
it works fine when scope is lexical. Should this code work when scope is dynamic? Right now it just do nothing and I don't know why but wanted to be sure that this code should work before I start debugging and make my dynamic scope break because of this.
My lisp with demo is here https://jcubic.github.io/lips/ but the code that make this work for lexical scope is not yet published so it will not work. (it's in devel branch and I can create codepen demo with it or using Stack Snippet).
I don't see how trampoline can work with dynamic scoping.
Simplified evaluation:
(define Y ...)
Now Y is bound (to some value).
(define (trampoline f)
(lambda args
(let ((result (apply f args)))
...)))
Now trampoline is bound to (lambda (f) (lambda args (let ((result (apply f args))) ...))).
(define (! n)
((trampoline ...) n 1))
Now ! is bound to (lambda (n) ((trampoline ...) n 1)).
(print (! 1000))
We evaluate the inner call first, so we need to resolve ! and apply it to 1000.
By the definition of ! above we bind n to 1000 and evaluate ((trampoline ...) n 1).
We need to call trampoline. By the definition of trampoline above, we bind f to ... and return (lambda args (let ((result (apply f args))) ...)).
We return from trampoline and undo the binding of f.
We now need to evaluate ((lambda args (let ((result (apply f args))) ...)) n 1) (applying the return value of trampoline to n and 1).
n is currently bound to 1000, so this expression becomes ((lambda args (let ((result (apply f args))) ...)) 1000 1). To perform the call call we bind args to (1000 1).
Now we need to evaluate (apply f args) (to bind the result to result as part of let). apply is in the standard library. args was just bound to (1000 1) above. But there is no binding for f.
At this point we should throw an error: The only binding of f we've seen so far was during the call to trampoline (where f was a parameter). But that call has already returned and the binding was removed, so f is unbound.
Live demo (using a Perl version of your code where all bindings are made dynamic manually): https://ideone.com/DWjwBj
It blows up as predicted: Can't use an undefined value as a subroutine reference for the line local $result = $f->(#args); because $f is unbound.
If you change all bindings to lexical (replace all occurrences of local by my), $fac->(5) returns 120 as expected.
No. Trampoline and Y combinators work with closures.
Dynamic scope has no closures so a procedure/function that refers to a free variable means whatever variable with that name in the call stack of the program.
In Lexical scope it is the variables captured when the lambda was created. Thus the code:
(define test 10)
(define (make-adder test)
(lambda (v) (+ test v)))
(define add20 (make-adder 20))
(add20 5)
; ==> 25 in lexical scope
; ==> 15 in dynamic scope
The reson is simple. The function returned by the make-adder stores the value 20 as test, while in dynamic scope test is whatever is bound closest so it's the local variable 10. Also when calling:
(let ((test 30))
(add20 5))
; ==> 25 in lexical scope
; ==> 35 in dynamic scope
Now Common Lisp has dynamic scope and lexical scope. A dynamically scoped variable is one that is defined top level with defvar, defparameter or declared special. This is so prone to errors that we have a special naming for such variables using *earmuffs*.
Scheme has parameters that are mutable objects and there are syntax for updating and restoring it so that it will act as a dynamic variable.
EDIT
I've tested your lexical and dynamic lisp and both seem to work as intended.
I am trying to parse some function to (let([x 1]) x) but racket read [ as (. Is there any simple way that I can keep it []?
this is what returns when I try to escape with backslash[ backslash]:
(let (|[| fact #f |]| |[| fact2 #f |]| |[| fact3 #f |]|) fact3)
what I want is:
, (let ([fact #f][fact2 #f][fact3 #f]) fact3)
If you are using the read-syntax primitive, then the parentheses within the parsed data structure have a paren-shape property that will tell you if they were square or not.
For example:
> (define stx-1 (read-syntax #f (open-input-string "(hello)")))
> (define stx-2 (read-syntax #f (open-input-string "[hello]")))
> stx-1
#<syntax::1 (hello)>
> stx-2
#<syntax::1 (hello)>
> (syntax-property stx-1 'paren-shape)
#f
> (syntax-property stx-2 'paren-shape)
#\[
So the syntax data structure can remember that the square brackets are there.