3 ms·
Your description of your work process sounds like descriptions I’ve read of language driven development. Could you expand on why this is so powerful for you?
by proamdev123 3y ago
Your description of your work process sounds like descriptions I’ve read of language driven development.
Could you expand on why this is so powerful for you?
Not doubting it’s power, but I’m having a hard time understanding _why_ it’s so powerful for some people.
- mjburgess 3y agoThis morning I was sketching how i'd do syntax for affine and linear types, which are (very basically) where variables can be used "at most once" or "only once". In sketching I iterated various designs, my notepad is below. It began trying to think about how to express scopes visually, or using tags/lables -- then moved into how that integrates with other langauge features etc. By doing this I understand much more about what really a language feature is trying to do -- I understand the tradeoffs, etc. program a: let x:a = 10 if 10 < 5 b: let x:b = x print(x) program UseyTypes: x : once = new Resource() # at most once -- rust's default y : never = ... z : once! = ... # only once q : many = ... program MoveSemantics: a = new 10 x = 10 y = move x z = copy y i0 = new(auto) 10 i1 = new(memo.alloc.heap) 10 # default g1 = new(heap) Graph.init({...}) g2 = copy(Graph) g1 # uses Graph's (deep)copy method g2 = copy(Graph.copy) g1 # eqv to above program : global heap = Allocator.tmp(...) if True: local xs = Vec.new(heap) { 1, 2, 3, 4 } memo.lifetimeOf(x) # eg., local scope a = lineno 10 - 20 memo.lifetimeOf(x.data) # eg., global via heap allocator repeat x <= xs: x = 10 # error print(x) repeat i <= int.range(10): x[i] += 1 repeat: const answer = input("What's 2 + 2?").to(int) print(compiler.scope) print(compiler.lineno) const int z = 10 const ref(int) y = ref(z) print(y, deref(y)) const x : global = 10 if 10 < 5: int x : local = 10 int y : parent = 10 # polymorphic .to fn str.to(int): parseInt(.) program EffectSystem: fn[IO] println(const ...data: ...any): repeat d <- data: IO.writeline(d.to(str)) pure fn calc(): # pure = no effects return 10 + 20 # by default, all fns are impure, ie., have IO auto-passed ? println("Hello", "World") with IO = open("output.txt", "w"): println("Into some file!") println[open("output.txt")]("hello world")
- proamdev123 3y agoThanks! Out of curiosity, have you ever tried developing DSLs in Racket? One of its explicit reasons for existence is to enable fast development of custom DSLs.
- mjburgess 3y agoThe art of designing a language is expressing semantics in intuitive syntax -- it's an art because "intuitive" is essentially a psycho-social cultural condition. (ie., I reject Lisp) C was "intuitively mind-expanding" to assembly developers and PDP-machine programmers -- and so on. My aim is always to express a semantic concept in syntax so that it is so obvious that it's originating language developers will be shocked. You can do that both with, eg., map fn over collection and xs/fn and repeat x from xs: fn(x) and { fn(x) st. x <- xs & st. x > 0 } etc. In that each syntax resonates with a certain programming culture. For novices, I suppose the following might be "consciousness raising", set result := repeat: set x := next xs: save fn(x)