Re: Best practices of using const
It feels disingenous to want to call a caching object even "logically" const. There has to be a scaffolding-based but hopefully generic compromise. I haven't yet tested this belief, but I believe "physical" const is of good use wherever it can be applied. On Friday, 21 June 2019 at 23:39:20 UTC, H. S. Teoh wrote: The problem with this is that you cannot use const(Wrapper). In particular, if you have a function that wants to document that it does not mutate its argument, you cannot write: auto func(in Wrapper data) { ... } because const(Wrapper) does not allow lazy initialization. ... IMHO, in parameters are a more important scenario than const in ranges (of course, same constraints). Just for the heck of it, I'll try to get a snippet "working" but I see out parameters snaking all through the call chain!
Re: There is a computer languages benchmark compare site, but no Dlang benchmark. I think they should support D.
On Saturday, 22 June 2019 at 01:27:31 UTC, lili wrote: A nick site, has a lot of languages, unfortunately no dlang in there. https://benchmarksgame-team.pages.debian.net/benchmarksgame/ This page frequently pops up in this forum, please refer to existing posts: https://forum.dlang.org/search?q=benchmarksgame&scope=forum In particular the last thread: https://forum.dlang.org/post/rcrhjgnskiuzzhrnz...@forum.dlang.org TL;DR: not happening.
There is a computer languages benchmark compare site, but no Dlang benchmark. I think they should support D.
A nick site, has a lot of languages, unfortunately no dlang in there. https://benchmarksgame-team.pages.debian.net/benchmarksgame/
Re: Best practices of using const
On Fri, Jun 21, 2019 at 06:32:33PM +, Yatheendra via Digitalmars-d-learn wrote: [...] >struct CostlyComputeResult { > ... // data fields > // constructor takes compute results, no postblit >} > >struct Wrapper { > const (CostlyComputeResult) *cachee = 0; > ... // data fields storing compute inputs > // constructor takes compute inputs > // pointer to function(compute inputs) > const ref get() { > if (!cachee) { > cachee = new(function(inputs)); > } > return cachee; > } >} > > Hopefully jumping through these hoops is worth the while. Instead, > maybe just wait until the compiler grows a 'cache pure' function > qualifier (move constructor required?). The problem with this is that you cannot use const(Wrapper). In particular, if you have a function that wants to document that it does not mutate its argument, you cannot write: auto func(in Wrapper data) { ... } because const(Wrapper) does not allow lazy initialization. Basically you have to resort to convention (e.g., name it ReadOnly or something similar) rather than actually mark it const. This generally isn't a big problem if you're using func in isolation, but as soon as you need to compose func with other const code, you quickly find yourself in a gordian knot of const incompatibilities that percolate throughout the entire call chain, because D's const is transitive. I.e., you want func to interact with other functions that trade in const data, but you cannot because of the constant(!) need to keep Wrapper mutable. The non-constness of Wrapper will then percolate up the call chain, "tainting" all functions that call it so that they cannot be marked const, even though *logically* they are const. This mix is already bad enough (try it on a non-trivial codebase sometime and see for yourself), but once you add generic functions to the mix, the whole thing simply becomes unusable -- because generic functions expect to write const types as const(T), but that will break if T is Wrapper. OK, so you can try to make it mutable as a workaround. But then that breaks const-ness attribute inference so the generic function becomes non-const, which in turn recursively causes its callers to be non-const, etc. Somewhere at the top of the call chain you'll have a const method that wants to call a const function, passing some higher-level data structure that eventually contains Wrapper somewhere deep down -- and it simply doesn't work without making the *entire* structure mutable, due to the infectiousness of const. So as soon as you use Wrapper in any data structure of arbitrary complexity, the entire thing must be mutable -- otherwise const percolates all the way down to Wrapper and the caching doesn't work anymore. tl;dr: using a wrapper works fine for relatively simple cases. But as soon as you add any meaningful complexity to it, the scheme quickly becomes either impractically convoluted, or outright impossible to use without a hard cast to cast away const (thereby invoking the lovely UB). T -- INTEL = Only half of "intelligence".
Re: Options for unit testing in D?
On Friday, 21 June 2019 at 17:52:43 UTC, Mike Wey wrote: On 21-06-2019 06:08, Mike Brockus wrote: [...] If you are using the D unittests in your source you can recompile the same source with `d_unittest: true`, the appstream-generator project does this: https://github.com/ximion/appstream-generator/blob/master/src/asgen/meson.build#L108 Or you can keep the tests separate and compile these test separately like you are doing in your C project. I use this option in the GlibD project: https://github.com/gtkd-developers/GlibD/blob/master/tests/gobject/meson.build So to use D 'unittest' I am required to include the main.d module file in the tester executable?
Re: What is iota function full name
On Friday, June 21, 2019 3:31:46 PM MDT KnightMare via Digitalmars-d-learn wrote: > On Friday, 21 June 2019 at 19:18:02 UTC, KnightMare wrote: > > On Friday, 21 June 2019 at 12:02:10 UTC, Jonathan M Davis wrote: > > > > auto goodName( ... ) { > > > > pragma( inline, true ) > > return terribleName( ... ); > > > > } > > hmm.. I have a question: this pragma will inline terribleName > (double code) or goodName (fine)? pragma(inline, true) goes on function declarations, not on function calls. So, you would need to put it on goodName's signature, in which case, it's goodName which would be inlined. There is no way for a caller to force a function to be inlined. - Jonathan M Davis
Re: What is iota function full name
On Friday, 21 June 2019 at 19:18:02 UTC, KnightMare wrote: On Friday, 21 June 2019 at 12:02:10 UTC, Jonathan M Davis wrote: auto goodName( ... ) { pragma( inline, true ) return terribleName( ... ); } hmm.. I have a question: this pragma will inline terribleName (double code) or goodName (fine)?
Re: Transform a function's body into a string for mixing in
On Friday, 21 June 2019 at 15:54:35 UTC, Adam D. Ruppe wrote: On Friday, 21 June 2019 at 15:42:56 UTC, Emmanuelle wrote: [...] This sounds very similar to something I hacked together a while ago and recently wrote about making cleaner code: https://forum.dlang.org/post/ekbyseslunvmudkhl...@forum.dlang.org The idea here was to do a pass-by-value lambda. Usage: --- auto bar(T)(T x) @nogc { return x(10); } auto foo(int x) @nogc { auto f = lambda!(x, q{ (int y) { return x + y; } }); return f; } void main() { import std.stdio; writeln(foo(15)(10)); } --- Magic implementation: --- template lambda(Args...) { static struct anon { static foreach(i; 0 .. Args.length - 1) mixin("typeof(Args[i]) " ~ __traits(identifier, Args[i]) ~ ";"); auto opCall(T...)(T t) { return mixin(Args[$-1])(t); } this(T...)(T t) { this.tupleof = t; } } anon lambda() { anon a; // copy the values in a.tupleof = Args[0 .. $-1]; return a; } } --- You could convert that into a regular delegate too, so it works with non-template consumers, by generating a non-templated opCall and taking its address. Oh wow, that's pretty awesome. Too bad it seems the token string around the lambda is unavoidable, but it's not a big deal I think. In any case thanks, you snippet helped me figure out the template I wanted without overuse of strings!
Re: Order of interfaces
On Friday, 21 June 2019 at 20:50:02 UTC, user1234 wrote: On Friday, 21 June 2019 at 20:42:00 UTC, Tomas wrote: Does it matter in which order a class inherits from interfaces? class A : Interface1, Interface2{ ... } vs class A : Interface2, Interface1{ ... } Conceptually it should not matter, but I'm getting really weird segfault errors with one version and no errors with the other version. compiler segfault or segfault when the program runs ? I still do not know what I'm doing wrong, but does anyone have an idea why the order might matter? I'm getting segfault when running the program.
Re: Order of interfaces
On Friday, 21 June 2019 at 20:42:00 UTC, Tomas wrote: Does it matter in which order a class inherits from interfaces? class A : Interface1, Interface2{ ... } vs class A : Interface2, Interface1{ ... } Conceptually it should not matter, but I'm getting really weird segfault errors with one version and no errors with the other version. compiler segfault or segfault when the program runs ? I still do not know what I'm doing wrong, but does anyone have an idea why the order might matter?
Re: What is iota function full name
On Friday, 21 June 2019 at 19:18:02 UTC, KnightMare wrote: On Friday, 21 June 2019 at 12:02:10 UTC, Jonathan M Davis wrote: On Friday, June 21, 2019 5:10:03 AM MDT JN via Some folks argued a while back that iota was a terrible name and that it should be changed, but it was decided not to change it. auto terribleName( ... ) { } auto goodName( ... ) { pragma( inline, true ) return terribleName( ... ); } everyone is happy Good tip. I usually make a file for these kind of aliases and simple functions that do not end up in the standard library, eg std.algorithm oneliners.
Order of interfaces
Does it matter in which order a class inherits from interfaces? class A : Interface1, Interface2{ ... } vs class A : Interface2, Interface1{ ... } Conceptually it should not matter, but I'm getting really weird segfault errors with one version and no errors with the other version. I still do not know what I'm doing wrong, but does anyone have an idea why the order might matter?
Re: What is iota function full name
On Friday, 21 June 2019 at 12:02:10 UTC, Jonathan M Davis wrote: On Friday, June 21, 2019 5:10:03 AM MDT JN via Some folks argued a while back that iota was a terrible name and that it should be changed, but it was decided not to change it. auto terribleName( ... ) { } auto goodName( ... ) { pragma( inline, true ) return terribleName( ... ); } everyone is happy
Re: Best practices of using const
That is a comprehensive reply. No pointers to other material required :-) On Friday, 21 June 2019 at 16:35:50 UTC, H. S. Teoh wrote: On Fri, Jun 21, 2019 at 06:07:59AM +, Yatheendra via Digitalmars-d-learn wrote: Actually, optimizers work best when there is minimal mutation *in the original source*. The emitted code, of course, is free to use mutation however it wants. But the trouble with mutation at the source level is that it makes many code analyses very complex, which hinders the optimizer from doing what it might have been able to do in the absence of mutation (or a reduced usage of mutation). [...] (aside: I hope we don't end up advocating the Haskell/Erlang way or the Clojure way!) Yes, the hindrances of non-const code are documented (are most programmers listening!). I was only pointing out that mutation being part of the design limits what can be logically const. Is the trade-off clear, between (mythical) guaranteed C++-like-const at all the points we remember to put it, versus guaranteed D-const at the fewer points we manage to put it? Does D-const distort the design (but you get all the optimizations possible in that scenario)? The inability to have a const caching object seems correct. The way around would be to have a wrapper that caches (meh). If that is not possible, then maybe caching objects just aren't meant to be const by their nature? Isn't memoize a standard library feature? I should look at it, but I wouldn't expect it to be const. It's not as simple as it might seem. Here's the crux of the problem: you have an object that logically never changes (assuming no bugs, of course). Meaning every time you read it, you get the same value, and so multiple reads can be elided, etc.. I.e., you want to tell the compiler that it's OK to assume this object is const (or immutable). However, it is expensive to initialize, and you'd like it to be initialized only when it's actually needed, and once initialized you'd like it to be cached so that you don't have to incur the initialization cost again. However, declaring a const object in D requires initialization, and after initialization it cannot be mutated anymore. This means you cannot declare it const in the first place if you want caching. It gets worse, though. Wrappers only work up to a certain point. But when you're dealing with generic code, it becomes problematic. Assume, for instance, that you have a type Costly that's logically const, but lazily initialized (and cached). Since you can't actually declare it const -- otherwise lazy initialization doesn't work -- you have to declare it mutable. Or, in this case, declare a wrapper that holds a const reference to it, say something like this: struct Payload { // lazily-initialized data } struct Wrapper { const(Payload)* impl; ... } However, what if you're applying some generic algorithms to it? Generic code generally assume that given a type T, if you want to declare a const instance of it, you simply write const(T). But what do you pass to the generic function? If you pass Wrapper, const(Wrapper) means `impl` cannot be rebound, so lazily initialization fails. OK, then let's pass const(Payload) directly. But that means you no longer have a wrapper, so you can't have lazy initialization (Payload must be constructed before you can pass it to the function, thus it must be eagerly initialized at this point). I should check on std memoize & maybe code something up for understanding before writing more than this - would you mind pointing to an example range algorithm that we would have trouble passing a caching wrapper to? I hadn't considered pointers as an option. Why wouldn't the following work, if expressible in D? struct CostlyComputeResult { ... // data fields // constructor takes compute results, no postblit } struct Wrapper { const (CostlyComputeResult) *cachee = 0; ... // data fields storing compute inputs // constructor takes compute inputs // pointer to function(compute inputs) const ref get() { if (!cachee) { cachee = new(function(inputs)); } return cachee; } } Hopefully jumping through these hoops is worth the while. Instead, maybe just wait until the compiler grows a 'cache pure' function qualifier (move constructor required?).
Re: Options for unit testing in D?
On 21-06-2019 06:08, Mike Brockus wrote: If you never herd about Meson before: 🤔. https://mesonbuild.com/ I am wondering as to what options are available for a Meson build user when unit testing? What I am trying todo is simply rewrite my C17 project reference templates to D versions so I may show other developers the basic structure of my project if I have a question about something or to influence the idea of Meson with D projects. Excuse the Conan file. As reference: C17 https://github.com/squidfarts/c-example.git https://github.com/squidfarts/c-project.git Dlang https://github.com/squidfarts/d-example.git If you are using the D unittests in your source you can recompile the same source with `d_unittest: true`, the appstream-generator project does this: https://github.com/ximion/appstream-generator/blob/master/src/asgen/meson.build#L108 Or you can keep the tests separate and compile these test separately like you are doing in your C project. I use this option in the GlibD project: https://github.com/gtkd-developers/GlibD/blob/master/tests/gobject/meson.build -- Mike Wey
Re: Best practices of using const
On Fri, Jun 21, 2019 at 06:07:59AM +, Yatheendra via Digitalmars-d-learn wrote: > Am I mistaken in saying that we are conflating: >"anything that is logically const should be declared const" No, not in D. D does not have logical const; it has "physical" const, which is a strict subset of logical const, and therefore there are some uses of logical const for which D's const is unsuitable. >// makes perfect sense >// e.g. the lowest 2, and some branches of the 3rd and 4th, levels >// of members (and a subset of the overall methods) in a 5-deep type > hierarchy are const > with: >"most code/data should be declared const" >// no! isn't efficient code all about mutation? >// no grounds for, e.g.: "ideally, no more than 40% of code should be > doing mutation" Actually, optimizers work best when there is minimal mutation *in the original source*. The emitted code, of course, is free to use mutation however it wants. But the trouble with mutation at the source level is that it makes many code analyses very complex, which hinders the optimizer from doing what it might have been able to do in the absence of mutation (or a reduced usage of mutation). Aliasing is one example that hampers optimizers from emitting optimal code. Aliasing plus mutation makes the analysis so complex that the optimizer has a hard time deciding whether a particular construct can be optimized away or not. Having minimal mutation in the original source code allows the optimizer to make more assumptions, which in turn leads to better optimizations. It also makes the source code easier to understand. Paradoxically, having less mutation in the source code means it's easier for the compiler to optimize it into mutation-heavy optimal code -- because it doesn't have to worry about arbitrary mutations in the source code, and therefore can be free(r) to, e.g., eliminate redundant copies, redundant movement of data, etc., which ultimately results in in-place modification of values, i.e., mutation-heavy emitted code. Conversely, if the source code is heavy on mutations, then the compiler cannot confidently predict the overall effect of the mutations, and therefore is forced to err on the safe side of assuming the worst, i.e., don't apply aggressive optimizations in case the programmer's mutations invalidate said optimizations. The result is less optimal code. [...] > The inability to have a const caching object seems correct. The way > around would be to have a wrapper that caches (meh). If that is not > possible, then maybe caching objects just aren't meant to be const by > their nature? Isn't memoize a standard library feature? I should look > at it, but I wouldn't expect it to be const. It's not as simple as it might seem. Here's the crux of the problem: you have an object that logically never changes (assuming no bugs, of course). Meaning every time you read it, you get the same value, and so multiple reads can be elided, etc.. I.e., you want to tell the compiler that it's OK to assume this object is const (or immutable). However, it is expensive to initialize, and you'd like it to be initialized only when it's actually needed, and once initialized you'd like it to be cached so that you don't have to incur the initialization cost again. However, declaring a const object in D requires initialization, and after initialization it cannot be mutated anymore. This means you cannot declare it const in the first place if you want caching. It gets worse, though. Wrappers only work up to a certain point. But when you're dealing with generic code, it becomes problematic. Assume, for instance, that you have a type Costly that's logically const, but lazily initialized (and cached). Since you can't actually declare it const -- otherwise lazy initialization doesn't work -- you have to declare it mutable. Or, in this case, declare a wrapper that holds a const reference to it, say something like this: struct Payload { // lazily-initialized data } struct Wrapper { const(Payload)* impl; ... } However, what if you're applying some generic algorithms to it? Generic code generally assume that given a type T, if you want to declare a const instance of it, you simply write const(T). But what do you pass to the generic function? If you pass Wrapper, const(Wrapper) means `impl` cannot be rebound, so lazily initialization fails. OK, then let's pass const(Payload) directly. But that means you no longer have a wrapper, so you can't have lazy initialization (Payload must be constructed before you can pass it to the function, thus it must be eagerly initialized at this point). It's an impasse. Cached / lazily-initialized objects and D's const simply don't mix. Well, you can try to mix them, but it's like trying to mix water and oil. They just don't work well together. T -- Notwithstanding the eloquent discontent that you have just
Re: Transform a function's body into a string for mixing in
On Friday, 21 June 2019 at 15:42:56 UTC, Emmanuelle wrote: Yeah, I want to be able to basically use mixin templates but with expressions instead, with the code being executed on the scope of the caller, not the callee; but it seems that's impossible without passing strings This sounds very similar to something I hacked together a while ago and recently wrote about making cleaner code: https://forum.dlang.org/post/ekbyseslunvmudkhl...@forum.dlang.org The idea here was to do a pass-by-value lambda. Usage: --- auto bar(T)(T x) @nogc { return x(10); } auto foo(int x) @nogc { auto f = lambda!(x, q{ (int y) { return x + y; } }); return f; } void main() { import std.stdio; writeln(foo(15)(10)); } --- Magic implementation: --- template lambda(Args...) { static struct anon { static foreach(i; 0 .. Args.length - 1) mixin("typeof(Args[i]) " ~ __traits(identifier, Args[i]) ~ ";"); auto opCall(T...)(T t) { return mixin(Args[$-1])(t); } this(T...)(T t) { this.tupleof = t; } } anon lambda() { anon a; // copy the values in a.tupleof = Args[0 .. $-1]; return a; } } --- You could convert that into a regular delegate too, so it works with non-template consumers, by generating a non-templated opCall and taking its address.
Re: Transform a function's body into a string for mixing in
On Thursday, 20 June 2019 at 20:38:48 UTC, Dennis wrote: On Thursday, 20 June 2019 at 19:09:11 UTC, Emmanuelle wrote: Is there any trait or Phobos function for transforming a function/delegate/lambda/whatever's body into a string suitable for `mixin(...)`? For example: See: https://forum.dlang.org/post/kozwskltzidfnatbp...@forum.dlang.org If not, is there any way to do this _without_ using strings? Depends on what you are trying to achieve with mixing in function body code. If you just want to execute the function code, you can just call it (obviously), so I assume you want dynamic scoping (that global variables are overridden by local variables from the caller) or something? Yeah, I want to be able to basically use mixin templates but with expressions instead, with the code being executed on the scope of the caller, not the callee; but it seems that's impossible without passing strings. For example, I recently hit an issue with closure scoping (https://forum.dlang.org/post/rnxebjcfpmyzptpwz...@forum.dlang.org) that can be worked around by using IIFEs; I thought, hey, maybe I could make a mixin that turns, say, this (taking the example from the post I just linked): --- ((x) => (int i) { nums[x] ~= i; })(x); --- into this: --- mixin(capture!(x, (int i) { nums[x] ~= i; }); --- where the variables I need captured go first there (in this case, only `x`). Of course, that doesn't work unless I use strings everywhere: --- mixin(capture!("x", q{(int i) { nums[x] ~= i; }}); --- which I find rather ugly and inconvenient. The technique you linked seems interesting but also loads of work so I'll just give up on this idea for now lol. Thanks though!
Trick for passing void* arrays around with typing
foo(cast(void*)[Object1, Object2]); foo(cast(bool delegate(void*))(Tuple!(X,Y) objects)) { }); One can pass arbitrary data as an array(the cast is ugly though) Then the tuple is cast back to void* but one can access objects correctly with typing. This works well when interacting with C/C++ void* data passing but can also work with passing heterogeneous objects in general. import std.stdio, std.typecons; class X { int x = 1; } class Y { int y = 2; } // a ** is required for the cast. void foo(void** data) { auto dd = cast(Tuple!(X,Y)*)(data); auto d = *dd; writeln(d[0].x); writeln(d[1].y); } // This would be a C callback that is hidden from us but the callback isn't. alias Q = void delegate(void*); void bar(Q d, void* x) { d(x); } void main() { X x = new X; Y y = new Y; foo(cast(void**)[x, y]); bar(cast(Q)(Tuple!(X,Y)* dd) { auto d = *dd; writeln("> ", d[0].x); writeln("> ", d[1].y); }, cast(void*)[x, y]); } What would be nice is if one didn't actually have to jump through all the hoops: void foo(void* as Tuple!(X,Y) d) // Redundant here but only because we have access to foo { writeln(d[0].x); writeln(d[1].y); } // This would be a C callback that is hidden from us but the callback isn't. alias Q = void delegate(void*); void bar(Q d, void* x) { d(x); } void main() { X x = new X; Y y = new Y; foo([x, y]); bar((as Tuple!(X,Y) d) { writeln("> ", d[0].x); writeln("> ", d[1].y); }, as [x, y]); } here I'm using as to signify a sort of implicit cast. The main thing to note is that for the callback, D gets the type as it is defined even though the cast changes the overall delegate to what it should be: bar(cast(Q)(Tuple!(X,Y)* dd) { auto d = *dd; writeln("> ", d[0].x); writeln("> ", d[1].y); }, cast(void*)[x, y]); } I don't actually use * in my code I think it is necessary to get the right values due to how they are passed. I think it has to do with register vs stack passing. So it might be fragile What I have is bar(cast(Q)(Tuple!(X,Y) d) { writeln("> ", d[0].x); writeln("> ", d[1].y); }, cast(void*)[x, y]); } which works, at least for x64. The cool thing is the "casting" all happens internally and so there is no direct need for casting. Obviously though there is no real casting going on(one could swap x and y in the argument) and so it is dangerous... but D could make it 100% type safe with the appropriate syntax. (only for delegates and callbacks) although maybe one could use it for normal functions too: foo([x,y] as Tuple!(X,Y)) e.g., normally we would have to do bar((dd) { auto d = cast(Tuple!(X,Y))dd; // Doesn't work though because tuple is not a reference, so must use the double pointer hacks. writeln("> ", d[0].x); writeln("> ", d[1].y); }, cast(void*)[x, y]); } When working with quite a number of C callbacks and passing data, this is a nice pattern to use to avoid the ugly temp variables and casting.
Why can't 'scope' be inferred here?
The following code fails to compile with -dip1000: struct Inner(T) { T value; this(ref T value) { this.value = value; } } struct Outer(T) { Inner!T inner; void opAssign(ref T rhs) { inner = Inner!T(rhs); } } @safe void main() { int x; int* p = &x; Outer!(int*) o; o = p; } (Interactive: https://run.dlang.io/is/yYTReh) Changing Inner's constructor to take a `scope ref T value` fixes the error. But since Inner is a template, and the body of the constructor is available to the compiler, shouldn't it be able to infer the `scope` attribute?
Re: Options for unit testing in D?
On Friday, 21 June 2019 at 04:08:42 UTC, Mike Brockus wrote: I am wondering as to what options are available for a Meson build user when unit testing? Unit tests are part of the language in D: https://dlang.org/spec/unittest.html These are compiled when you (or whatever build system you use) pass the argument -unittest to the compiler. If you never herd about Meson before: 🤔. https://mesonbuild.com/ D has an "official" build manager, called dub. Of course you're free to use another one you prefer. https://dub.pm/getting_started PS also embedded documentation is part of the language (no need for e.g. doxygen): https://dlang.org/spec/ddoc.html
Blog Post #0046 - SpinButton
Friday's post covers the SpinButton and its all-important Adjustment object companion. You can find it here: https://gtkdcoding.com/2019/06/21/0046-the-spinbutton.html Facelift Update Things are moving along nicely and I expect the fully-realized site to be unveiled within the next week.
Re: What is iota function full name
On Friday, 21 June 2019 at 09:24:54 UTC, lili wrote: in dictionary iota means: a tiny or scarcely detectable amount the 9th letter of the Greek alphabet but this function is not that mean. Full answer: https://stackoverflow.com/questions/9244879/what-does-iota-of-stdiota-stand-for
Re: What is iota function full name
On Friday, June 21, 2019 5:10:03 AM MDT JN via Digitalmars-d-learn wrote: > On Friday, 21 June 2019 at 09:18:49 UTC, Jonathan M Davis wrote: > So, iota is > > > the name of the function, and it doesn't stand for anything. > > It's just the name of the Greek letter that was used for a > > similar function in another language that most programmers > > these days have probably never heard of. > > > > - Jonathan M Davis > > I don't even understand why get so much inspiration from C++. Why > not just name it seq or sequence? Quite a lot of the functions in std.algorithm (especially the functions that it got early on) are modeled after similar functions in C++, standard library, and when Andrei wrote those functions, he purposefully made them use the same names as they have in C++. For anyone already familiar with those functions in C++ (including iota), having the same names makes sense. Other people are more likely to look at the names on their own merits, and as such, the names don't necessarily make as much sense (particularly iota). Regardless, given that Andrei was heavily involved in C++ long before he got involved with D, it's not exactly surprising that he'd use the C++ names rather than coming up with new ones - especially when std.algorithm was originally heavily modeled after C++'s algorithm header. Some folks argued a while back that iota was a terrible name and that it should be changed, but it was decided not to change it. However, truth be told, if you know what iota is, the name is more descriptive than a more generic name like sequence or generateRange would be. It's just a terrible name from the perspective that it's not at all decriptive of what it is. It's just a name that has historically been used for this particular operation. In practice, what tends to happen is that when someone first encounters iota, they think that it's a terrible name, but in the long run, they just know what it is, and it isn't actually a problem. Either way, at this point, names in Phobos don't get changed just because some folks think that a name isn't as good as it could be or should be, because changing would break code, and Walter and Andrei do not believe that simply giving something a better name is worth breaking anyone's code. - Jonathan M Davis
Re: What is iota function full name
On Friday, 21 June 2019 at 09:18:49 UTC, Jonathan M Davis wrote: So, iota is the name of the function, and it doesn't stand for anything. It's just the name of the Greek letter that was used for a similar function in another language that most programmers these days have probably never heard of. - Jonathan M Davis I don't even understand why get so much inspiration from C++. Why not just name it seq or sequence?
Re: What is iota function full name
So basically iota spills Increments Over The Array. Am 21.06.2019 um 11:18 schrieb Jonathan M Davis: On Friday, June 21, 2019 3:01:17 AM MDT lili via Digitalmars-d-learn wrote: Hi Guys: What is range.iota function full name iota _is_ its full name. It's named after an STL function which does basically the same with iterators in C++: https://en.cppreference.com/w/cpp/algorithm/iota Apparently, C++ got it from the APL programming language, which uses Greek characters and other symbols that you can't find on most keyboards, which makes APL code more like what you see in equations in a math textbook, and APL uses the Greek letter iota for a function with similar behavior to the C++ and D functions. And since unlike APL, C++ couldn't use the Greek letter, when they named their version of the function, they used the name of the letter rather than the letter. And then D's function name was named after the C++ function. So, iota is the name of the function, and it doesn't stand for anything. It's just the name of the Greek letter that was used for a similar function in another language that most programmers these days have probably never heard of. - Jonathan M Davis
Re: make C is scriptable like D
On Thursday, 20 June 2019 at 16:55:01 UTC, Jonathan Marler wrote: On Thursday, 20 June 2019 at 06:20:17 UTC, dangbinghoo wrote: [...] rdmd adds a few different features as well, but the bigger thing it does is cache the results in a global temporary directory. So If you run rdmd on the same file with the same options twice, the second time it won't compile anything, it will detect that it was already compiled and just run it. great! thanks.
Re: What is iota function full name
On Friday, 21 June 2019 at 09:09:33 UTC, aliak wrote: On Friday, 21 June 2019 at 09:01:17 UTC, lili wrote: Hi Guys: What is range.iota function full name That is the full name. Or what do you mean? Found on the internet somewhere: "The function is named after the integer function ⍳ from the programming language APL." 😄 I mean is that the what is iota stands for. in dictionary iota means: a tiny or scarcely detectable amount the 9th letter of the Greek alphabet but this function is not that mean.
Re: What is iota function full name
On Friday, June 21, 2019 3:01:17 AM MDT lili via Digitalmars-d-learn wrote: > Hi Guys: > What is range.iota function full name iota _is_ its full name. It's named after an STL function which does basically the same with iterators in C++: https://en.cppreference.com/w/cpp/algorithm/iota Apparently, C++ got it from the APL programming language, which uses Greek characters and other symbols that you can't find on most keyboards, which makes APL code more like what you see in equations in a math textbook, and APL uses the Greek letter iota for a function with similar behavior to the C++ and D functions. And since unlike APL, C++ couldn't use the Greek letter, when they named their version of the function, they used the name of the letter rather than the letter. And then D's function name was named after the C++ function. So, iota is the name of the function, and it doesn't stand for anything. It's just the name of the Greek letter that was used for a similar function in another language that most programmers these days have probably never heard of. - Jonathan M Davis
Re: What is iota function full name
On Friday, 21 June 2019 at 09:01:17 UTC, lili wrote: Hi Guys: What is range.iota function full name That is the full name. Or what do you mean? Found on the internet somewhere: "The function is named after the integer function ⍳ from the programming language APL."
What is iota function full name
Hi Guys: What is range.iota function full name