Sham expressions are first-class objects in Racket […]
Thus, we can build expressions for a complex DSL on the fly based on Racket values. One such example is to build a power function for a specific exponent n.
(define (build-pow x n)
(if (= n 0)
(ui64 1)
(mul x (build-pow x (- n 1)))))
Wouldn’t it be better to compile to closures, when possible? Like this:
(define (build-pow n)
(if (= n 0)
(sham-lambda (x: ui64): ui64
1)
(let ([rest (build-pow (- n 1))])
(sham-lambda (x: ui64): ui64
(* x (rest x))))))
This seems more high-level, because I don’t have to think about ASTs or variable hygiene. I’ve wondered the same thing about Terra’s quotations.
Are there cases when you really need this escape hatch?
We present Sham, a toolkit designed to enable internal DSLs with high performance. Sham provides a domain-specific language (embedded in Racket) for implementing other high-performance DSLs, with transparent compilation to assembly code at runtime. Sham is well suited as both a compilation target for other embedded DSLs and for transparently replacing DSL support code with faster versions. Sham provides seamless inter-operation with its host language without requiring any additional effort from its users. Sham also provides a framework for defining language syntax which implements Sham’s own language interface as well.
Cool! Sounds a lot like Terra: https://terralang.org/
Wouldn’t it be better to compile to closures, when possible? Like this:
This seems more high-level, because I don’t have to think about ASTs or variable hygiene. I’ve wondered the same thing about Terra’s quotations.
Are there cases when you really need this escape hatch?
Oh, my. Perhaps they could use the keyword shambda? I’ll see myself out.
Here’s a link to the actual paper: https://arxiv.org/pdf/2005.09028v2
Racket implementation https://github.com/rjnw/sham