-
Notifications
You must be signed in to change notification settings - Fork 22
Explain Syntax #21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
The syntax is, broadly, a strange combination of Haskell, ML, and Rust. It has first-class functions, pattern-matching, and a variety of other features typical for functional languages. Expression syntax is broadly similar to C-likes (you call a function Function calls
alternatively, the following syntax is equivalent to the above (but makes chaining function calls easier in many cases)
Conditionals(ternary operators, in most C-like languages)
Variable declaration
Pattern matching:(the final branch uses
Pattern-matching in particular is interesting and arises very often. If you're not used to functional languages, it might feel a little unintuitive but, but it's basically like C's Functions also support pattern-matching on their arguments directly. Consider a factorial function written in C: int factorial(int n) {
if (n == 0) {
return 1;
} else {
return n * factorial(n - 1);
}
} In Tao, we can very efficiently express this with pattern-matching in a way that allows the compiler to check the exhaustivity of our logic (i.e: ensure that we've covered all cases, and that no runtime errors are possible):
This The end result of this is that the compiler can automatically determine that no underflow or unhandled cases exist in the resulting problem, allowing writing programs with significantly more confidence that they work correctly. Another example is the
Here, we have two patterns. The first binds on the empty list, As before, the compiler verifies that we're handling all possible cases and will throw an error if this is not the case. Definitely give it a try! There is a lot more to explain about the syntax: I've not touched on sum types, tuples, classes (called 'typeclasses' or 'traits' in other languages: they aren't the same as C++-style classes!), etc. but hopefully this gives a taste of what Tao can do! One thing I would mention is that Tao is still very experimental. I change the syntax relatively often and I'm still doing some pretty fundamental work on the compiler internals. I don't expect it to be usable for general-purpose programming for quite a while yet, if ever. If that's fine by you, then feel free to play around with it to see what you can get it to do (or, alternatively, figure out how it can be broken!). |
For sure, I'd be happy to explain any particular areas of the syntax you find particularly confusing! |
Thanks for taking the time to write this. This has certainly clarified some things for me.
To give you a sense of my background: I have a passing familiarity with Haskell, and a pretty good handle on Rust.
Does this mean that all variables are explicitly scoped to a given expression?
This pattern matching is amazing! Can the expressions be arbitrarily complex? Can they involve more than one variable? Does it work on user defined types? If it doesn't now, is something like that even possible or desirable?
This is perfectly fine. I'm primarily interested in Tao as a case study in language design. I've started dabbling in languages and I find them fascinating.
What is the most convenient way for me to ask you questions? Should I just keep opening new issues? I know that some maintainers have strong feelings about issues being used as a general forum. |
Yes. The syntax is
Thanks. This grew out of the desire to statically avoid runtime errors when doing
Unfortunately not, and this is (in general, at least) intractable. Currently, only arithmetic add works for I would like to generalise this more in the future to allow for patterns like
Uh... sort of? But not deliberately. Consider a definition of
Here,
( Obviously, the type system would be able to reason about this but I'm sure this isn't quite what you were expecting 😀
Totally fine to throw them in here, I'm not bothered. For me, Tao is just a fun exercise to see how much I can learn and how much I can push language design so I'm very happy to discuss it casually here! |
may I suggest that this is extracted to SYNTAX.md file on the repository itself |
A previous revision of the language had a book explaining the language, and I'm hopeful that I can find the time to resurrect that once the syntax has stabilised a little. Much of the behaviour remains the same, so the old book might still be of some use! |
Just to be sure: Am I missing something? Shouldn't this be |
Nope, it's i.e: That might sound a little topsy-turvy, but it enables really nice method-chaining-like syntax like this:
|
Ah, cool. Well that syntax is really confusing, but I see the value (as in the last example you provided). |
Yes, I'm not overly happy with it myself. It also comes with the difficulty that functions like I am considering moving to a setup where it's possible to implement functions "on" a type, Rust-style, and the type system would choose which implementation to use based on the first parameter. I've not done too much thinking about this yet though, so I'm open to ideas! |
Well, I really like function chaining syntax in Rust, but I am not so sure whether it actually makes sense in a functional language. FWIW, I find the composing in Haskell really nice: combined = sum $ map \x -> x + 1 $ range 0 10
-- or
combined =
let
mapper = map \x -> x + 1
in sum $ mapper $ range 0 10 (I am not a Haskeller, so that might be slightly or completely wrong). Which, AFAICS would translate to something like
in tao? I can clearly see from the first glimpse at that piece of code, what it does. |
Interestingly, Tao's
Close enough, yes. Tao uses C-style function calling syntax though (i.e: it requires parentheses) so it would be more like this:
I definitely agree. I've tried to keep Tao's actual syntax relatively minimal (at least, without hurting ease of use), tending to favour explicit keywords instead of opaque symbols. There are almost no operators in Tao that you wouldn't find in your typical C-like language, with perhaps two exceptions:
|
Hm, yes, you're right. Maybe the thing that is confusing to me is the missing spaces around the operator
I guess I have to wrap my head around that a bit better. Does it mean that we can short-circuit function implementations in case of error with the Further syntax questionsI have a list of questions about syntax here. Please don't get overwhelmed with me asking a lot of questions here and don't hesitate to skip some or all of them if you think they're not worthy of an answer 😆 Maybe a bit context to all my questions (also for other readers of this comment): I started playing around with my own idea of a functional programming language [here](https://github.com/vunk-lang/vunk-lang/). There's nothing to see yet except some syntax examples, because I am a lazy person and only implemented a tokenizer so far. That's also why I contribute here: Because I hope that joining forces results in me getting my ass of the couch and do something cool.
My idea of a functional syntax is inspired by three points:
(from most important to "least" important). There's an example of the syntax here(, or the same code with some comments here). Pattern matchingYou mentioned above that the last branch in a pattern uses
Is this necessary? I believe that it makes maintenance of code rather complex, as adding a new variant would mean that the last variant needs to be touched as well, right? Variable declarationI see that the But it is rather hard to maintain, isn't it?
? Function call syntaxWhy is the function call syntax made with parentheses? Especially with currying and possibly partial function application in mind, it becomes even more of a question to me. I see that Another example: Would this be the right way:
for defining a function Implementation of typeclassesAs far as I can see, implementing a typeclass is done with How about Trait boundsOr is it "class bounds"? 🤔
This is really confusing to me. I guess it means "For all A that implement Neg, implement Neg for [A]". But the syntax is very confusing. How about this:
or, if we want to be a bit more consise:
or
Additional bounds could then be added with
|
Ah and one bit that also just came up: What's the difference between |
Yes, effect propagation can short-circuit, just like
I originally added this is avoid needing either delimiters (like the braces that surround
Tao actually supports your suggested syntax! You can do
Mostly personal preference at this stage. I've always used C-like languages, and I found it easier to use. I'm not opposed to switching though! Although Tao currently supports currying, I'm actually tempted to remove it (or, at least, require explicit currying, perhaps like The argument for this becomes even greater if the
Yes.
I see typeclasses as sets.
Tao supports
Is just as valid. I use
It's true that function syntax is a bit opaque right now, and this is something I've been trying to come up with a rugged solution for. I believe the reason for this is that the type signature is separated from the function expression itself. If we fit it into a more Rusty syntax, you end up with: fn fix<A, B, e>(
f: fn(A) -> e ~ B,
n: A,
) -> e ~ B {
f(fix(f), n)!
} Having the types be layered on top of the function definition help quite a bit. I want to find a similar syntax for Tao that doesn't involve throwing braces and arrows everywhere as Rust does. That said, the definition of
It doesn't. As mentioned earlier, I think it would be a useful feature to have and would improve both error messages and also allow differentiating between difference functions with the same name, such as
is just syntax sugar for
It's part of my effort, as mentioned above, to come up with a more terse and easily understandable syntax for function definitions, but I consider it incomplete. In Tao, functions are just values (as in most functional languages). There's no difference between a value item and a function item. In fact, value items can have type parameters! (unlike, say, Rust's
You might initially be a little concerned about this: what if we created a value item that had a side-effect such as printing to the console? Surely that would need to happen in a const (i.e: compile-time) context? Well, effects solve this problem!
Because effectful functions return effect objects, this does nothing: but gets assigned the type
And you'll end up with In effect, this means that all Tao code is |
Hi,
I think this language looks pretty cool and it'll be informative to see chumsky being used as intended by you, the original author.
However, I'm having trouble learning the language's syntax from the examples. If you have the time, would you be willing to write a brief explanation of the syntax?
I understand that this is a hobby project so I'm not looking for anything fancy, it's just that I'm interested in your thoughts on language design and I'd like to understand it a bit better. If I end writing any programs in tao that actually work, that would be entirely incidental.
If it'd be helpful/interesting to you, I can write an itemized list of things I find confusing with links to the relevant lines of code.
The text was updated successfully, but these errors were encountered: