I’ve got a Discord from my previous game of about 2000 people, mostly teenagers, and my testers have mostly come from there. To name one example, just yesterday a teenager completed a chess game after 3-4 weeks on Easel. I’ve been incorporating tons of feedback from the testers over the past year and a half.
I think that it may look strange to a person who has coded before because the language is semi-declarative. Most teenagers come to Easel as players with no prior programming experience, and begin by remixing their favourite game, and that’s when the semi-declarative model really shines. Many interesting changes can be done in a single edit because the code is clumped together in a hierarchy. Whereas in another programming language there may be more indirection and you might need to edit 3 separate parts in different files to make 1 change, and people who haven’t coded before don’t know how to find all the parts. I think Easel works for players becoming makers but can feel strange for people who come from other languages.
It is very interesting though! I have been interested in this kind of language design for interactive UI for a while. If there was a quick article outlining how all the "with" and "on" and "own" work to more experienced developers using references to existing language features, I'd love to read it. Right now it reminds me of the declarative style of qt ui and online primitives introduced in godot, but i haven't looked at it in more details. Also love your take on async. Wish you all the best luck, this seems like a really thought through language design!
This is a very kind comment, thank you! Yes it has been a LOT of iteration to make the language what it is. I think it would make sense to have a page for experienced developers to better understand what Easel is. Right now maybe the closest is this page: https://easel.games/docs/learn/key-concepts
This is really cool, these patterns (run once now and then once triggered) surface all the time and usually turn into ugly code! How many interations did it take?
So most lines like A { B{ on D{ print() } } C{} } equivalently desugar into something like a = A; b = B(); a.mount(b); d = D(); d.on(f); b.mount(d); .. ?
I got confused by a couple of things. One of them is whether object parameters act like context parameters and there for depend on names in the caller variable scope? Ie if i define 'fn ship.Explode', i must have variable ship at call site? But i can still otherwise pass it explicitly as alien_ship.Explode(), right? How do i know if a particular call takes the current object into account? If i have two variables in my nested scope: ship and asteriod and both have ship.Explode and asteroid.Explode, which one is picked if i do just `Explode`? The innermost? Or I can't have two functions like that because the first thing is literally just a named variable and not a "method"?
Overall, if you could provide some examples of how things could have de-sugured into a different language, that'd be very interesting! Maybe with some examples of why this or that pattern is useful? I think it does a good job for things like on / once, but I'm not grokking how one would structure an app using this variable scoping use clause and object parameters.
Also not sure how to define functions that could be on'd or once'd. (Ah, i see, delve)
I went through the demo on the first page and found it quite complex (but then I am stuck in existing patterns of course).