4 ms·
ObjC's dot syntax? Sure. That's easy in Lumen: https://github.com/sctb/lumen/commit/6410c8cc2de66d1976515bdd71ab9b65c12cbf10#diff-910c7ff4864f437a8c67427b7b0
by laarc 11y ago
ObjC's dot syntax?
Sure. That's easy in Lumen: https://github.com/sctb/lumen/commit/6410c8cc2de66d1976515bdd71ab9b65c12cbf10#diff-910c7ff4864f437a8c67427b7b055657R70 https://github.com/sctb/lumen/commit/6410c8cc2de66d1976515bd...
Is it possible to use this technique to introduce, say, infix arithmetic operators?
Yep! I wrote a macro to swap any instance of `x with the previous expression. Meaning, it allows you to write:
(foo `= (x `+ y))
rather than
(= foo (+ x y))
The reason it was so easy to do this is because `foo is shorthand for (quasiquote foo). So the macro simply steps through a body of code, looks for any instance of quasiquote followed by an atom, and then swaps it with the previous expression.
But more generally, it's easy to write a macro to do whatever you want. If you really want infix expressions all of the time, I could imagine writing a macro which matches the pattern (... + ... + ...) and replaces it with (+ ... ... ...)
That's made-up notation, but the idea is just "look for some set of symbols, like + or /, which occur within a list in between all of the other elements, and then move the symbol to the front of the list."
The power is available to you, but whether you choose to use it is a separate question. Prefix notation tends to be a win for everything except math. And even for math, it's usually a matter of code formatting. Rather than
(- (* 2 (/ (+ x y) (+ a b c))) 1)
try
(- (* 2
(/ (+ x y)
(+ a b c)))
1)
or
(let u (+ x y)
(/= u (+ a b c))
(*= u 2)
(-- u))
Once Laarc has support for indentation-as-parens, it'd look like:
let u (+ x y)
/= u (+ a b c)
*= u 2
-- u
which is rather pretty, and has no ambiguity. One of pg's essays on Arc mentioned this feature, and it seems like a good idea, so I hope to pursue it.
- akkartik 11y ago0. Is Laarc an arc variant you're working on? I don't see it on the github page. 1. You might be interested in how my arc-inspired language did indent-sensitivity and infix: http://akkartik.name/post/wart http://akkartik.name/post/wart. For example, here's bresenham's line-drawing algorithm in wart: https://gist.github.com/akkartik/4320819 https://gist.github.com/akkartik/4320819. There are more code samples at http://rosettacode.org/wiki/Category:Wart http://rosettacode.org/wiki/Category:Wart. 2. Do you have a username on arclanguage.org? Perhaps we've met!
- laarc 11y agoIt is indeed. I'm in the process of porting from Racket to Lumen. It's taking a bit, and it'll be tricky to add true greenthread support to js and lua, but it's a win so far. Wart is freaking cool! Thanks for showing that. Whoaaa, you use tangle/weave! How do you like it / what do you think about literate programming? I was batting around the idea of writing code that way, but it seemed like tangle might not be the best solution. But I love your 000prefix naming scheme; I instinctively do that for branches. After reading through a few files starting at https://github.com/akkartik/wart/blob/master/literate/000organization https://github.com/akkartik/wart/blob/master/literate/000org... it became pretty clear how wart worked, pretty quickly. I'm mainly wary of the "compile" step that using Tangle implies; do you find it slows you down much? Would you choose to do it that way if starting fresh? What would a language ecosystem be like without any backwards-compatibility guarantees, super easy to change and fork promiscuously? It's fun to find someone has been mulling over the same problems! I was considering taking Laarc in a similar direction: (import "akkartik/foo") That would check whether the folder "../foo/akkartik" exists, and if not, clone foo from github.com/akkartik/foo. It would also rewrite its own source code to look like: (import "akkartik/bar" "f1d2d2f924e986ac86fdf7b36c94bcdf32beec15") That means whenever someone clones your codebase, running the program would cause them to clone github.com/akkartik/bar using commit f1d2d2f9. So it's static linking, basically. It's a guarantee that "This source code will always work, the same way (+ 1 2) will always yield 3. You could copy-paste this source code into a gist, and whoever ran it would end up running the same program." That removes dependency hell / worrying about versions entirely. But it's not the right solution, and I've been searching for a better one. What do you think? The problem is that it throws away the ability for the code to pull updates from library maintainers. If the import is "pinned" at commit f1d2d2f9, then you push a security-related patch to akkartik/bar, most existing code will stay vulnerable forever, because most code is never maintained after being written. I was thinking of following that model, but using the convention that libraries are expected to use git tags in order to indicate major.minor.patch, and (import "akkartik/bar" "f1d2d2f924e986ac86fdf7b36c94bcdf32beec15") will bump itself to the next commit if it's tagged as an increment of the patch version. What kind of things have surprised you about Wart during development? Any unexpected pitfalls or interesting discoveries along the way? Thanks again for pointing it out! By the way, were there any ambiguities with indentation-as-parens? I haven't thought about it rigorously, so I was just wondering if there are any corner cases to watch out for when I add it.