popa.bogdanp
2021-1-30 12:01:38

I made a couple changes this morning that’ll hopefully make this less confusing in the future: the response-output port now gets closed unless #:stream? #t is provided and it now has explicit documentation describing this behavior.


laurent.orseau
2021-1-30 12:27:41

if you want something with a warmer feeling, you could go with ‘embracing’ I suppose :slightly_smiling_face:


samth
2021-1-30 13:28:02

Thanks!


greg
2021-1-30 14:31:01

“The expression in tail position will tap its heels and go here — to the warm embrace of its home, only to realize it shared the same continuation, and was home all along…” might be too long for a tooltip.


greg
2021-1-30 14:31:42

But I might do that anyway, and wait for the ensuing complaints on GitHub issues.


laurent.orseau
2021-1-30 14:32:05

“Love is sharing the same continuation” they say


sorawee
2021-1-30 14:33:42

philip.mcgrath
2021-1-30 17:23:01

Just wanted to say I’m interested in the answer, too! I also have a DHT sensor and Raspberry Pi, but haven’t played with it for a while (or been on slack for a while).


samdphillips
2021-1-30 19:19:24

I took the conservative route and implemented the part that reads the pin states in C. It’s mostly a translation of an Adafruit Python C module I found on github. Basically Racket calls into a C function that fills a uint array with “timings” of zeroes and ones. Then on the Racket side there is code that converts that into bytes. Basically trying to do the least amount of work that needs to be done in C.


samdphillips
2021-1-30 20:22:19

I tidied up the DHT11 sensor library that I wrote for the RPi if anyone is interested. https://github.com/samdphillips/racket-dht11


soegaard2
2021-1-30 21:09:39

I have amused myself writing a simple version of something that looks like Rust traits. Have I overlooked an existing library implementing traits?

I know generics and the unit system are close, but are there others?


soegaard2
2021-1-30 21:09:39

#lang racket (require (for-syntax syntax/parse racket/syntax)) ;;; ;;; TRAITS ;;; ; This file contains a minimal implementation of traits. ; Overview: ; (define-trait trait (method ...) ; A trait is defined as list of methods names. ; (implementation trait structure body ...) ; An implementation of a trait for a given structure types, ; associates functions to each of the methods suitable ; for that structure type. ; Within body, the method names can be used. ; (with ([id trait structure expression] ...) . body) ; Similar to (let ([id expression] ...) . body), ; but within the body, one can use id.method ; to call a method. ; Expansion time helpers (begin-for-syntax ; These functions produce new identifiers. The context is taken from stx. (define (identifier:structure-method stx s m) (format-id stx "~a-~a" s m)) (define (identifier:id.method stx id m) (format-id #'stx "~a.~a" id m)) ; get-methods : identifier -> list-of-identifiers (define (get-methods trait) (syntax-local-value (format-id trait "~a-methods" trait)))) ; SYNTAX (define-trait Name (name ...)) ; This declares a new trait with the name Name having the methods name .... (define-syntax (define-trait stx) (syntax-parse stx [(_define-trait Name (id ...)) (with-syntax ([trait-methods (format-id #'Name "~a-methods" #'Name)]) (syntax/loc stx (define-syntax trait-methods (list #'id ...))))] [(_define-trait Name (super-trait ...) (id ...)) (displayln (list 'dt stx)) (define ids (syntax->list #'(id ...))) (define supers (syntax->list #'(super-trait ...))) (with-syntax ([trait-methods (format-id #'Name "~a-methods" #'Name)] [((super-method ...) ...) (map get-methods supers)]) (syntax/loc stx (define-syntax trait-methods (list #'id ... #'super-method ... ...))))])) ; SYNTAX (implementation trait structure . body) ; Defines structure-method for each method of the trait. ; The structure-method is bound to method. ; If method is defined in body, then that binding is used. ; If method is not bound in body, but bound outside, the outside binding is used. ; If method is not bound at all, an error is signaled. (define-syntax (implementation stx) (syntax-parse stx [(_implementation trait structure body ...) (define methods (get-methods #'trait)) (with-syntax* ([(method ...) ; These short names are used by the user (for/list ([method methods]) (syntax-local-introduce (format-id #'stx "~a" method)))] [(structure-method ...) ; Used in the output of the `with` form. (for/list ([method methods]) (identifier:structure-method #'trait #'structure method))]) (syntax/loc stx (define-values (structure-method ...) (let () body ... (values method ...)))))])) (define-syntax (with stx) (syntax-parse stx [(_with ([id trait structure expression] ...) . body) (define traits (syntax->list #'(trait ...))) (define ids (syntax->list #'(id ...))) (define structures (syntax->list #'(structure ...))) (define methodss (map get-methods traits)) (define (map-methods f id t s ms) (for/list ([m ms]) (f id t s m))) (define (map-clauses f) (for/list ([id ids] [t traits] [s structures] [ms methodss]) (map-methods f id t s ms))) (with-syntax ([((id.method ...) ...) ; names used inside `with` (map-clauses (λ (id t s m) (syntax-local-introduce (identifier:id.method #'stx id m))))] [((structure-method ...) ...) ; names used outside `with` (map-clauses (λ (id t s m) (syntax-local-introduce (identifier:structure-method t s m))))] [((it ...) ...) ; all id (in the right shape) (map-clauses (λ (id t s m) id))]) (syntax/loc stx (let* ([id expression] ...) (let-syntaxes ([(id.method ...) ; we need a macro in other to pass id (values ; to the associated structure-method (λ (call-stx) (syntax-parse call-stx [(_ . args) (syntax/loc call-stx (structure-method it . args))])) ...)] ...) . body))))])) ;;; ;;; Test ;;; ; Let's test the traits with a silly fish example. (struct herring (size color) #:transparent) (define-trait Fish (grow swim shrink)) (define (shrink f) (displayln (~a "This type of fish can't swim: " f))) (implementation Fish herring ; swim : herring -> void (define (swim h) (match h [(herring s c) (displayln (~a "A " c " herring swims."))])) ; grow : fish integer -> fist ; Add the amount a to the size of of the fish. (define (grow h a) (match h [(herring s c) (herring (+ s a) c)]))) (define a-herring (herring 2 "gray")) (with ([h Fish herring a-herring]) (h.shrink) ; picks up default definition (h.grow 3)) ; uses the herring implementation of Fish ;; ; => (let ([h a-herring]) (herring-shrink h) (herring-grow h 3)) ;;; ;;; A simple implementation of rings using traits. ;;; (define-trait Set (member? size)) ; a Set has the methods member? and size (define-trait Monoid (Set) ($)) ; a Monoid is a Set with an operation $ (define-trait Group (Monoid) (inv)) ; a Group is a Monoid with an operation inv (define-trait Ring (Group) (+ \|0\| * \|1\|)) ; a Ring is an additive Group with an multiplicative monoid (require (prefix-in + (only-in racket/base +)) ; ++ is now standard + (prefix-in * (only-in racket/base *))) ; ** is now standard * (struct Z ()) (implementation Ring Z (define (member? R x) (integer? x)) (define (size R) +inf.0) ; Ring (define (+ R a b) (++ a b)) (define (* R a b) (** a b)) (define \|0\| 0) (define \|1\| 1) ; Group (define (inv R a) (- a)) ; Additive Monoid (define $ +)) (struct Zn (n)) (implementation Ring Zn (define (modulus R) (Zn-n R)) ; Set (define (member? R x) (and (integer? x) (<= x (modulus R)))) (define (size R) (modulus R)) ; Ring (define (+ R a b) (modulo (++ a b) (modulus R))) (define (* R a b) (modulo (** a b) (modulus R))) (define \|0\| 0) (define \|1\| 1) ; Group (define (inv R a) (modulo (- a) (modulus R))) ; Additive Monoid (define $ +)) (struct Zx (x p)) ; p(x) belongs to Z[x], the ring of polynomials over Z (require (prefix-in cas: racket-cas)) (implementation Ring Zx (define (var R) (Zx-x R)) ; Set (define (member? R f) (cas:polynomial? f (var R))) ; approximate (define (size R) +inf.0) ; Ring ; Note: We are assuming a and b are normalized. ; If a and b are normalized, the return values from + and * will ; automatically be normalized. (define (+ R a b) (cas:plus a b)) (define (* R a b) (cas:expand (cas:times a b))) (define \|0\| 0) (define \|1\| 1) ; Group (define (inv R a) (cas:times -1 a)) ; Additive Monoid (define $ +)) (struct Zx/I (x I)) ; the ideal I is represented by a polynomial p ; The ring of single variable polynomials over Z modulo an ideal I. ; Note: We are using racket-cas to compute, and it supports polynomials ; over Z, Q and floating points. It does support polynomials ; in several variables, so Zxy/I can be implemented in the same ; manner. (implementation Ring Zx/I (define (var R) (Zx/I-x R)) (define (I R) (Zx/I-I R)) ; a polynomial (define (inject R p) (cas:polynomial-remainder p (I R) (var R))) ; Set (define (member? R f) (cas:polynomial? f (var R))) ; approximate (define (size R) +inf.0) ; Ring (define (+ R a b) (inject R (cas:plus a b))) (define (* R a b) (inject R (cas:expand (cas:times a b)))) (define \|0\| 0) (define \|1\| 1) ; Group (define (inv R a) (cas:times -1 a)) ; Additive Monoid (define $ +)) (with ([R Ring Z (Z)]) (R.* (R.+ 1 2) 3)) ; => 9 (with ([R Ring Zn (Zn 5)]) (R.* (R.+ 1 2) 3)) ; => 4 (with ([R Ring Zx Zx]) (R.* (R.+ 'x 1) (R.+ 'x 1))) (with ([R Ring Zx/I (Zx/I 'x (cas:normalize '(+ (* x x) 1)))]) (R.* 'x 'x)) ; => -1 (with ([R Ring Zx/I (Zx/I 'x (cas:normalize '(+ (* x x) 1)))]) (R.* (R.+ 'x 1) (R.+ 'x 1))) ; => 2x


soegaard2
2021-1-30 21:09:39


soegaard2
2021-1-30 21:35:02

That’s looks very similar indeed (for objects rather than structs, but the concept is the same).


laurent.orseau
2021-1-30 22:17:01

You know about rename-in I suppose?


soegaard2
2021-1-30 22:36:34

Yes?


soegaard2
2021-1-30 22:49:13

I thought about using submodules, but then I need to instantiate the same submodule more than once.


soegaard2
2021-1-30 22:50:35

But maybe … maybe local-require can be used to implement with.