// the example expression from above:const bind(String).toValue('hello, world!');// is unwrapped by inlining functions and methods:// Step 1: inline `bind`const BindingBuilder(String).toValue('hello, world!');// Step 2: inline `toValue`const Binding(String, 'hello, world!');
const Binding(const BindingBuilder(String).type, value);
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
To unsubscribe from this group and stop receiving emails from it, send an email to misc+uns...@dartlang.org.
This is a cool idea, but I think there's a problem. In particular, I think you did the transformation too quickly between steps 1 and 2.
const Binding(const BindingBuilder(String).type, value);Unfortunately, the part in bold isn't a constant expression.
Be very useful for some of my packages that use annotations like constrain and shelf_rest
+1 for this being a cool idea.
Be very useful for some of my packages that use annotations like constrain and shelf_rest
@Test("you can add numbers")testAddition() {expect(1 + 2, equals(3));}
For example, this proposal does not include: ... lazy evaluation
const expressions can be syntactically and lexically transformed to the existing syntax that is accepted by current Dart implementations. Anything that requires more than static transformation is beyond the scope of this proposal.
// fn.dartconst name = "I'm from fn.dart";const fn() => name;// main.dartimport 'fn.dart';const name = "Oops, I'm from main.dart";@SomeAnnotation(fn())main() { ... }
If you make too many language decisions based on how Dart is currently used then you will likely just entrench that use and deter others.
Dart is an excellent language on the server side and it would be sad to see useful language features ignored because Dart on the server is not yet that popular.
> Our runtime reflection story doesn't play nice with the dominant way that Dart is executed in the wild (compiled to JS)
If you make too many language decisions based on how Dart is currently used then you will likely just entrench that use and deter others.
--
Dart was sold as as a web language. The fact it is useful server side somewhat seems pointless given python exists. It's not even close between python and dart in terms of mature libraries especially db access.
Dart promised to bring sanity to web development to replace it and now seems withering in that regard.
To unsubscribe from this group and stop receiving emails from it, send an email to misc+uns...@dartlang.org.
Long reply is long!Theoretical consistencyI like the proposal in principle. The fact that a semi-arbitrary set of methods/functions is hardcoded in the language as "these are const and nothing else is" has always felt magical and special case-y. Also, any time users can write an expression, they almost always want to be able to create their own abstractions so they don't have to copy/paste the same expression over and over again. const expressions have always been a sort of unloved step-child to normal expressions in Dart.
Pragmatic usefulnessHaving said that: in practice, I don't think const has proven to be that useful in Dart. Angular is very metadata and metaprogramming heavy, so it's a bit of an outlier, but in a lot of Dart code I read, const is rarely used. I've seen a number of classes start out with const constructors and then end up becoming non-const over time because the limitations are too onerous. When that happens, honestly, not much is lost. It's not like using const gives you that much benefit in Dart.Given how much complexity they add to the language, I don't feel they've ever really carried their weight. I could be wrong, but my intuition is that a lack of const functions/methods isn't what's holding them back. The main problem is they just don't do much.
They exist for two reasons (that I know of):
- To possibly enable some VM optimizations. Since you know a const expression's result will never change, the VM could cache it. For example, in code like:
for (var i = 0; i < 9999999; i++) {
var c = const SomeSlowToCreateClass(...);
}
It's safe to hoist that const constructor out of the loop since it will never change. Maybe I'm wrong, but I believe smart VMs can and do do that for regular non-const classes automatically anyway, so I don't find it very compelling to add a whole shadow "const" sublanguage just to enable that. Even if the VM can't optimize this, you know, just hoist it yourself.
- To have some values that are reliably computable at "compile time". This is your use case, because metadata annotations require this. That way, the values of the parameters to a metadata annotation can be computed at "compile time."
---You don't specify this, but your semantics require that const functions and methods cannot be recursive or mutually recursive. Otherwise, the expansion doesn't terminate.
If we add constant functions, I think users will almost immediately want some kind of flow control, at least branching. Think how nice it would be to have a const function that allows a single argument or a list of them and can handle both cases appropriately.
At that point, recursion could be allowed as long as there was a reliable base case. But now you're inching towards Turing-completness and all of the scariness that causes in code that runs at compile/static-analysis time.
---I agree that if you're going to have const functions, you should have const methods too since Dart is so method-oriented. Also, doing so would give a coherent way to explain why "1 + 2" is a valid const expression. I do worry that somehow dynamic dispatch may sneak in. I can't think of any good examples, so maybe not.
As always, this is just my gut feeling. I definitely don't speak for the entire team.
Cheers!- bob--On Mon, Aug 24, 2015 at 12:03 PM, 'Natalie Weizenbaum' via Dart Misc <mi...@dartlang.org> wrote:If both const functions and const methods must be preceded with the const keyword, wouldn't your example have to be written as const (const bind(String)).toValue('hello, world!')?--On Sat, Aug 22, 2015 at 5:03 PM, Anders Holmgren <andersm...@gmail.com> wrote:+1 for this being a cool idea.
Be very useful for some of my packages that use annotations like constrain and shelf_rest
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
To unsubscribe from this group and stop receiving emails from it, send an email to misc+uns...@dartlang.org.
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
To unsubscribe from this group and stop receiving emails from it, send an email to misc+uns...@dartlang.org.
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
To unsubscribe from this group and stop receiving emails from it, send an email to misc+uns...@dartlang.org.
I do worry that somehow dynamic dispatch may sneak in. I can't think of any good examples, so maybe not.It shouldn't - const methods will only make sense on const objects, so it's the actual method on that object that needs to be const, and if it is, you are fine.
class Foo {const method() => "Foo";}class Bar {const method() => "Bar";}const fn(bool condition, Foo foo, Bar bar) => (condition ? foo : bar).method();
We do need to consider whether overriding a non-const method with a const method (or vice versa) is a warning or error. It might not need to be.We probably also want to allow access to final fields on const objects. That breaks the field/getter symmetry, so we might want to define const instance fields (the ones you are allowed to read at compile-time) vs non-const (just plain final) fields. That way, you can see that changing a const instance field to a non-const getter will break code. If a field is just final, you keep the option of making it a non-const getter later.
On Mon, Aug 24, 2015 at 11:09 PM, 'Lasse R.H. Nielsen' via Dart Misc <mi...@dartlang.org> wrote:I do worry that somehow dynamic dispatch may sneak in. I can't think of any good examples, so maybe not.It shouldn't - const methods will only make sense on const objects, so it's the actual method on that object that needs to be const, and if it is, you are fine.Since you mentioned ?: can be used in const expressions, then consider:class Foo {const method() => "Foo";}class Bar {const method() => "Bar";}const fn(bool condition, Foo foo, Bar bar) => (condition ? foo : bar).method();Is this OK? If we evaluate the ternary operator at compile time, then after that, we know which branch was chosen and can then dispatch the method() call at compile time too, and it works. But the least upper bound of the ?: operands gives a result type of Object, which doesn't have method().I guess this would be a static warning, but could work by "dynamically dispatching at compile time"! This feels like a rathole to me.
We do need to consider whether overriding a non-const method with a const method (or vice versa) is a warning or error. It might not need to be.We probably also want to allow access to final fields on const objects. That breaks the field/getter symmetry, so we might want to define const instance fields (the ones you are allowed to read at compile-time) vs non-const (just plain final) fields. That way, you can see that changing a const instance field to a non-const getter will break code. If a field is just final, you keep the option of making it a non-const getter later.Oof, this also feels really complex. I'd rather keep const dead simple like it is now and like C# attributes are, or just use regular Dart expressions. It feels like we have to add a ton of complexity to const just to get an incremental increase in expressiveness otherwise.
On Wed, Aug 26, 2015 at 12:49 AM, 'Bob Nystrom' via Dart Misc <mi...@dartlang.org> wrote:On Mon, Aug 24, 2015 at 11:09 PM, 'Lasse R.H. Nielsen' via Dart Misc <mi...@dartlang.org> wrote:I do worry that somehow dynamic dispatch may sneak in. I can't think of any good examples, so maybe not.It shouldn't - const methods will only make sense on const objects, so it's the actual method on that object that needs to be const, and if it is, you are fine.
Since you mentioned ?: can be used in const expressions, then consider:class Foo {const method() => "Foo";}class Bar {const method() => "Bar";}const fn(bool condition, Foo foo, Bar bar) => (condition ? foo : bar).method();Is this OK? If we evaluate the ternary operator at compile time, then after that, we know which branch was chosen and can then dispatch the method() call at compile time too, and it works. But the least upper bound of the ?: operands gives a result type of Object, which doesn't have method().I guess this would be a static warning, but could work by "dynamically dispatching at compile time"! This feels like a rathole to me.
True.Compile-time constants are independent of static type checking, they just happen to be mostly type-safe so you don't see warnings like this much.We designed compile-time constant expressions to have the same meaning as if they were executed at runtime - except for the canonicalization, so if it works at runtime, it should work at compile-time.You could argue that you should get the same warnings too - the static type analysis doesn't have to do constant evaluation, so it doesn't know the actual type of the constant.
We already have the problem of the actual type not matching the static type in other places, even at compile-time.class C {const factory C.a() = A;}class A implements C, Z {const A();}class Z {}main() {const Z z = const C.a(); // Warning, compile-time safe.}
It's just that the ?: operator is very good at loosing the static type.Another example:class A {const factory A() = C.a;}class B {const factory B() = C.b;}class C implements A, B {final int id;const C.a() : id = 0;const C.b() : id = 1;}main() {const C c = (const bool.fromEnvironment("foo") ? const A() : const B());print(c.id);}
We do need to consider whether overriding a non-const method with a const method (or vice versa) is a warning or error. It might not need to be.
We probably also want to allow access to final fields on const objects. That breaks the field/getter symmetry, so we might want to define const instance fields (the ones you are allowed to read at compile-time) vs non-const (just plain final) fields. That way, you can see that changing a const instance field to a non-const getter will break code. If a field is just final, you keep the option of making it a non-const getter later.
Oof, this also feels really complex. I'd rather keep const dead simple like it is now and like C# attributes are, or just use regular Dart expressions. It feels like we have to add a ton of complexity to const just to get an incremental increase in expressiveness otherwise.Agree, it's probably not worth the complexity it introduces
But if you want to make sure that certain expressions will have a single value that we can compute at compile-time, e.g., because we want to inline it during compilation, then you need something like `const`.
Perhaps we need to find a different perspective here, too? For example:"const" sub-language is just a euphemism for pre-processor. Very limited one, but still. In another thread, Lasse's comment indicates that dart might have warmed up to the idea of preprocessing (if my understanding is correct). This would make things simpler in many areas - e.g, right now "configurable imports" proposals are on their way to create yet another weird sub-language. Preprocessor makes this unnecessary.
My point is that the idea of eschewing preprocessor is getting more costly by the day. Maybe it makes sense to look at nim language for inspiration: Quote:"Nim meta-programming is done with the Nim language itself. That means that most Nim code can be executed at compile time, and Nim's ability to generate Nim-code at compile time is much more sophisticated"