til-lang / til

An easy to extend command language
56 stars 5 forks source link

Questions & future #1

Open dumblob opened 3 years ago

dumblob commented 3 years ago

Newbie here. I'm following Til for a few weeks now and like the syntax and its simplicity. There is actually a somewhat similar actively developed attempt to create a simple Tcl/Rebol/Red/...-like language called Arturo but I must admit I like the syntax of Til more. Though Arturo is undoubtedly a very good source of inspiration regarding APIs, concepts, etc.

Of course, regarding functionality Til is extremely limited, but let me ask some other questions which IMHO determine the future direction of the language.

1) What are the expectations of maximum possible performance? In other words, will the language provide means to compile/transpile its static parts into highly efficient C/D/platform_specific_binary code or not (e.g. Red is a language with such a hybrid static-dynamic compilation approach)?

2) What are the expectations of the "safety degree" (defensive programming without any runtime performance cost - i.e. compile-time checking of correctness - e.g. using explicit compile-time types, immutable variables by default, no exceptions but effects on steroids or optionals_with_one_character_propagation instead unlike Go, contracts/protocols, static assertions, static code flow analysis, etc.)?

And if you're wondering how to unobtrusively include "types" or alike, [Phix](http://phix.x10.mx/docs/html/types.htm ) has quite an interesting approach (though that's just half of the problem - the other half is compile-time checking of relations among types themself - i.e. which combinations of types at which point of the variable life are allowed - this is usually done with static asserts, but there might be other options...).

3) Actually related to (2) but still separate. What are the expectations of metaprogramming capabilities? I mean, rather no unconstrained eval (I can imagine "safer" eval variants - will elaborate if anyone asks), but maybe something like compile-time macro-like eval (but with hygienic variables etc.). For the language itself this is an enormous advantage as this guarantees long-term sustainability if used in the form of from future import feature5 ala Python while satisfying special needs of companies as well as freaks like me :wink: who need to have some specialties not suitable for upstream.

4) Is Til already used for some non-toy projects (preferably by some medium or bigger company)? Or are there at least any serious plans to do so?

5) Any true concurrency support (leveraging more CPU cores)? Don't be afraid of this - no need to introduce any new syntax nor any special primitives. After 10+ years of participating in designing concurrency APIs for languages like Nim, V, Red, etc. I've come to conclusion that CSP/async-await API shall be modeled identically as APIs for os-level threads/processes (usually fork-join with lock/unlock, but nowadays preferably nursery pattern with transactional memory).

6) If Til gets compile-time support (i.e. pre-run phase to accomplish e.g. (2)), do you plan to add "upfront" FFI support (i.e. compile time FFI with manually defined function signatures & manually defined struct signatures and their offsets etc. in dynlibs for maximum performance)?


Btw. let me say one more thing. Prudence says that the you're not supposed to write complex code in Til never happens. A language either died quickly (in which case it doesn't matter) or became popular/used_in_practice in which case it is being used for writing complex code.

Probably the most horrifying widely known example is Python which after many years culminated with saying "we can't develop Python 1.x 2.x any more and need to do major changes here and there in Python 3.x" which was extremely painful.

And only because they deliberately tried to pursue you're not supposed to write complex code in Python for too long instead of trying to watch out for mistakes soon after their creation. Btw. there is soon-to-be-accepted PEP about macro support in Python - I myself was really surprised by that, but this further underlines the fact I stated above - a language will either die soon or become full-featured for real life complex programming.

Generally it's better to accept this fact and rather outline how to tackle it generally (not necessarily a very concrete plan like Java has for the next 20 years but also not overlooking this problem for too long).

cleberzavadniak commented 3 years ago

Newbie here.

Hi! Curiously, I'm also a newbie.

What are the expectations of maximum possible performance? In other words, will the language provide means to compile/transpile its static parts into highly efficient C/D/platform_specific_binary code or not (e.g. Red is a language with such a hybrid static-dynamic compilation approach)?

I created Til just to learn how to write a language, so no grandiosity should be expected. Now I'm starting to experience how to "maintain" a language and how to deal with both the need for things like some roadmap and with the user's expectations.

For now my major goal is to keep the language code as clean as possible. I want that any reasonably experienced programmer be able to get the grasp of the language internals in one day and without feeling overwhelmed by any complexity. At first it may seem at odds with some performance concerns, but I believe reasoning about performance is much easier when the code base is simple enough.

While keeping the code simple, the next big thing is distribution. I have a strong Python background and I know well how frustrating it can be to ship/deploy/distribute some Python applications. Java .jar files, being a zip package with almost everything the VM needs is a very nice thing, IMHO. Tcl Starpacks are even better. So, I'm willing to give up performance any time if that means my programs are very easy to distribute.

Of course, there are amazing projects like AppImage out there, so, when the time comes, that's going to be an interesting research area.

So performance itself is the third place in the priority list. I think it's not that hard to add JIT powers to the interpreter and following a LuaJIT approach is what's on the top of my mind right now. But D is a very extensible language itself and there's also this possibility of simply translating Til programs (or parts of them) to D, somehow.

But, as you said, there's a lot of work to be done and everything can change until v1.0.0.

What are the expectations of the "safety degree" (defensive programming without any runtime performance cost - i.e. compile-time checking of correctness - e.g. using explicit compile-time types, immutable variables by default, no exceptions but effects on steroids or optionals_with_one_character_propagation instead unlike Go, contracts/protocols, static assertions, static code flow analysis, etc.)?

Well, Til is a scripting language and I'm not sure how well all those features would fit in an interpreter, but I'd love to have a "syntatic analyser mode", at least, to filter out the more obvious bugs.

About "exceptions", errors in Til behave in a similar fashion, propagating through callers (as it should be, IMHO) but are all handled together at scope level, so programmers are incentivized to segregate functionality into new scopes (by calling procedures instead of doing everything in only one). The reason for that is because I hate try/catch blocks - they are too intrusive for something we consider "exceptional behavior", but I also hate Go [inexistent] error handling policy.

Actually related to (2) but still separate. What are the expectations of metaprogramming capabilities? I mean, rather no unconstrained eval (I can imagine "safer" eval variants - will elaborate if anyone asks), but maybe something like compile-time macro-like eval (but with hygienic variables etc.). For the language itself this is an enormous advantage as this guarantees long-term sustainability if used in the form of from future import feature5 ala Python while satisfying special needs of companies as well as freaks like me wink who need to have some specialties not suitable for upstream.

D modules are already free to manipulate things as they may wish. In Til itself I'm trying to avoid "eval" of strings and I think it's much better to allow the programmer to manipulate the AST itself, since there are only a handful of possible nodes to use, anyway (and that, AFAICS, tends to make the metaprogramming parts more resilient to eventual syntax changes).

In the end, you should expect to see, soon (or not), new commands to manipulate the various types of lists, compile (that probably will return a SubList) and run (to execute the SubList content).

That and scope manipulation.

Is Til already used for some non-toy projects (preferably by some medium or bigger company)? Or are there at least any serious plans to do so?

It can't be used even for toy projects, haha! (But I can work hard all day if someone hire me to do only Til development, of course.)

Any true concurrency support (leveraging more CPU cores)? Don't be afraid of this - no need to introduce any new syntax nor any special primitives. After 10+ years of participating in designing concurrency APIs for languages like Nim, V, Red, etc. I've come to conclusion that CSP/async-await API shall be modeled identically as APIs for os-level threads/processes (usually fork-join with lock/unlock, but nowadays preferably nursery pattern with transactional memory).

Not yet, but I'm thinking exactly about how much I want to hide from the programmers. I tend to prefer exposing everything and just make sure sending messages between (micro)processes in different OS threads just follows the same principles as any message sending.

If Til gets compile-time support (i.e. pre-run phase to accomplish e.g. (2)), do you plan to add "upfront" FFI support (i.e. compile time FFI with manually defined function signatures & manually defined struct signatures and their offsets etc. in dynlibs for maximum performance)?

I believe someone sometime will be able to build something along these lines in D and make it a module with a nice API. std.sharedlib has a stub, already, that can call functions with void function() signature. But I'll confess I've not worked that much with dynamic libraries and would appreciate help with that a lot.

Btw. let me say one more thing. Prudence says that the you're not supposed to write complex code in Til never happens. A language either died quickly (in which case it doesn't matter) or became popular/used_in_practice in which case it is being used for writing complex code.

Yup. But the idea in this phrase is some sort of "do not be like Tcl": people love "pure Tcl" libraries because using C/compiled ones always present some sort of (weird) challenge. I hope people won't be afraid of using D to build and distribute modules (I'm not hiding the base language: Til even has TIL_PATH defaulting to $HOME/.dub). Dub is a great tool and I'd rather help the project to evolve than creating yet another language package manager.

Also, most concerns about performance are generally satisfied if you write things in D and just define the overall behavior in Til.

Probably the most horrifying widely known example is Python which after many years culminated with saying "we can't develop Python 1.x 2.x any more and need to do major changes here and there in Python 3.x" which was extremely painful.

That's a nice point and another thing I value a lot is stability. In the sense that my Til code should be stable: I write it today, I expect it to be "valid" for the next 20 years. Languages evolve, but everybody should hate rewriting already-working code.

That also touches the distribution issue: will people keep "til-1", "til-2" and "til-3" interpreters on their systems? Oh, please, God, no. There must be a better way!

Generally it's better to accept this fact and rather outline how to tackle it generally (not necessarily a very concrete plan like Java has for the next 20 years but also not overlooking this problem for too long).

Yes, it is.