digitalmars.D - global vs context variable
- luka8088 (51/51) Dec 11 2013 Hi everyone!
- monarch_dodra (15/29) Dec 11 2013 "write" is really just a global helper/shortcut function that
- luka8088 (14/31) Dec 11 2013 Yes. That is exactly what this kind of approach is all about. In
- QAston (17/84) Dec 11 2013 This issue is probably nearly as old as programming itself.
- luka8088 (7/24) Dec 11 2013 I was thinking about such issues and think they are all solvable. I
- monarch_dodra (2/11) Dec 11 2013 I hate it when issues just keep pooping up. So rude!
- luka8088 (2/6) Dec 11 2013 Lol, popping xD
- Ary Borenszweig (2/8) Dec 11 2013 shit happens
- Shammah Chancellor (6/21) Dec 11 2013 What does this method have over just using:
- luka8088 (18/44) Dec 11 2013 It works with deep nesting without the need to pass the context as a
- Artur Skawina (24/43) Dec 11 2013 import std.stdio;
Hi everyone! I would like to address the issue of global variables (or states). In general my opinion is that they are bad solely because they (in most cases) lack the ability of alternative values (or states) or ability to alter them in user friendly way. For example, take write function from std.stdio. For a third party function that uses write to output to screen user is unable to redirect that output to, for example, file without altering third party function's body. Or if there is a way it rarely user friendly. For example, in php there are function for buffering output but you have to manually start buffering and manually stop it. In python active output is a global variable and you are able to replace it with a custom file stream but you are responsible maintain a custom stack in case of recursion and switching it back to default output when no longer needed. There are also examples of loggers, database connections, etc. I have a proposal to generalize this issue. Attached is a example library that implements context based approach and I would like to see this kind of library in phobos (std.context). It is very simple and yet in my experience it has shown to be very useful. Examples using such library: void writeOutput () { writeln("example output"); } void main () { writeOutput(); standardOutputContext(file("example.txt"), { writeOutput(); }); } MVC example: void databaseToView () { auto result = db.query("select;"); view.populate(result); } void myAction () { auto customView = new View(); viewContext(customView, { databaseToView(); }); view.regionA.append(customView); } void main () { dbContext(defaultDbConnection { viewContext(defaultView, { myAction(); }); }); } I would like to add this to phobos and document it but I would like to know if this is desirable at all and to get a community feedback. Thoughts?
Dec 11 2013
On Wednesday, 11 December 2013 at 08:21:33 UTC, luka8088 wrote:Hi everyone! I would like to address the issue of global variables (or states). In general my opinion is that they are bad solely because they (in most cases) lack the ability of alternative values (or states) or ability to alter them in user friendly way. For example, take write function from std.stdio. For a third party function that uses write to output to screen user is unable to redirect that output to, for example, file without altering third party function's body."write" is really just a global helper/shortcut function that calls "stdout.write". If the user wants to customize this, then it's really no more complicated than doing a write to a named stream, which represents the global out, which may or may not be stdout: auto myGlobalOut = stdout; myGlobalOut.write(); //Writes to console (technically, "standard output") //Change the global output context myGlobalOut = File("out.txt", "w"); myGlobalOut.write(); //Writes to file -------- I'm not really sure I understood the rest of what you posted though, so I can't make any comments on that.
Dec 11 2013
On 11.12.2013. 9:30, monarch_dodra wrote:"write" is really just a global helper/shortcut function that calls "stdout.write". If the user wants to customize this, then it's really no more complicated than doing a write to a named stream, which represents the global out, which may or may not be stdout: auto myGlobalOut = stdout; myGlobalOut.write(); //Writes to console (technically, "standard output") //Change the global output context myGlobalOut = File("out.txt", "w"); myGlobalOut.write(); //Writes to fileYes. That is exactly what this kind of approach is all about. In practice I found a need to temporarily change myGlobalOut while keeping in mind that recursion could be used and in most cases a stack was required. You also need to make sure that stack is pop'ed properly (even in case of throwing) so generally there is some work to be done. I think that this kind of approach would be much more user friendly if a library support was introduced.-------- I'm not really sure I understood the rest of what you posted though, so I can't make any comments on that.Take MVC for example. Most frameworks either support global variables or setting a controller properties for stuff that needs to be accessible globally. I have seen database connections being a property of a controller, which if you think about it makes no sense, but it was the most pragmatical way to do it in order to make database connection "globally" accessible without setting is as a global variable.
Dec 11 2013
On Wednesday, 11 December 2013 at 08:21:33 UTC, luka8088 wrote:Hi everyone! I would like to address the issue of global variables (or states). In general my opinion is that they are bad solely because they (in most cases) lack the ability of alternative values (or states) or ability to alter them in user friendly way. For example, take write function from std.stdio. For a third party function that uses write to output to screen user is unable to redirect that output to, for example, file without altering third party function's body. Or if there is a way it rarely user friendly. For example, in php there are function for buffering output but you have to manually start buffering and manually stop it. In python active output is a global variable and you are able to replace it with a custom file stream but you are responsible maintain a custom stack in case of recursion and switching it back to default output when no longer needed. There are also examples of loggers, database connections, etc. I have a proposal to generalize this issue. Attached is a example library that implements context based approach and I would like to see this kind of library in phobos (std.context). It is very simple and yet in my experience it has shown to be very useful. Examples using such library: void writeOutput () { writeln("example output"); } void main () { writeOutput(); standardOutputContext(file("example.txt"), { writeOutput(); }); } MVC example: void databaseToView () { auto result = db.query("select;"); view.populate(result); } void myAction () { auto customView = new View(); viewContext(customView, { databaseToView(); }); view.regionA.append(customView); } void main () { dbContext(defaultDbConnection { viewContext(defaultView, { myAction(); }); }); } I would like to add this to phobos and document it but I would like to know if this is desirable at all and to get a community feedback. Thoughts?This issue is probably nearly as old as programming itself. There are several sollutions already developed: dependency injection (requires complex configuration rules), manually passing deps as args (cumbersome), service locator or global variables. Your sollution as far as I understand it relies on swapping a global variable when inside a context and restoring it afterwards. While this would be perfectly fine in environment where code is executed in OS threads, there will be a problem in the case of Vibe.d which uses fibers. But I guess the problem is solvable there aswell. Just to note - you have to bind to globals at some point - what if someone wants to swap writeln function whith his own (for example to call logger, or for whatever reason)? Or he may want to swap dbContext :).In my practice I make swappable only things I think I'll need to swap in future.
Dec 11 2013
On 11.12.2013. 10:53, QAston wrote:This issue is probably nearly as old as programming itself. There are several sollutions already developed: dependency injection (requires complex configuration rules), manually passing deps as args (cumbersome), service locator or global variables.Yeah, and it always keeps pooping right up!Your sollution as far as I understand it relies on swapping a global variable when inside a context and restoring it afterwards. While this would be perfectly fine in environment where code is executed in OS threads, there will be a problem in the case of Vibe.d which uses fibers. But I guess the problem is solvable there aswell.I was thinking about such issues and think they are all solvable. I concluded that I should present this issues as simple and possible to check out the general interest first.Just to note - you have to bind to globals at some point - what if someone wants to swap writeln function whith his own (for example to call logger, or for whatever reason)? Or he may want to swap dbContext :).In my practice I make swappable only things I think I'll need to swap in future.Yes. Not only that swapping would need to permitted but also only same type values could be swapped. D makes sure of that.
Dec 11 2013
On Wednesday, 11 December 2013 at 12:58:54 UTC, luka8088 wrote:On 11.12.2013. 10:53, QAston wrote:I hate it when issues just keep pooping up. So rude!This issue is probably nearly as old as programming itself. There are several sollutions already developed: dependency injection (requires complex configuration rules), manually passing deps as args (cumbersome), service locator or global variables.Yeah, and it always keeps pooping right up!
Dec 11 2013
On 11.12.2013. 15:47, monarch_dodra wrote:On Wednesday, 11 December 2013 at 12:58:54 UTC, luka8088 wrote:Lol, popping xDYeah, and it always keeps pooping right up!I hate it when issues just keep pooping up. So rude!
Dec 11 2013
On 12/11/13 12:54 PM, luka8088 wrote:On 11.12.2013. 15:47, monarch_dodra wrote:shit happensOn Wednesday, 11 December 2013 at 12:58:54 UTC, luka8088 wrote:Lol, popping xDYeah, and it always keeps pooping right up!I hate it when issues just keep pooping up. So rude!
Dec 11 2013
On 2013-12-11 08:21:35 +0000, luka8088 said:Examples using such library: void writeOutput () { writeln("example output"); } void main () { writeOutput(); standardOutputContext(file("example.txt"), { writeOutput(); }); }What does this method have over just using: with(file("example.txt")) { writeln("Foo"); }
Dec 11 2013
On 11.12.2013. 12:14, Shammah Chancellor wrote:On 2013-12-11 08:21:35 +0000, luka8088 said:It works with deep nesting without the need to pass the context as a function argument: void writeOutput () { writeln("example output"); } void f2 () { writeOutput(); } void f1 () { f2(); } void main () { f1(); standardOutputContext(file("example.txt"), { f1(); }); }Examples using such library: void writeOutput () { writeln("example output"); } void main () { writeOutput(); standardOutputContext(file("example.txt"), { writeOutput(); }); }What does this method have over just using: with(file("example.txt")) { writeln("Foo"); }
Dec 11 2013
On 12/11/13 09:21, luka8088 wrote:Hi everyone! I would like to address the issue of global variables (or states). In general my opinion is that they are bad solely because they (in most cases) lack the ability of alternative values (or states) or ability to alter them in user friendly way. For example, take write function from std.stdio. For a third party[...]void writeOutput () { writeln("example output"); } void main () { writeOutput(); standardOutputContext(file("example.txt"), { writeOutput(); }); }import std.stdio; void writeOutput () { writeln("example output"); } void main () { writeOutput(); { auto ex = Push!stdout(File("example.txt", "w")); writeOutput(); } writeOutput(); } struct Push(alias A, T=typeof(A)) { T old; this(T a) { old = A; A = a; } ~this() { A = old; } } Last time I checked, 'with' was still broken (the object is destroyed too soon), but once that is fixed you should be able to do: with (Push!stdout(File("example.txt", "w"))) writeOutput(); artur
Dec 11 2013