(So this is the post where I finally reveal myself as totally incompetent.)
> 1. Want to make sure we can select platform-dependent implementation code. The system should be able to handle code that works different on client and server.
> 2. A way to to pass in constant values that can be compiled into the snapshot or execution.
From these two points, the first is easily solvable by the predicated imports mechanism that Kasper suggests (and I already suggested it too, and even described in dartbug.com/6943).
And the second one... what is it really supposed to do? I can't see how it can solve the "general configuration" problem... and frankly, I don't really understand what this problem really looks like.
> Gilad: It's certainly simpler, but it doesn't solve generalized config problem.
But what that problem is?
> Me: Say you're using some package "foo" that in turn uses a logging package. You want to swap in your awesome logging package even though "foo" knows nothing about it and wasn't designed with that abstraction in mind.
I firmly believe that putting dependency injection into the language is ultimately a good thing, but I'm not sure that Dart is a good fit for that.
Don't we have some other example of the "general configuration" problem that isn't solved by predicated imports but doesn't immediately lead to dependency injection? Or is this "general configuration problem" already understood to be equal to DI?
> Gilad: I want some use cases.
Me too.
> Lars: One problem is that you cannot write package that has both client and server code embedded in it.
Predicated imports, anyone?
> Lars: The two top issues:
>
> 1. Platform-dependent parts.
> 2. Can set constants from outside.
Been there...
> Gilad's proposal would address 1 like:
>
> library d({
> x: LIbrary.platform.name ='dartjs'
> ? Library.fromURI('dart:html')
> : Library.fromURI('dart:io')
> })
I can't see how this solves more problems than the predicated imports stuff... except that it has much more complicated syntax. That is good for consultants, but noone else.
> Kasper: One issue is that ?: isn't a const expression.
Gilad says it's perfectly doable: dartbug.com/5558
> Lars: So the two cases we're worrying about are:
> 1. Simple cases where you know set of options you're selecting from.
> 2. Open-ended dependency injection.
Oh! That's probably it.
So, if we use the logging example, then point 1 is about enabling/disabling logging or setting a minimal log level, while point 2 is about choosing logger implementation (potentially external, so thatit doesn't degenerate to 1). Is this any more complicated? If not, do we really need this inside the language? This stuff was solved on the application level like a gazillion times. Is this about helping dart2js to produce smaller output by doing some decisions ahead of time?
LT
2. Can set constants from outside.
1. Platform-dependent parts.
For the most immediate use case, platform dependent imports/exports, you want to choose between different libraries to import/export, not selectively import a single library.
So I think the where clause could get unwieldy and error prone:
import 'package:foo/browser.dart' as foo show bar, baz, bang where platform == 'browser';
import 'package:foo/standalone.dart' as foo show bar, baz, bang where platform == 'standalone';
I think being able to use any constant String expression as the import/export URI would be better:
import 'package:foo/${platform == 'browser' ? 'browser' : 'standalone'}.dart' as foo show bar, baz, bang;
I don't think string interpolation is currently considered constant, but it should be when it is guaranteed to yield a String, since there is no need to execute an arbitrary toString() in that case. Obviously ternary expressions should be able to be constant too.
Presumably this "platform" constant could be defined in a library e.g. 'dart:platform' which one could import. The editor/analyzer could expose a setting for which platform to analyze with.
This could solve the general problem of how to use constants to control imports/exports. The general problem of how to externally define constants (which could be used even beyond the scope of imports/exports) could be saved for later.
import 'package:foo/${platform == 'browser' ? 'browser' : 'standalone'}.dart' as foo show bar, baz, bang;
> 1. Want to make sure we can select platform-dependent implementation code. The system should be able to handle code that works different on client and server.
> 2. A way to to pass in constant values that can be compiled into the snapshot or execution.
From these two points, the first is easily solvable by the predicated imports mechanism that Kasper suggests (and I already suggested it too, and even described in dartbug.com/6943).
And the second one... what is it really supposed to do? I can't see how it can solve the "general configuration" problem... and frankly, I don't really understand what this problem really looks like.
So, if we use the logging example, then point 1 is about enabling/disabling logging or setting a minimal log level, while point 2 is about choosing logger implementation (potentially external, so thatit doesn't degenerate to 1). Is this any more complicated? If not, do we really need this inside the language? This stuff was solved on the application level like a gazillion times.
Dart code could import it, eg: my entry point app file could declare:
import "constants:myfile.yaml";
which would / could supply all required constants for all imports that I use. It would be an error if there are external constants defined that aren't supplied in an external file.
I think being able to use any constant String expression as the import/export URI would be better:
import 'package:foo/${platform == 'browser' ? 'browser' : 'standalone'}.dart' as foo show bar, baz, bang;
I don't think string interpolation is currently considered constant, but it should be when it is guaranteed to yield a String, since there is no need to execute an arbitrary toString() in that case. Obviously ternary expressions should be able to be constant too.
I think being able to use any constant String expression as the import/export URI would be better:
import 'package:foo/${platform == 'browser' ? 'browser' : 'standalone'}.dart' as foo show bar, baz, bang;I don't think string interpolation is currently considered constant, but it should be when it is guaranteed to yield a String, since there is no need to execute an arbitrary toString() in that case. Obviously ternary expressions should be able to be constant too.This was discussed, more or less. The problem here is that now the editor has to be able to evaluate those constant expressions in order to figure out what libraries to use to analyze your code. If the import path is a simple literal but then whether or not it gets processed is conditional, then the Editor can easily find all of the libraries you may import and it can let you see how the different conditions would affect your code.
Gilad: It's certainly simpler, but it doesn't solve generalized config problem.Lars: Can you come up with an example?Me: Say you're using some package "foo" that in turn uses a logging package. You want to swap in your awesome logging package even though "foo" knows nothing about it and wasn't designed with that abstraction in mind.
>> import 'package:foo/${platform == 'browser' ? 'browser' : 'standalone'}.dart' as foo show bar, baz, bang;... you have 100 files, and you copy this nice construct into each of them?
To be fair, dependency injection a-la spring framework is a nightmare, too (on top of being ugly).
What's wrong with keeping it simple? Every class can get whatever it needs from an object that knows what is what:class Foo {Logger logger=Config.getLogger("Foo"); // Config is a normal class.}
Dependencies and modularity are deeply close to Gilad's heart and I think by "general configuration" he means that any module can have all of its dependencies controlled by the module that uses it. This is probably a good start to see where he's coming from: http://gbracha.blogspot.com/2009/06/ban-on-imports.html
I believe he's also worried that not trying to solve dependency management generally will mean that the Dart community will eventually recapitulate OSGI, which would seem to be a kind of moral crime according to some people on the team.
So, if we use the logging example, then point 1 is about enabling/disabling logging or setting a minimal log level, while point 2 is about choosing logger implementation (potentially external, so thatit doesn't degenerate to 1). Is this any more complicated? If not, do we really need this inside the language? This stuff was solved on the application level like a gazillion times.I think that's the right idea. I just think Gilad believes solving it at the application level will be inelegant, but I don't speak for him so don't hold me to that.
Suppose you have a bunch of objects, and they want to interconnect - just by finding each other.
And for testing, you want to wire them differently than for production. And for production, you want them wired differently in different deployments. And...
Config class KNOWS everything.
How do you think, is the idea of passing static context into runtime for the purposes of configuration patentable?