8 ms·
I don't see why people won't just take the step D and Lisp do-- allowing full use of the programming language at compile time. You can execute an ordinary func
by crazypython 6y ago
I don't see why people won't just take the step D and Lisp do-- allowing full use of the programming language at compile time.
You can execute an ordinary functions at compile-time to read a DSL from a string or read attributes (reflective metaprogramming) on your program's classes. Take the string it outputs, use mixin(), and you have code. For example:
// Sort a constant declaration at Compile-Time
enum a = [ 3, 1, 2, 4, 0 ];
static immutable b = sort(a);
"a" only appears in the compiler's memory. "sort" is a normal function that runs at compile-time. "allowing accessto the full language at compile-time" is similar to what dynamic languages such as Python and JavaScript give you, except D is a static language with GCC and LLVM backends.
- dilap 6y agoZig takes this approach. I haven't done more than kick the tires curiously, but it seems very cool.
- empath75 6y agoDoesn’t the compiler already do optimizations like that?
- ncmncm 6y agoThe most useful values at compile time are types, so straight-up interpreting the core language at compile time is not enough. You need meta-typed named values to transport types in, and meta-functions to pass them to. Fortraith cleverly re-purposes existing features, doing some violence to language usage conventions to achieve it.
- deleted 6y ago[deleted]
- dependenttypes 6y ago> so straight-up interpreting the core language at compile time is not enough. You need meta-typed named values to transport types in, and meta-functions to pass them to. Can you please explain what you mean by this?
- neutronicus 6y agoIn Rust (for example), Types are not Values. You can't store them in variables, pass them to functions, etc. However, at macro-expansion time, often what you want to do is examine a Type and expand the macro differently based on some information about the Type. So you would like your Macro language to have some notion of manipulating Types that is absent from the language itself
- vertex-four 6y agoRust is getting that, gradually, with the work of replacing the ad-hoc "const evaluator" with miri (an interpreter for a Rust intermediate representation). Right now you have procedural macros, which are Rust code that operates on the syntax tree, including custom attributes. Proper reflective metaprogramming would be a fairly big step though - right now, the macro systems happen well before the type system even gets a chance to look at the code, so the data to play with types in an interesting way isn't there at the right step.
- Animats 6y agoRust is getting that, gradually. Uh oh. I'd hoped the language would settle down. The Go crowd knows when to stop. Go is mediocre, but stable.
- Rantenki 6y agoIt's possible to stop too soon though.
- TA0X4 6y ago>The Go crowd knows when to stop. Considering Go is removing "blacklist" from it's code and documentation because it can delusionally be construed as racist, I'd say they don't know when to stop.
- TA0X5 6y ago>The Go crowd knows when to stop. Considering Go is removing "blacklist" from it's code and documentation because it can delusionally be construed as racist, I'd say they don't know when to stop.
- ThA0x1 6y ago>The Go crowd knows when to stop. Considering Go is removing "blacklist" from it's code because deranged individuals can delusionally construe it as racist, I'd say they don't know when to stop.
- 6y ago
- zokier 6y agoRust have procedural macros https://doc.rust-lang.org/reference/procedural-macros.html https://doc.rust-lang.org/reference/procedural-macros.html
- zozbot234 6y ago> I don't see why people won't just take the step D and Lisp do-- allowing full use of the programming language at compile time. Because "full use of the programming language" implies Turing completeness, which means compilation may require unbounded time and compute resources. You can allow use of a non-Turing complete subset, and this is something that dependently-typed languages can do quite elegantly.
- pilif 6y agoMany type systems are already Turing complete like C++ and indeed Rust as evidenced by the project linked here. It’s a valid point. Of compilation already is Turing complete, why not just drop the pretense and allow arbitrary compile time expressions.
- dllthomas 6y agoEven where nothing in compilation is Turing complete, many pieces may be unbounded. And where there are artificial bounds, they could as well be applied to something otherwise Turing complete.
- dependenttypes 6y agoA program that requires 2^256 time units and 2^256 memory units is not really any better compared to unbounded computations.
- dimtion 6y agoOne issue not yet mentioned with Turing complete language at compile is that it makes tooling and IDE integration much more difficult. When you need to run an unbounded program each time you want to provide real time feedback, like type inference or in Rust case lifetime inference, you make the language tooling much less simple and accessible.
- dependenttypes 6y ago> One issue not yet mentioned with Turing complete language at compile is that it makes tooling and IDE integration much more difficult How so? > When you need to run an unbounded program How is a program that provably terminates but takes 2 years to finish any better for compile-time computation? You want timeouts in either case.
- ImprobableTruth 6y ago>How is a program that provably terminates but takes 2 years to finish any better for compile-time computation? You want timeouts in either case. I'm not sure how realistic that actually is. Besides certain party tricks like encoding the ackermann functino using primitive recursion, I haven't actually seen anything like that. From my experience the vast majority of programs that don't finish in a reasonable amount of time are those that have some logic bug. A timeout seems pretty off-putting. The idea that compilation could fail on a weaker machine just because it isn't fast enough just doesn't sit right with me.
- qppo 6y agoThe analog of a timeout in a compiler is recursion depth limits.
- ImprobableTruth 6y agoThat alone definitely won't suffice. A naïve fibonacci implementation will give you a recursion depth of n, but even fib(64) take ages.
- dependenttypes 6y agoIt should be noted that gcc and clang both execute certain functions at compile-time at their higher optimization levels. In addition C++ has constexpr which marks an expression to be evaluated at compile-time.
- codr7 6y agoI suspect a big reason is that you need an interpreter in addition to the compiler. From what I understand, the D gods spent quite some time and effort developing theirs. For interpreted languages, there are no excuses; hooking into the interpreter at compile time is trivial. Full macros [0] are nice, but depends a lot on the syntax. A way to evaluate expressions at compile time [1] would go a long way. [0] https://github.com/codr7/gfoo#macros https://github.com/codr7/gfoo#macros [1] https://github.com/codr7/gfoo#bindings https://github.com/codr7/gfoo#bindings
- dependenttypes 6y agoIf you do not want to implement a separate interpreter you can do multiple compilation passes instead.
- mikepurvis 6y agoTrue, but in the cross-compilation case, you then need to do fun stuff like compile anything invoked at compile time for the host arch as well as the target.
- octo_t 6y agoAnother issue not mentioned is cross-compiling. If the result of my `sort ` function is dependent on `sizeof(void )` being 8, when I compile from my x86 hardware for a 32-bit only architecture, assumptions go awry. Note that this isn't likely with something like sort, but definitely is* likely with precomputing values/structs etc.
- deleted 6y ago[deleted]
- staticassertion 6y agoThey do. You can. You have procedural macros, which are literally "Rust code is the input, which you write rust code to manipulate, and output more rust code". You have const fns, which are interpreted at compile time, and are closer to what you're referring to.
- deleted 6y ago[deleted]
- a1369209993 6y agoBecause that's fundamentally incompatible with a competently-designed compiled language. Consider: fn immutable foo() long: asm(long x:"rax") "mov rax 7" return x Now try cross-compiling that from a 32-bit ARM machine. Aside: D is kind of weird in this regard because most of it is designed to work as a interpreted language as well as a compiled one. To the extent the D is good, it's not compiled[0]; to extent that it's compiled[0], it's not good. 0: in the language design sense, not the language implementation sense.
- BeKindAndLearn 6y agoPretty much all languages with turing-complete compile-time expressions only expose a subset. This comfortably lands in the "not in that subset" category.
- a1369209993 6y ago> [...] and Lisp do-- allowing full use of the programming language at compile time. If you only expose a subset, you very specifically don't have the full use of the programming language.
- BeKindAndLearn 6y agoNow you're just being pedantic. Also, leaving out the "D" just before your quote is plain disingenuous. That contextualizes the discussion and clearly establishes we don't mean being able to directly run ASM operations and syscalls willy-nilly at compile time.
- zamalek 6y agoThis is just nerd flexing. Rust has a slightly more flexible compile time code generation story than D. There's even a package that connects to your SQL DB and type-checks your queries.
- pull_my_finger 6y agoTerra[1] does this using Lua as it's compile time language. [1]: http://terralang.org/ http://terralang.org/
- s17n 6y agoLisp failed as an industrial language precisely because it has powerful meta programming capabilities. In the real world, nobody wants to have to solve a puzzle every time they visit a new area of the codebase.
- BiteCode_dev 6y agoI hope not. I really don't want Rust to be crippled with a 1000 of DSL just because devs could write them easily.
- GolDDranks 6y agoThe recent signs are that in near-future Rust releases you are able to have rudimentary logic in constant expressions: if, match, loop etc. (Around Rust 1.47 ish. That's three months away.) When the capabilities of the constant evaluation system get improved and stabilized, we are going to see the exact feature you are describing. (With the caveat that non-deterministic functions are not allowed to ensure deterministic builds.)