digitalmars.D.announce - Scriptlike v0.9.4 - Perl-like interpolated strings, full examples
- Nick Sabalausky (63/63) Sep 22 2015 Big update to Scriptlike, v0.9.4:
- Sebastiaan Koppe (8/15) Sep 22 2015 What about:
- Adam D. Ruppe (4/8) Sep 22 2015 Won't work because it won't be able to see the local variables
- Sebastiaan Koppe (4/13) Sep 22 2015 facepalm... ofcourse...
- =?UTF-8?Q?S=c3=b6nke_Ludwig?= (19/36) Sep 22 2015 An alternative idea would be to mix in a local "writeln" function, which...
- Nick Sabalausky (15/33) Sep 23 2015 Hmm, interesting idea. I'd leave it as a string-returning function,
- Chad Joan (13/53) Sep 23 2015 This is why I argued for alternative mixin syntax in D some ...
- Nick Sabalausky (13/24) Sep 23 2015 Yea, the trouble with string mixins is that they're ugly enough people
- Chad Joan (40/76) Sep 23 2015 I hope not :(
- Meta (8/44) Sep 23 2015 What about even just removing the syntax distinction between
- Nick Sabalausky (4/8) Sep 25 2015 I like that idea. It it feasible? I'd always assumed the syntaxes were
- Meta (18/22) Sep 25 2015 At first glance I can't see any problem with it, other than the
- =?UTF-8?Q?S=c3=b6nke_Ludwig?= (21/31) Sep 25 2015 True, it's still far from being good. There is another possible syntax
- Andrei Alexandrescu (4/45) Sep 24 2015 Yah, I think we need something like that in the stdlib. Also, we need
- H. S. Teoh via Digitalmars-d-announce (40/43) Sep 24 2015 https://issues.dlang.org/show_bug.cgi?id=13568
- Jacob Carlborg (5/20) Sep 25 2015 Not sure why you need to complicate it with template constraints. Just
- H. S. Teoh via Digitalmars-d-announce (10/32) Sep 25 2015 [...]
- Jacob Carlborg (13/18) Sep 26 2015 1. "writefln" is already a template [1]:
- Jacob Carlborg (5/22) Sep 22 2015 Different bikeshedding: I would prefer to make the curly braces optional...
- Nick Sabalausky (4/6) Sep 23 2015 I agree. I've left that as a future enhancement for the right now.
- Jacob Carlborg (8/11) Sep 22 2015 One thing that really bugs me in Phobos, Scriptlike seems to have the
- Dmitry Olshansky (5/15) Sep 22 2015 Bugzilla issue with this enhancement would help a lot with this ;)
- Jacob Carlborg (5/7) Sep 23 2015 https://issues.dlang.org/show_bug.cgi?id=15102
- Ben Boeckel via Digitalmars-d-announce (5/10) Sep 23 2015 Be aware that you will have to pay an extra lstat call for such a
- Jacob Carlborg (6/9) Sep 23 2015 Perhaps not in Phobos, but I don't see why someone using Scriptlike
- Nick Sabalausky (9/19) Sep 23 2015 Me too. That's why this latest version adds removePath and
Big update to Scriptlike, v0.9.4: https://github.com/Abscissa/scriptlike Scriptlike is a library to help you write script-like programs in D. The two highlights in this release are string interpolation and a full set of examples in the documentation. Also of note are the new functions removePath and tryRemovePath which can be used to delete files (like remove) *or* directories (like rmdirRecurse). Full changelog: http://semitwist.com/scriptlike/changelog.html ===================== String Interpolation: ===================== https://github.com/Abscissa/scriptlike#string-interpolation AFAICT, a string mixin is necessary to accomplish this in D, but otherwise it works much like other languages: -------------------------------------------- // Output: The number 21 doubled is 42! int num = 21; writeln( mixin(interp!"The number ${num} doubled is ${num * 2}!") ); -------------------------------------------- The interpolated sections are handled via std.conv.text(), so they accept any type. Bikeshedding requested! I'm not 100% sold on the name "interp" for this long-term. Suggestions welcome. ========= Examples: ========= https://github.com/Abscissa/scriptlike https://github.com/Abscissa/scriptlike/blob/master/USAGE.md https://github.com/Abscissa/scriptlike/tree/master/examples The homepage/readme now provides sample code demonstrating all of Scriptlike's various features. The second link above demonstrates suggested practices for how to use Scriptlike in a D-based script. And finally, all examples are included as actual runnable programs (all automatically tested by "dub test", to ensure continued freshness). ====================== All changes in v0.9.4: ====================== - Fixed: Previous release broke the unittest script when dub test support was added. - Fixed: In echo mode, several functions would echo the wrong "try*" or non-"try*" version. Ex: run echoed tryRun, and tryRename echoed rename. - Fixed: Path and buildNormalizedPathFixed now convert back/forward slashes to native on BOTH Windows and Posix, not just on Windows. - Fixed: Some links within changelog and API reference were pointing to the reference docs for Scriptlike's latest version, instead of staying within the same documentation version. This made archived docs for previous versions difficult to navigate. - Enhancement: Add interp for interpolated strings: string s = mixin( interp!"Value is ${variableOrExpression}" ) - Enhancement: Add removePath/tryRemovePath for deleting a path regardless of whether it's a file or directory. (Calls remove for files and rmdirRecurse for directories.) - Enhancement: Add a Path-accepting overload of escapeShellArg for the sake of generic code. - Enhancement: When runCollect throws, the ErrorLevelException now includes and displays the command's output (otherwise there'd be no way to inspect the command's output for diagnostic purposes). - Enhancement: Greatly extended and improved set of tests.
Sep 22 2015
On Tuesday, 22 September 2015 at 20:18:48 UTC, Nick Sabalausky wrote:-------------------------------------------- // Output: The number 21 doubled is 42! int num = 21; writeln( mixin(interp!"The number ${num} doubled is ${num * 2}!") ); --------------------------------------------What about: void echo(T)() { writeln(mixin(interp!T)); } At least it saves some typing.
Sep 22 2015
On Wednesday, 23 September 2015 at 01:24:54 UTC, Sebastiaan Koppe wrote:What about: void echo(T)() { writeln(mixin(interp!T));Won't work because it won't be able to see the local variables you want to interpolate.
Sep 22 2015
On Wednesday, 23 September 2015 at 01:45:03 UTC, Adam D. Ruppe wrote:On Wednesday, 23 September 2015 at 01:24:54 UTC, Sebastiaan Koppe wrote:facepalm... ofcourse... Well, you could still get rid of the writeln.What about: void echo(T)() { writeln(mixin(interp!T));Won't work because it won't be able to see the local variables you want to interpolate.
Sep 22 2015
Am 22.09.2015 um 22:18 schrieb Nick Sabalausky:===================== String Interpolation: ===================== https://github.com/Abscissa/scriptlike#string-interpolation AFAICT, a string mixin is necessary to accomplish this in D, but otherwise it works much like other languages: -------------------------------------------- // Output: The number 21 doubled is 42! int num = 21; writeln( mixin(interp!"The number ${num} doubled is ${num * 2}!") ); -------------------------------------------- The interpolated sections are handled via std.conv.text(), so they accept any type. Bikeshedding requested! I'm not 100% sold on the name "interp" for this long-term. Suggestions welcome.An alternative idea would be to mix in a local "writeln" function, which can then be used multiple times without syntax overhead: mixin template interp() { void iwriteln(string str)() { // pretend that we actually parse the string ;) write("This is "); write(somevar); writeln("."); } } void main() { int somevar = 42; mixin interp; iwriteln!("This is ${somevar}."); }
Sep 22 2015
On 09/23/2015 01:44 AM, Sönke Ludwig wrote:An alternative idea would be to mix in a local "writeln" function, which can then be used multiple times without syntax overhead: mixin template interp() { void iwriteln(string str)() { // pretend that we actually parse the string ;) write("This is "); write(somevar); writeln("."); } } void main() { int somevar = 42; mixin interp; iwriteln!("This is ${somevar}."); }Hmm, interesting idea. I'd leave it as a string-returning function, rather than automatically printing, but a writeln convenience wrapper is a nice idea too. The one problem I'm seeing with it though, is it wouldn't be able to see symbols declared between the "mixin interp;" and any later uses of it. Ie: void main() { int somevar = 42; mixin interp; iwriteln!("This is ${somevar}."); int another = 17; iwriteln!("This won't work, using ${another}."); } Seems like it would be too awkward and confusing to be worthwhile. :(
Sep 23 2015
On Wednesday, 23 September 2015 at 14:33:23 UTC, Nick Sabalausky wrote:On 09/23/2015 01:44 AM, Sönke Ludwig wrote:This is why I argued for alternative mixin syntax in D some ... years? ... ago. It'd be really cool to have a writefln overload that did this: int somevar = 42; Which would just be shorthand for int somevar = 42; mixin writefln!("This is ${somevar}"); mixin writefln!("Plus two and you get ${somevar+2}"); I feel like a bit of syntax sugar could go a long way ;)An alternative idea would be to mix in a local "writeln" function, which can then be used multiple times without syntax overhead: mixin template interp() { void iwriteln(string str)() { // pretend that we actually parse the string ;) write("This is "); write(somevar); writeln("."); } } void main() { int somevar = 42; mixin interp; iwriteln!("This is ${somevar}."); }Hmm, interesting idea. I'd leave it as a string-returning function, rather than automatically printing, but a writeln convenience wrapper is a nice idea too. The one problem I'm seeing with it though, is it wouldn't be able to see symbols declared between the "mixin interp;" and any later uses of it. Ie: void main() { int somevar = 42; mixin interp; iwriteln!("This is ${somevar}."); int another = 17; iwriteln!("This won't work, using ${another}."); } Seems like it would be too awkward and confusing to be worthwhile. :(
Sep 23 2015
On 09/23/2015 03:18 PM, Chad Joan wrote:This is why I argued for alternative mixin syntax in D some ... years? ... ago. It'd be really cool to have a writefln overload that did this: int somevar = 42; Which would just be shorthand for int somevar = 42; mixin writefln!("This is ${somevar}"); mixin writefln!("Plus two and you get ${somevar+2}"); I feel like a bit of syntax sugar could go a long way ;)Yea, the trouble with string mixins is that they're ugly enough people don't like to use them. I'd argued in the past for a way to tag a CTFE-able string-returning function as being intended for mixing-in, so you could omit the "mixin(...)" part. But we only ever got it for template mixins. Allowing it for string mixins was too controversial. :( I dunno, maybe even a string mixin sugar as simple as this would be a big help: mixin!func(args to func here) ie: mixin!interp("Some string here") But I'm guessing the ship's ling since sailed for anything like that.
Sep 23 2015
On Wednesday, 23 September 2015 at 19:28:03 UTC, Nick Sabalausky wrote:On 09/23/2015 03:18 PM, Chad Joan wrote:I hope not :( I remember when Walter originally designed mixins, he stated something to the effect that he wanted them to be easily greppable at all times. I would argue that they are so centrally important that they should be a symbol rather than a keyword. Still greppable. But also much more useful. Since D already has the mixin keyword, I suspect it would be more practical to just ask people to grep for 'mixin|<mixin symbol>' instead of just 'mixin'. There are similar (but orthogonal) concerns with delegate (anonymous function) nesting: // D notation. foo ( (x,y) { auto z = doSomething(x+y); return z*z; }); vs // Speculative notation. foo() : (x,y) { auto z = doSomething(x+y); return z*z; } Current D notation for nesting functions reminds me of C's notation for structs... // C notation. typedef struct WhatDoIPutHereFoo { int x,y; } Foo; // D notation. (Yay, consistency!) struct Foo { int x,y; } Extra semicolon and syntax noise and such. I'm still incredibly glad D even has delegates and mixins at this point ;)This is why I argued for alternative mixin syntax in D some ... years? ... ago. It'd be really cool to have a writefln overload that did this: int somevar = 42; Which would just be shorthand for int somevar = 42; mixin writefln!("This is ${somevar}"); mixin writefln!("Plus two and you get ${somevar+2}"); I feel like a bit of syntax sugar could go a long way ;)Yea, the trouble with string mixins is that they're ugly enough people don't like to use them. I'd argued in the past for a way to tag a CTFE-able string-returning function as being intended for mixing-in, so you could omit the "mixin(...)" part. But we only ever got it for template mixins. Allowing it for string mixins was too controversial. :( I dunno, maybe even a string mixin sugar as simple as this would be a big help: mixin!func(args to func here) ie: mixin!interp("Some string here") But I'm guessing the ship's ling since sailed for anything like that.
Sep 23 2015
On Wednesday, 23 September 2015 at 19:28:03 UTC, Nick Sabalausky wrote:On 09/23/2015 03:18 PM, Chad Joan wrote:What about even just removing the syntax distinction between string mixins and template mixins? mixin "int i = 0"; mixin declareI!(); While we're at it, how about optional parens for templates as well as functions?This is why I argued for alternative mixin syntax in D some ... years? ... ago. It'd be really cool to have a writefln overload that did this: int somevar = 42; Which would just be shorthand for int somevar = 42; mixin writefln!("This is ${somevar}"); mixin writefln!("Plus two and you get ${somevar+2}"); I feel like a bit of syntax sugar could go a long way ;)Yea, the trouble with string mixins is that they're ugly enough people don't like to use them. I'd argued in the past for a way to tag a CTFE-able string-returning function as being intended for mixing-in, so you could omit the "mixin(...)" part. But we only ever got it for template mixins. Allowing it for string mixins was too controversial. :( I dunno, maybe even a string mixin sugar as simple as this would be a big help: mixin!func(args to func here) ie: mixin!interp("Some string here") But I'm guessing the ship's ling since sailed for anything like that.
Sep 23 2015
On 09/23/2015 08:42 PM, Meta wrote:What about even just removing the syntax distinction between string mixins and template mixins? mixin "int i = 0"; mixin declareI!();I like that idea. It it feasible? I'd always assumed the syntaxes were different because they needed to be for some sort of technical reason. But now that I look at it...maybe that could work after all?
Sep 25 2015
On Friday, 25 September 2015 at 14:38:33 UTC, Nick Sabalausky wrote:I like that idea. It it feasible? I'd always assumed the syntaxes were different because they needed to be for some sort of technical reason. But now that I look at it...maybe that could work after all?At first glance I can't see any problem with it, other than the fact that it makes it somewhat ambiguous whether you're mixing in a string returned from a CTFE function or a template mixin in some cases. mixin template mixable() { int i = 0; } string mixable()() { return "int i = 0;"; } However, this currently causes a compile time error anyway, so I don't believe it's a problem. //Error, two templates with the same name mixin mixable!();
Sep 25 2015
Am 23.09.2015 um 16:33 schrieb Nick Sabalausky:(...) void main() { int somevar = 42; mixin interp; iwriteln!("This is ${somevar}."); int another = 17; iwriteln!("This won't work, using ${another}."); } Seems like it would be too awkward and confusing to be worthwhile. :(True, it's still far from being good. There is another possible syntax variation: mixin template iwriteln(string str, int line = __LINE__) { auto __dummy_/*~line*/ = () { import std.stdio; // pretend to parse the input string write("Result: "); write(result); writeln(); return true; } (); } void main() { int result = 42; } Works only for top-level calls, but has less visual noise, so maybe it makes sense to include that as a convenience function.
Sep 25 2015
On 09/23/2015 01:44 AM, Sönke Ludwig wrote:Am 22.09.2015 um 22:18 schrieb Nick Sabalausky:Yah, I think we need something like that in the stdlib. Also, we need writefln with compile-time format string (someone was working on it but I haven't heard about it in a while). -- Andrei===================== String Interpolation: ===================== https://github.com/Abscissa/scriptlike#string-interpolation AFAICT, a string mixin is necessary to accomplish this in D, but otherwise it works much like other languages: -------------------------------------------- // Output: The number 21 doubled is 42! int num = 21; writeln( mixin(interp!"The number ${num} doubled is ${num * 2}!") ); -------------------------------------------- The interpolated sections are handled via std.conv.text(), so they accept any type. Bikeshedding requested! I'm not 100% sold on the name "interp" for this long-term. Suggestions welcome.An alternative idea would be to mix in a local "writeln" function, which can then be used multiple times without syntax overhead: mixin template interp() { void iwriteln(string str)() { // pretend that we actually parse the string ;) write("This is "); write(somevar); writeln("."); } } void main() { int somevar = 42; mixin interp; iwriteln!("This is ${somevar}."); }
Sep 24 2015
On Thu, Sep 24, 2015 at 08:00:53PM -0400, Andrei Alexandrescu via Digitalmars-d-announce wrote: [...]Yah, I think we need something like that in the stdlib. Also, we need writefln with compile-time format string (someone was working on it but I haven't heard about it in a while). -- Andreihttps://issues.dlang.org/show_bug.cgi?id=13568 I wanted to work on it, but haven't actually gotten to it yet. Basically, the idea is relatively simple: // compile-time variant void writefln(string format="", A...)(A args) if (format.length > 0) { ... // implementation here } // runtime variant void writefln(string format="", A...)(A args) if (format.length == 0 && args.length > 0 && is(typeof(args[0]) == string)) { ... // current implementation } This will allow backward compatibility with the current writefln API, while allowing existing code to simply transition from: writefln("...", ...); to: writefln!"..."(...); The tricky part is how to extricate the various parts of the current implementation in order to take full advantage of compile-time format strings, e.g., (1) don't import anything except what's necessary to format the current format string (the current format() has to import, e.g., std.bigint even if you never use BigInt, because it can't assume that a runtime format string might not ask to format BigInts; this causes the infamous format() template bloat) -- this includes allowing format() to be pure, nogc, etc. if your format strings never ask for anything that requires that; (2) compile-time argument mismatch checking (e.g., writefln!"%d"("abc") should give a compile-time error rather than a runtime exception). A lot of the current implementation will probably have to be overhauled / rewritten in order to make this work. That part unfortunately requires a lot of time, which I don't have right now. T -- Creativity is not an excuse for sloppiness.
Sep 24 2015
On 2015-09-25 02:15, H. S. Teoh via Digitalmars-d-announce wrote:I wanted to work on it, but haven't actually gotten to it yet. Basically, the idea is relatively simple: // compile-time variant void writefln(string format="", A...)(A args) if (format.length > 0) { ... // implementation here } // runtime variant void writefln(string format="", A...)(A args) if (format.length == 0 && args.length > 0 && is(typeof(args[0]) == string)) { ... // current implementation }Not sure why you need to complicate it with template constraints. Just overload the function? -- /Jacob Carlborg
Sep 25 2015
On Fri, Sep 25, 2015 at 02:14:30PM +0200, Jacob Carlborg via Digitalmars-d-announce wrote:On 2015-09-25 02:15, H. S. Teoh via Digitalmars-d-announce wrote:[...] It's to work around a dmd bug that doesn't allow overloads between templates and non-templates. But I just checked, looks like that bug may have been fixed since, so now the following overloads would work: void writefln(string format, A...)(A args) { ... } // current void writefln(A...)(string format, A args) { ... } // new T -- Don't drink and derive. Alcohol and algebra don't mix.I wanted to work on it, but haven't actually gotten to it yet. Basically, the idea is relatively simple: // compile-time variant void writefln(string format="", A...)(A args) if (format.length > 0) { ... // implementation here } // runtime variant void writefln(string format="", A...)(A args) if (format.length == 0 && args.length > 0 && is(typeof(args[0]) == string)) { ... // current implementation }Not sure why you need to complicate it with template constraints. Just overload the function?
Sep 25 2015
On 2015-09-25 23:28, H. S. Teoh via Digitalmars-d-announce wrote:It's to work around a dmd bug that doesn't allow overloads between templates and non-templates. But I just checked, looks like that bug may have been fixed since, so now the following overloads would work: void writefln(string format, A...)(A args) { ... } // current void writefln(A...)(string format, A args) { ... } // new1. "writefln" is already a template [1]: void writefln(Char, A...)(in Char[] fmt, A args) 2. Both of your above examples are templates 3. The easiest way to workaround that bug is to make the non-template function a template function without arguments: void foo()(int a); void foo(T)(T a, T b); But if the bug is fixed, then that's great :) [1] https://github.com/D-Programming-Language/phobos/blob/master/std/stdio.d#L1362 -- /Jacob Carlborg
Sep 26 2015
On 2015-09-22 22:18, Nick Sabalausky wrote:===================== String Interpolation: ===================== https://github.com/Abscissa/scriptlike#string-interpolation AFAICT, a string mixin is necessary to accomplish this in D, but otherwise it works much like other languages: -------------------------------------------- // Output: The number 21 doubled is 42! int num = 21; writeln( mixin(interp!"The number ${num} doubled is ${num * 2}!") ); -------------------------------------------- The interpolated sections are handled via std.conv.text(), so they accept any type. Bikeshedding requested! I'm not 100% sold on the name "interp" for this long-term. Suggestions welcome.Different bikeshedding: I would prefer to make the curly braces optional if it only contains a symbol. -- /Jacob Carlborg
Sep 22 2015
On 09/23/2015 02:21 AM, Jacob Carlborg wrote:Different bikeshedding: I would prefer to make the curly braces optional if it only contains a symbol.I agree. I've left that as a future enhancement for the right now. Although it shouldn't be too difficult a change. Filing it here: https://github.com/Abscissa/scriptlike/issues/23
Sep 23 2015
On 2015-09-22 22:18, Nick Sabalausky wrote:Big update to Scriptlike, v0.9.4: https://github.com/Abscissa/scriptlike Scriptlike is a library to help you write script-like programs in D.One thing that really bugs me in Phobos, Scriptlike seems to have the same problem, is that there are three (!!!) different functions to remove something from the file system. Give me just one function that removes everything, regardless if it's a file, directory and if it's empty or not. -- /Jacob Carlborg
Sep 22 2015
On 23-Sep-2015 09:30, Jacob Carlborg wrote:On 2015-09-22 22:18, Nick Sabalausky wrote:Bugzilla issue with this enhancement would help a lot with this ;) And a PR would make it happen... -- Dmitry OlshanskyBig update to Scriptlike, v0.9.4: https://github.com/Abscissa/scriptlike Scriptlike is a library to help you write script-like programs in D.One thing that really bugs me in Phobos, Scriptlike seems to have the same problem, is that there are three (!!!) different functions to remove something from the file system. Give me just one function that removes everything, regardless if it's a file, directory and if it's empty or not.
Sep 22 2015
On 2015-09-23 08:32, Dmitry Olshansky wrote:Bugzilla issue with this enhancement would help a lot with this ;) And a PR would make it happen...https://issues.dlang.org/show_bug.cgi?id=15102 I'm too lazy for a PR. -- /Jacob Carlborg
Sep 23 2015
On Wed, Sep 23, 2015 at 08:30:18 +0200, Jacob Carlborg via Digitalmars-d-announce wrote:One thing that really bugs me in Phobos, Scriptlike seems to have the same problem, is that there are three (!!!) different functions to remove something from the file system. Give me just one function that removes everything, regardless if it's a file, directory and if it's empty or not.Be aware that you will have to pay an extra lstat call for such a function so that *it* can call the right function. It certainly shouldn't replace the existing functions. --Ben
Sep 23 2015
On 2015-09-23 15:59, Ben Boeckel via Digitalmars-d-announce wrote:Be aware that you will have to pay an extra lstat call for such a function so that *it* can call the right function. It certainly shouldn't replace the existing functions.Perhaps not in Phobos, but I don't see why someone using Scriptlike would care. As I understand it, the whole point of Scriptlike is convenience. -- /Jacob Carlborg
Sep 23 2015
On 09/23/2015 02:30 AM, Jacob Carlborg wrote:On 2015-09-22 22:18, Nick Sabalausky wrote:Me too. That's why this latest version adds removePath and tryRemovePath, which do exactly that ;) http://semitwist.com/scriptlike-docs/v0.9.4/scriptlike/file/extras/removePath.html http://semitwist.com/scriptlike-docs/v0.9.4/scriptlike/file/extras/tryRemovePath.html (Pardon the excess paragraph breaks on those pages. *cough* https://github.com/D-Programming-Language/dmd/pull/4745 *cough*) Of course, that does mean two *more* functions, but at least they're the only ones you need. :)Big update to Scriptlike, v0.9.4: https://github.com/Abscissa/scriptlike Scriptlike is a library to help you write script-like programs in D.One thing that really bugs me in Phobos, Scriptlike seems to have the same problem, is that there are three (!!!) different functions to remove something from the file system. Give me just one function that removes everything, regardless if it's a file, directory and if it's empty or not.
Sep 23 2015