Re: 'auto' keyword
On 3/12/23 06:07, DLearner wrote: > 1. As a shorthand to make the type of the variable being declared the > same as the type on the right hand side of an initial assignment. As Adam explained, D already has type inference without a special keyword. However, some places where 'auto' (or 'const', etc.) appear is not only for "shorthand" but for necessity. Some types cannot be spelled-out at all: auto foo() { struct S {} return S(); } void main() { pragma(msg, typeof(foo())); auto s = foo(); } The name 'S' is available only inside 'foo', so code outside has no choice but to use 'auto' (or 'const', etc.) Having said that, it is still possible to alias the returned type, which may be cumbersome in some cases because you may have to come up with a clean expression for attempting to call the function. In this case it's trivial because foo does not take any parameter: alias T = typeof(foo()); T t;// <-- There: I did not need to use 'auto' Ali
Re: 'auto' keyword
On Sunday, 12 March 2023 at 13:27:05 UTC, Adam D Ruppe wrote: [...] *any* storage class will work for type inference. [...] After heaving read [1] I immediately thought of this: void main () { deprecated i = 3; i = 4; } $ dmd test.d test.d(4): Deprecation: variable `test.main.i` is deprecated Does that make sense??? [1] https://issues.dlang.org/show_bug.cgi?id=7432 Issue 7432 - DMD allows variables to be declared as pure
Re: 'auto' keyword
On Sunday, 12 March 2023 at 15:31:07 UTC, Salih Dincer wrote: Moreover, `auto ref` or `ref auto` is needed in functions. That's because `ref` isn't part of the argument or return value's type, so it isn't covered by **type** inference. Instead, D has a totally separate feature for "`ref` inference".
Re: 'auto' keyword
On Sunday, 12 March 2023 at 13:07:58 UTC, DLearner wrote: Is it correct that this _single_ keyword is used to indicate _two_ quite different things: 1. As a shorthand to make the type of the variable being declared the same as the type on the right hand side of an initial assignment. The auto keyword is really helpful for shortening it. But in at least 2 cases (one of which is interfaces) it should help the compiler. For example, contrary to expected, it is dynamic array: ```d auto arr = [ 1, 2, 3 ]; ``` Moreover, `auto ref` or `ref auto` is needed in functions. SDB@79
Re: 'auto' keyword
On Sunday, 12 March 2023 at 13:07:58 UTC, DLearner wrote: Is it correct that this _single_ keyword is used to indicate _two_ quite different things: No, it only actually does #2 in your thing. The type is optional meaning *any* storage class will work for type inference. `auto` is not special in variable declarations. (it can be special in other contexts though). auto A = 5; static A = 5; const A = 5; all the same.
Re: auto scope question?
typeof(screen.output.findSplit("")) s; Perfect. That was the "essence" of my question. But thanks to Ali, I don't have to use such esoteric syntax. D is a wonderful language, but I seem to shoot myself in the foot :)
Re: auto scope question?
On 10/25/22 6:07 PM, WhatMeWorry wrote: I'm naturally getting a undefined identifier `s` error in the return. Is there some way to refactor my code? I tried to declare s outside of the else brackets like: auto screen = executeShell(cmdLine); auto s; ... { s = screen.output.findSplit("REG_SZ"); } but that doesn't compile either. string[] getPath(string cmdLine) { auto screen = executeShell(cmdLine); if (screen.status != 0) { writeln(cmdLine, " failed"); } else { writeln("screen.output = ", screen.output); auto s = screen.output.findSplit("REG_SZ"); writeln("s[0] = ", s[0]); writeln("s[1] = ", s[1]); writeln("s[2] = ", s[2]); } return (s.split(';')); // Error: undefined identifier `s` } As Ali mentioned, your logic is faulty -- you seem to write that the command failed, but then return something anyway. Also, you are returning `string[]`, so just declaring `string[] s;` should be enough. However, I did want to mention that if you do want to hoist a difficult to name type outside where it is declared with an auto, you can use `typeof`: ```d typeof(screen.output.findSplit("")) s; ``` In this case, it's just `string[]`, but the idea here is you can name a type without naming it, by using `typeof` on the expression you would have called. Hope this helps further your D knowledge ;) -Steve
Re: auto scope question?
On 10/25/22 15:07, WhatMeWorry wrote: > auto screen = executeShell(cmdLine); > auto s; That can't work because there is no information to infer the type of 's'. Judging from the return type of getPath, perhaps it's string[]: string[] s; This is the question we should answer first: What should happen when executeShell fails? a) It is an error; the program should not continue. Then we can use 'enforce' (this is my way of coding): string[] getPath(string cmdLine) { import std.exception : enforce; auto screen = executeShell(cmdLine); enforce(screen.status == 0, format!"%s failed:\n%s"(cmdLine, screen.output)); writeln("screen.output = ", screen.output); auto s = screen.output.findSplit("REG_SZ"); writeln("s[0] = ", s[0]); writeln("s[1] = ", s[1]); writeln("s[2] = ", s[2]); return (s.split(';')); } b) It is not an error; getPath() should return empty array: string[] getPath(string cmdLine) { string[] result; auto screen = executeShell(cmdLine); if (screen.status != 0) { writeln(cmdLine, " failed"); return null; // <-- HERE (null converts to any array type) } else { // ... // Now, 'return' is where 's' is defined: return (s.split(';')); } } Ali
Re: auto ref function parameter causes that non copyable struct is copied?
On Tuesday, 9 November 2021 at 19:30:20 UTC, tchaloupka wrote: On Monday, 8 November 2021 at 23:26:39 UTC, tchaloupka wrote: Bug or feature? :) I've reported it in https://issues.dlang.org/show_bug.cgi?id=22498. It doesn't copy. It just destructs the same object twice... Ouch. Change the destructor to `~this() { printf("~this(%d)\n", n); n = 12; }` and you'll see. I have been looking at LDC's IR of this. `unwrap` takes a lvalue, but the compiler puts the object from `gen` on main's stack and gives a pointer to unwrap instead. `unwrap` is now the sole owner of the object, and calls the destructor before returning a ref to one of its fields. I haven't figured out the interplay of features and optimizations here, but it looks like a leak. I would have expected @safe to catch this. As you said in the bug, NVRO solves it (not sure why). As well as not passing a lvalue into `unwrap` in the first place.
Re: auto ref function parameter causes that non copyable struct is copied?
On Monday, 8 November 2021 at 23:26:39 UTC, tchaloupka wrote: Bug or feature? :) I've reported it in https://issues.dlang.org/show_bug.cgi?id=22498.
Re: auto ref function parameter causes that non copyable struct is copied?
On Tuesday, 9 November 2021 at 02:43:55 UTC, jfondren wrote: On Tuesday, 9 November 2021 at 02:41:18 UTC, jfondren wrote: The expectation is probably that `f.move` set `f` to `Foo.init`, but the docs say: Posted too fast. Foo qualifies with its @disable: ```d struct A { int x; } struct B { int x; @disable this(this); } unittest { import core.lifetime : move; auto a = A(5); auto b = B(5); a.move; b.move; assert(a == A(5)); assert(b == B(0)); } ``` Yes it should qualify so it should be cleaned out when moved. When I change: ```D auto ref unwrap(EX)(auto ref EX res) { printf("unwrap()\n"); return res.get(); } ``` I get: ``` ~this(0) ~this(0) ~this(0) unwrap() ~this(42) ~this(0) ~this(42) ``` So the destructor isn't called from `gen()` -> there is [NRVO](https://dlang.org/glossary.html#nrvo) in play. Also `pragma(msg, __traits(isRef, res));` prints false in unwrap in this case (which is expected), but how it gets there as a value when it's not moved and instead copied even though it has disabled copy constructor? `isCopyable!(Value!Foo)` returns false as expected too.
Re: auto ref function parameter causes that non copyable struct is copied?
On Tuesday, 9 November 2021 at 02:41:18 UTC, jfondren wrote: The expectation is probably that `f.move` set `f` to `Foo.init`, but the docs say: Posted too fast. Foo qualifies with its @disable: ```d struct A { int x; } struct B { int x; @disable this(this); } unittest { import core.lifetime : move; auto a = A(5); auto b = B(5); a.move; b.move; assert(a == A(5)); assert(b == B(0)); } ```
Re: auto ref function parameter causes that non copyable struct is copied?
On Tuesday, 9 November 2021 at 02:19:28 UTC, Stanislav Blinov wrote: On Monday, 8 November 2021 at 23:26:39 UTC, tchaloupka wrote: ``` auto gen() { Foo f; // <--- this one f.n = 42; return value(f.move()); } void main() { Foo f; f = gen().unwrap.move; } ``` ~this(0) ~this(0) ~this(0) ~this(42) <- this is a copy (that shouldn't exist) being destroyed ~this(0) ~this(42) Is it a copy? I think the first destructor call is one of `f` in `gen` (marked by the comment above) The expectation is probably that `f.move` set `f` to `Foo.init`, but the docs say: "If T is a struct with a destructor or postblit defined, source is reset to its .init value after it is moved into target, otherwise it is left unchanged." ```d struct A { int x; } struct B { int x; this(this) { } } unittest { import core.lifetime : move; auto a = A(5); auto b = B(5); a.move; b.move; assert(a == A(5)); assert(b == B(0)); } ```
Re: auto ref function parameter causes that non copyable struct is copied?
On Monday, 8 November 2021 at 23:26:39 UTC, tchaloupka wrote: ``` auto gen() { Foo f; // <--- this one f.n = 42; return value(f.move()); } void main() { Foo f; f = gen().unwrap.move; } ``` ~this(0) ~this(0) ~this(0) ~this(42) <- this is a copy (that shouldn't exist) being destroyed ~this(0) ~this(42) Is it a copy? I think the first destructor call is one of `f` in `gen` (marked by the comment above)
Re: auto vectorization notes
On Saturday, 28 March 2020 at 18:01:37 UTC, Crayo List wrote: On Saturday, 28 March 2020 at 06:56:14 UTC, Bruce Carneal wrote: On Saturday, 28 March 2020 at 05:21:14 UTC, Crayo List wrote: On Monday, 23 March 2020 at 18:52:16 UTC, Bruce Carneal wrote: [snip] Explicit SIMD code, ispc or other, isn't as readable or composable or vanilla portable but it certainly is performance predictable. This is not true! The idea of ispc is to write portable code that will vectorize predictably based on the target CPU. The object file/binary is not portable, if that is what you meant. Also, I find it readable. There are many waypoints on the readability <==> performance axis. If ispc works for you along that axis, great! I find SIMT code readability better than SIMD but a little worse than auto-vectorizable kernels. Hugely better performance though for less effort than SIMD if your platform supports it. Again I don't think this is true. Unless I am misunderstanding you, SIMT and SIMD are not mutually exclusive and if you need performance then you must use both. Also based on the workload and processor SIMD may be much more effective than SIMT.j SIMD might become part of the solution under the hood for a number of reasons including: ease of deployment, programmer familiarity, PCIe xfer overheads, kernel launch overhead, memory subsystem suitability, existing code base issues, ... SIMT works for me in high throughput situations where it's hard to "take a log" on the problem. SIMD, in auto-vectorizable or more explicit form, works in others. Combinations can be useful but most of the work I've come in contact with splits pretty clearly along the memory bandwidth divide (SIMT on one side, SIMD/CPU on the other). Others need a plus-up in arithmetic horsepower. The more extreme the requirements, the more attractive SIMT appears. (hence my excitement about dcompute possibly expanding the dlang performance envelope with much less cognitive load than CUDA/OpenCL/SycL/...) On the readability front, I find per-lane programming, even with the current thread-divergence caveats, to be easier to reason about wrt correctness and performance predictability than other approaches. Apparently your mileage does vary. When you have chosen SIMD, whether ispc or other, over SIMT what drove the decision? Performance? Ease of programming to reach a target speed?
Re: auto vectorization notes
On Saturday, 28 March 2020 at 06:56:14 UTC, Bruce Carneal wrote: On Saturday, 28 March 2020 at 05:21:14 UTC, Crayo List wrote: On Monday, 23 March 2020 at 18:52:16 UTC, Bruce Carneal wrote: [snip] (on the downside you have to guard against compiler code-gen performance regressions) auto vectorization is bad because you never know if your code will get vectorized next time you make some change to it and recompile. Just use : https://ispc.github.io/ Yes, that's a downside, you have to measure your performance sensitive code if you change it *or* change compilers or targets. Explicit SIMD code, ispc or other, isn't as readable or composable or vanilla portable but it certainly is performance predictable. This is not true! The idea of ispc is to write portable code that will vectorize predictably based on the target CPU. The object file/binary is not portable, if that is what you meant. Also, I find it readable. I find SIMT code readability better than SIMD but a little worse than auto-vectorizable kernels. Hugely better performance though for less effort than SIMD if your platform supports it. Again I don't think this is true. Unless I am misunderstanding you, SIMT and SIMD are not mutually exclusive and if you need performance then you must use both. Also based on the workload and processor SIMD may be much more effective than SIMT.
Re: auto vectorization notes
On Saturday, 28 March 2020 at 05:21:14 UTC, Crayo List wrote: On Monday, 23 March 2020 at 18:52:16 UTC, Bruce Carneal wrote: [snip] (on the downside you have to guard against compiler code-gen performance regressions) auto vectorization is bad because you never know if your code will get vectorized next time you make some change to it and recompile. Just use : https://ispc.github.io/ Yes, that's a downside, you have to measure your performance sensitive code if you change it *or* change compilers or targets. Explicit SIMD code, ispc or other, isn't as readable or composable or vanilla portable but it certainly is performance predictable. I find SIMT code readability better than SIMD but a little worse than auto-vectorizable kernels. Hugely better performance though for less effort than SIMD if your platform supports it. Is anyone actively using dcompute (SIMT enabler)? Unless I hear bad things I'll try it down the road as neither going back to CUDA nor "forward" to the SycL-verse appeals.
Re: auto vectorization notes
On Monday, 23 March 2020 at 18:52:16 UTC, Bruce Carneal wrote: When speeds are equivalent, or very close, I usually prefer auto vectorized code to explicit SIMD/__vector code as it's easier to read. (on the downside you have to guard against compiler code-gen performance regressions) One oddity I've noticed is that I sometimes need to use pragma(inline, *false*) in order to get ldc to "do the right thing". Apparently the compiler sees the costs/benefits differently in the standalone context. More widely known techniques that have gotten people over the serial/SIMD hump include: 1) simplified indexing relationships 2) known count inner loops (chunkify) 3) static foreach blocks (manual inlining that the compiler "gathers") I'd be interested to hear from others regarding their auto vectorization and __vector experiences. What has worked and what hasn't worked in your performance sensitive dlang code? auto vectorization is bad because you never know if your code will get vectorized next time you make some change to it and recompile. Just use : https://ispc.github.io/
Re: Auto-generation of online documentation for my open libraries
On Sunday, 23 February 2020 at 18:40:03 UTC, Adam D. Ruppe wrote: The error I currently get when clicking the documentation link https://phobos-next.dpldocs.info/ is try it now. I've been tweaking the time out and retry numbers lately so it is less likely to do this but still sometimes does when it regenerates... but still that particular error you saw indicates i messed up an if condition somewhere, that path is supposed to be impossible. oops. regardless it works now and you can see some of the new style tweaks I've been doing! Wonderful! Thanks
Re: Auto-generation of online documentation for my open libraries
On Sunday, 23 February 2020 at 18:20:19 UTC, Per Nordlöw wrote: The error I currently get when clicking the documentation link https://phobos-next.dpldocs.info/ is try it now. I've been tweaking the time out and retry numbers lately so it is less likely to do this but still sometimes does when it regenerates... but still that particular error you saw indicates i messed up an if condition somewhere, that path is supposed to be impossible. oops. regardless it works now and you can see some of the new style tweaks I've been doing!
Re: Auto-generation of online documentation for my open libraries
On Sunday, 23 February 2020 at 18:18:25 UTC, Per Nordlöw wrote: On Sunday, 23 February 2020 at 17:18:48 UTC, Andre Pany wrote: If your Dub package is registered on code.dlang.org, this is automatically provided. Example: http://code.dlang.org/packages/arsd-official Click on the documentation link. Beside that you can use e.g. Github Actions to create documentation. Kind regards Andre I've fixed my phobos-next so that doc generation now works via dub build --build=docs --compiler=dmd Is this command called only when I tag my repo with a new version? The error I currently get when clicking the documentation link https://phobos-next.dpldocs.info/ is The project build failed. copy/paste this link to adam so he can fix the bug. std.file.FileException@std/file.d(379): /dpldocs/phobos-next/master/adrdox-generated/: Is a directory /home/me/d/dmd2/linux/bin64/../../src/phobos/std/file.d:273 @trusted bool std.file.cenforce!(bool).cenforce(bool, scope const(char)[], scope const(char)*, immutable(char)[], ulong) [0x543266] ??:? @trusted void[] std.file.readImpl(scope const(char)[], scope const(char)*, ulong) [0x5ec90b] /home/me/d/dmd2/linux/bin64/../../src/phobos/std/file.d:310 @safe void[] std.file.read!(immutable(char)[]).read(immutable(char)[], ulong) [0x543041] dl.d:271 void dl.app(arsd.cgi.Cgi) [0x528000] /home/me/arsd/cgi.d:3815 void arsd.cgi.doThreadScgiConnection!(arsd.cgi.Cgi, dl.app(arsd.cgi.Cgi), 500L).doThreadScgiConnection(std.socket.Socket) [0x546e43] /home/me/arsd/cgi.d:4361 void arsd.cgi.ConnectionThread.run() [0x53b2a8] ??:? void core.thread.Thread.run() [0x5c8a25] ??:? thread_entryPoint [0x6159cb] ??:? [0x7f0c425e76da]
Re: Auto-generation of online documentation for my open libraries
On Sunday, 23 February 2020 at 17:18:48 UTC, Andre Pany wrote: If your Dub package is registered on code.dlang.org, this is automatically provided. Example: http://code.dlang.org/packages/arsd-official Click on the documentation link. Beside that you can use e.g. Github Actions to create documentation. Kind regards Andre I've fixed my phobos-next so that doc generation now works via dub build --build=docs --compiler=dmd Is this command called only when I tag my repo with a new version?
Re: Auto-generation of online documentation for my open libraries
On Sunday, 23 February 2020 at 17:14:33 UTC, Per Nordlöw wrote: I would like to setup auto-generation of online documentation for my public D libraries residing on Github and Gitlab. What alternatives do I have? for gitlab they have a system of pages that's quite easy to setup: something like .gitlab-ci.yml --- #to get dmd and dub image: dlang2/dmd-ubuntu #special section to generate gitlab "pages" pages: before_script: - apt-get install -y - script: - artifacts: paths: - public only: - master - --- and then your doc is online and updated for each push. It can be downloaded from the artifacts too, maybe in an automated way I think, but havent used this for now so cant say.
Re: Auto-generation of online documentation for my open libraries
On Sunday, 23 February 2020 at 17:38:35 UTC, Per Nordlöw wrote: On Sunday, 23 February 2020 at 17:18:48 UTC, Andre Pany wrote: Example: http://code.dlang.org/packages/arsd-official Click on the documentation link. Beside that you can use e.g. Github Actions to create documentation. Kind regards Andre Thanks! How do I check which dmd or dub command that is called to generate the docs? They are generated using adrdox, a third-party documentation generator by Adam Ruppe: https://github.com/adamdruppe/adrdox The exact command used to generate the docs for dpldocs.info can be found here: https://github.com/adamdruppe/dpldocs/blob/858e375b98883c9a46a6ff9a894f371fcfae23a0/dl.d#L301-L309
Re: Auto-generation of online documentation for my open libraries
On Sunday, 23 February 2020 at 17:18:48 UTC, Andre Pany wrote: Example: http://code.dlang.org/packages/arsd-official Click on the documentation link. Beside that you can use e.g. Github Actions to create documentation. Kind regards Andre Thanks! How do I check which dmd or dub command that is called to generate the docs?
Re: Auto-generation of online documentation for my open libraries
On Sunday, 23 February 2020 at 17:14:33 UTC, Per Nordlöw wrote: I would like to setup auto-generation of online documentation for my public D libraries residing on Github and Gitlab. What alternatives do I have? If your Dub package is registered on code.dlang.org, this is automatically provided. Example: http://code.dlang.org/packages/arsd-official Click on the documentation link. Beside that you can use e.g. Github Actions to create documentation. Kind regards Andre
Re: Auto-generation of online documentation for my open libraries
On Sunday, 23 February 2020 at 17:14:33 UTC, Per Nordlöw wrote: I would like to setup auto-generation of online documentation for my public D libraries residing on Github and Gitlab. What alternatives do I have? I'm thinking something like http://ddocs.org announced here https://forum.dlang.org/thread/weuxppabkrreaxbqq...@forum.dlang.org. Unfortunately http://ddocs.org seems to be down. Are there any mirrors up?
Re: auto keyword
On Thu, Jan 30, 2020 at 09:37:40AM +, Michael via Digitalmars-d-learn wrote: [...] > auto elements = buf.to!string.strip.split(" ").filter!(a => a != ""); > > That line strips white space from buf, splits it, removes empty > elements and returns an array of strings. At least I thought so. If you want an array of strings, just add .array to the end, and you will get string[] back. > Indeed elements can be treated as a string slice, but if i replace > auto by string[] the compiler complains: > Error: cannot implicitly convert expression filter(split(strip(to(buf)), " > ")) of type FilterResult!(__lambda1, string[]) to string[] That's because the actual type is a lazily-evaluated range. > In order to use an explicit type I wonder what kind of type I might > use instead of auto? In this case, you actually can't spell out the type, because it's a Voldemort type (it's only defined inside the function that constructs it, and is not directly nameable outside). Usually, a Voldemort type is returned when you *shouldn't* be referring to it with an explicit type. For example, in this case, if what you really want is an array of strings then you should add .array at the end to get a string[]. If you wish to store the lazy range, for whatever reason, you can use the typeof() operator to extract a type from it (without actually spelling it out -- because you can't): auto elements = buf.to!string.strip.split(" ").filter!(a => a != ""); alias E = typeof(elements); E x; x = elements; Usually this is only useful if you wish the store the lazy range inside some kind of aggregate type while retaining its lazy evaluation semantics. But if you expect it to be eagerly evaluated anyway, there's no need to jump through hoops to get at the type of `elements`; just stick .array to the end of it and get a string[] back. T -- "The whole problem with the world is that fools and fanatics are always so certain of themselves, but wiser people so full of doubts." -- Bertrand Russell. "How come he didn't put 'I think' at the end of it?" -- Anonymous
Re: auto keyword
On Thursday, January 30, 2020 2:37:40 AM MST Michael via Digitalmars-d-learn wrote: > auto is surely a nice feature. Nonetheless I'd prefer to use > explicit types. So when reading a code and I see the auto keyword > I also have to find out what kind of type is meant. > > I have a line of code that looks like this: > auto elements = buf.to!string.strip.split(" ").filter!(a => a != > ""); > > That line strips white space from buf, splits it, removes empty > elements and returns an array of strings. At least I thought so. > > Indeed elements can be treated as a string slice, but if i > replace auto by string[] the compiler complains: > Error: cannot implicitly convert expression > filter(split(strip(to(buf)), " ")) of type > FilterResult!(__lambda1, string[]) to string[] > > In order to use an explicit type I wonder what kind of type I > might use instead of auto? For code like that, you don't. A lot of code in D - especially code that uses ranges - uses what are called Voldemort types. They are declared inside the function and you have no access to them. They follow a known API, so you know what to do with them, but you they have no name that you have access to. Realistically though, even if you had access to the type's name, you wouldn't want to use it explicitly anyway, because usually, it's a templated type which is instantiated with another templated type and is likely several layers deep. Using the explicit names would be hideous. Years ago (before we had Voldemort types), there was a bug in ddoc that made functions that returned auto not show up in the documentation. So, all of std.algorithm returned explicit types, and they were so hideous that it just scared people. It works _far_ better to just understand how to use these types and not use their names explicitly. It also makes the code far more resilient to changes, since as long as the return type retains the same API, it doesn't matter how the return type is changed. A function like filter could have its return type changed to something else, and the code calling it wouldn't care so long as it was the same kind of range. Since you probably aren't familiar with ranges in D (or you wouldn't be trying to use them by name), I suggest that you read this: http://ddili.org/ders/d.en/ranges.html And in addition to the fact that you pretty much have to use auto with range-based code, you're pretty much going to have to get used to dealing with D code using auto heavily, because that's what most D code does. Certainly, sometimes, you can use type names explicitly, but it's common practice to use auto most of the time. It can take a bit of getting used to, but ultimately, it actually results in more maintainable code. - Jonathan M Davis
Re: Auto keyword and when to use it
On Tuesday, 21 August 2018 at 21:37:00 UTC, QueenSvetlana wrote: I had a misunderstanding about the keyword auto because I wrongfully believed that it made the code like Python Exactly, you are thinking still like D is Python or also dynamically typed. :) You will get when compiling errors that Python wouldn't detect until run-time (or with your private methods). - A declaration with auto needs to include an initialization. - The code will be equivalent as if replacing "auto" with the inferred type. It is not left for later to check. I'm not terribly bothered btw by "Type = new Type()" but often type names get too long or include namespaces... "mylib.numeric.squareObjectWithPointyCorners = new mylib.numeric.squareObjectWithPointyCorners()"
Re: Auto keyword and when to use it
On Tuesday, 21 August 2018 at 18:44:15 UTC, Jim Balter wrote: Python is not statically typed; D is. Why are you talking about Python? You asked whether D's auto is like C#'s var ... it is, but it doesn't have C#'s pointless restriction of not being allowed for non-local declarations. I think you misunderstood my point. Let me elaborate. In Python a type could change at anytime, for example: number = 1 In Python the variable number will be treated as an int, but at any point in my code, that could change, in Python this is legal: number = "one" The code will compile and run. Now Python introduced type hints to tell the reader how to treat the variable. The problem with the code is, when you have a class, take my Person example, a person will obviously have a first and last name, which should be strings, now without validation I can pass ints to those variables, which is undesirable. I would need a private function to check the types passed and reject it if they aren't strings, in addition to if the string is blank or contains foreign characters. I had a misunderstanding about the keyword auto because I wrongfully believed that it made the code like Python, and for that I apologize. I thought you were allowed to make class variables auto, so for example: class Person{ auto firstName auto lastName } If this was allowed, when I create my person object, I can pass ints to firstName and lastName, which is obviously undesirable. I would need to check what value types were passed and reject them if they aren't strings. As pointed out in the answers above, this isn't legal, which means, there is no need to check anything, it won't compile.
Re: Auto keyword and when to use it
On Tuesday, August 21, 2018 12:22:42 PM MDT QueenSvetlana via Digitalmars-d- learn wrote: > On Monday, 20 August 2018 at 17:55:11 UTC, JN wrote: > > class Foo > > { > > > > auto bar; > > > > } > > > > because now the compiler doesn't know what type 'bar' is > > supposed to be. > > Just to clarify, even if I set bar in the constructor, I can't > declare it with auto first, correct? I would have to declare a > specific type? Yes. As Mike's excellent response explained, auto is simply used to indicate that you're not providing the explicit type and that it should be inferred from the direct initialization of the variable. Whenever an explicit type is not provided for a variable when declaring it, you _must_ use direct initialization so that the type can be inferred. You can't do something like have the type of a member variable inferred from what the constructor is doing. And code like auto foo; is never legal. - Jonathan M Davis
Re: Auto keyword and when to use it
On Tuesday, August 21, 2018 9:04:31 AM MDT Steven Schveighoffer via Digitalmars-d-learn wrote: > On 8/20/18 9:15 PM, Mike Parker wrote: > > I tend to use type inference liberally, almost always with > > const/immutbale locals, though I tend to use auto only when the type > > name is longer than four characters. For me, it's a nice way to save > > keystrokes. Some take a dim view of that approach and prefer to use it > > only when they actually require type inference. I mostly program alone, > > though, and I have a number of habits others may label 'bad', so I'm > > happy with my approach. > > I'm more extreme in this camp -- I use auto everywhere. Why? because at > some point, I may change some type somewhere (oops, I should have wrote > size_t instead of uint), and then I would have to go through and change > all the places I put the concrete type if I hadn't used auto. > > While using functions, I also can use auto and not have to worry about > the type. I know kind of what it is (integer type, string type, range > type, etc), and not care what the exact type is. I'd argue that it's generally better to use explicit types where possible in function signatures so that the documentation is clearer, but overall, I agree with you, and if I can use type inference, I almost always do. However, it does seem like the sort of thing that many newcomers to D balk at initially, whereas most of us who have been using it for a while have no problem with it and prefer it. - Jonathan M Davis
Re: Auto keyword and when to use it
On Tuesday, 21 August 2018 at 18:18:25 UTC, QueenSvetlana wrote: On Tuesday, 21 August 2018 at 16:15:32 UTC, XavierAP wrote: Only if someone likes "Type x = new Type()" instead of "auto x = new Type()" I would say they're clearly wrong. As you stated it's up to the programmer to decided. I'm in favor of Type x = new Type() There is nothing to recommend such redundancy; don't do it. because when it comes to constructing a class it usually means more code to verify the types Type inference doesn't require more code. for example: Your example has no bearing on any of the above ... it's not an example of it. class Person { auto firstName; auto lastName; // constuctor to set first and last names } That code is meaningless and isn't legal. You need to either provide explicit types, or they need to be inferable from the type of the initializer. The compiler doesn't know know what firstName or lastName is supposed to be and a programmer might make the obvious assumption and use them as strings. The programmer can't make any assumption because the code is not remotely legal. Doing this also means you have reject any type that isn't a string which means a private function to check the type that was pass to the constructor before initializing it. Where as if you declared it as a string to start of with, all you have to ensure is that it's not blank or contain illegal characters. This is all incoherent. D is a statically typed language. As the answer stated above doing what I showed in my example isn't allowed and this is where Python gets frustrating, because at any point the types could change. They introduced type hints, but it's not enforced, it just makes it more readable, you still have to write code to ensure the proper types were passed. Python is not statically typed; D is. Why are you talking about Python? You asked whether D's auto is like C#'s var ... it is, but it doesn't have C#'s pointless restriction of not being allowed for non-local declarations.
Re: Auto keyword and when to use it
On Monday, 20 August 2018 at 17:55:11 UTC, JN wrote: class Foo { auto bar; } because now the compiler doesn't know what type 'bar' is supposed to be. Just to clarify, even if I set bar in the constructor, I can't declare it with auto first, correct? I would have to declare a specific type?
Re: Auto keyword and when to use it
On Tuesday, 21 August 2018 at 16:15:32 UTC, XavierAP wrote: Only if someone likes "Type x = new Type()" instead of "auto x = new Type()" I would say they're clearly wrong. As you stated it's up to the programmer to decided. I'm in favor of Type x = new Type() because when it comes to constructing a class it usually means more code to verify the types, for example: class Person { auto firstName; auto lastName; // constuctor to set first and last names } The compiler doesn't know know what firstName or lastName is supposed to be and a programmer might make the obvious assumption and use them as strings. Doing this also means you have reject any type that isn't a string which means a private function to check the type that was pass to the constructor before initializing it. Where as if you declared it as a string to start of with, all you have to ensure is that it's not blank or contain illegal characters. As the answer stated above doing what I showed in my example isn't allowed and this is where Python gets frustrating, because at any point the types could change. They introduced type hints, but it's not enforced, it just makes it more readable, you still have to write code to ensure the proper types were passed.
Re: Auto keyword and when to use it
On Monday, 20 August 2018 at 17:52:17 UTC, QueenSvetlana wrote: So I can't declare class level variables with auto, correct? only local method variables? One difference between D's auto and C#'s var or C++'s auto is that the latter languages allow automatically typed declarations only for local (method/function-scope) variables, and forbid them for class or struct member variables (aka fields); whereas D allows auto anywhere (even function/method return type! -- which C# and C++ allow as well but only case of anonymous methods/lambdas). I'm in favor of the AAA ("Auto" Almost Always) paradigm, but as long as the type if obvious to a human reader. I don't favor them for numeric types for this reason (non obvious bitsize, signedness...) It's up to each programmer. Only if someone likes "Type x = new Type()" instead of "auto x = new Type()" I would say they're clearly wrong.
Re: Auto keyword and when to use it
On 8/20/18 9:15 PM, Mike Parker wrote: I tend to use type inference liberally, almost always with const/immutbale locals, though I tend to use auto only when the type name is longer than four characters. For me, it's a nice way to save keystrokes. Some take a dim view of that approach and prefer to use it only when they actually require type inference. I mostly program alone, though, and I have a number of habits others may label 'bad', so I'm happy with my approach. I'm more extreme in this camp -- I use auto everywhere. Why? because at some point, I may change some type somewhere (oops, I should have wrote size_t instead of uint), and then I would have to go through and change all the places I put the concrete type if I hadn't used auto. While using functions, I also can use auto and not have to worry about the type. I know kind of what it is (integer type, string type, range type, etc), and not care what the exact type is. -Steve
Re: Auto keyword and when to use it
On Monday, 20 August 2018 at 17:24:19 UTC, QueenSvetlana wrote: I'm struggling to understand what the auto keyword is for and it's appropriate uses. From research, it seems to share the same capabilities as the var keyword in C#. auto is one of the most misunderstood understood features in D. By that I mean, everyone understands the effect of auto, but aren't always accurate in describing it. In D, every variable must have a storage class. The automatic storage class is the default and is never specified in the declaration: int x = 10; Other storage classes are const, immutable, and shared. These are also type constructors, so they become part of the type: const int y = 11; // type is const(int) immutable int z = 12; // type is immutable(int) shared int s = 13; // type is shared(int) D allows the type to be dropped in declarations that include an initializer. In those cases, the type will be inferred: const y = 11; // type is const(int) immutable z = 12; // type is immutable(int) shared s = 13; // type is shared(int) You can also drop the type in declarations with automatic storage, but `x = 10;` is not allowed as a variable declaration. You must include at minimum a type or a storage class. That's where auto comes in: auto x = 10; // type is int So that's all it is. It's nothing special. It just means you're declaring a variable with the default storage class and want the compiler to infer the type. So the question 'when should I use auto' is probably the wrong way to look at it. 'When should I use type inference' is a better way to frame it. And the answer to that is that there is no right answer. I tend to use type inference liberally, almost always with const/immutbale locals, though I tend to use auto only when the type name is longer than four characters. For me, it's a nice way to save keystrokes. Some take a dim view of that approach and prefer to use it only when they actually require type inference. I mostly program alone, though, and I have a number of habits others may label 'bad', so I'm happy with my approach.
Re: Auto keyword and when to use it
On Monday, 20 August 2018 at 17:52:17 UTC, QueenSvetlana wrote: Great! So I can't declare class level variables with auto, correct? only local method variables? You can, globals, class members: class Foo { auto bar = "hi"; } Foo.bar will be of string type here, because "hi" is a string. What you can't do is: class Foo { auto bar; } because now the compiler doesn't know what type 'bar' is supposed to be.
Re: Auto keyword and when to use it
On Monday, 20 August 2018 at 17:52:17 UTC, QueenSvetlana wrote: Great! So I can't declare class level variables with auto, correct? only local method variables? You can use auto if you're setting the class level variable to a default. class X { auto i = 42; // i will be an int }
Re: Auto keyword and when to use it
Great! So I can't declare class level variables with auto, correct? only local method variables?
Re: Auto keyword and when to use it
On Monday, 20 August 2018 at 17:24:19 UTC, QueenSvetlana wrote: I'm new to D programming, but have I have a background with Python. I'm struggling to understand what the auto keyword is for and it's appropriate uses. From research, it seems to share the same capabilities as the var keyword in C#. From the C# documentation, it states: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/var ... variables that are declared at method scope can have an implicit "type" var. An implicitly typed local variable is strongly typed just as if you had declared the type yourself, but the compiler determines the type. Is the same true for auto? For example, if I have a class Person, I might have attributes such as FirstName, LastName which should obviously be strings but will D allow me to declare class level attributes with auto? C# doesn't allow this. It basically works like C#. auto x = "hi"; will make x a string. But if you later try: x = 5; it will throw an error, because x is a string. It's used to save you the typing of the type, it doesn't make the language dynamically typed.
Re: auto & class members
On 5/22/18 4:40 AM, Robert M. Münch wrote: On 2018-05-21 18:55:36 +, Steven Schveighoffer said: When you use the alias, both are using the same exact lambda. Ok. I didn't expect that the name is relevant in this case, instead assumed that only the types need to match. The type is the problem. The type returned by filter is parameterized on that *specific* lambda. If you look at the error message, it says something like "lamda1" and "lambda4" in the type for filter. In order to make this work, the compiler would have to make the name of the lambda based on the actual AST inside it. I think something like that should be done. I see you are casting now as well, Do I? Not that I'm aware of it in my pseudo-code example... Haha, looking back, I see you didn't cast originally, which is probably the reason it didn't work :) Here is the line from your revised example after Jonathan showed you how to declare a member of that type: myB.mySubstream = myA.myStream.filter!(x => x == myMessage); And here is the subsequent line: myB.mySubstream = cast(myMessageType)myA.myStream.filter!(x => x == myMessage); Both exactly the same, but one forces the cast. Your first line could have been done: myB.mySubstream = cast(typeof(myB.mySubstream))myA.myStream.filter!(x => x == myMessage); Giving a name helps to make the code less verbose, but essentially that is what you are doing -- forcing the cast. What may make more sense (both for type sanity and for code reuse) is to wrap your call to filter into one place so it can be used wherever you need it: auto wrapStream(S)(S str) { return str.filter!(x => x == myMessage); } class b { typeof(wrapStream(a.init.myStream)()) mySubStream; } void myFunc() { a myA = new a; b myB = new b; myB.mySubstream = myA.myStream.wrapStream; } This would require one wrap function per different lambda, right? Assume I have 50-100 of these. Maybe the myMessage value can be given as parameter and with this becomes more like a "filter factory". Not sure if this would work Well, you then have to have 50-100 types of b with the correct member. Unless... you want to parameterize b, in which case it becomes REALLY easy: class b(FilterType) { FilterType mySubstream; } auto makeB(FilterType)(FilterType f) { return new b!FilterType(f); } ... auto myB = myA.myStream.filter!(x => coolCrazyFunction(x)).makeB; -Steve
Re: auto & class members
On Tuesday, May 22, 2018 10:40:55 Robert M. Münch via Digitalmars-d-learn wrote: > This would require one wrap function per different lambda, right? > Assume I have 50-100 of these. Maybe the myMessage value can be given > as parameter and with this becomes more like a "filter factory". Not > sure if this would work. Pretty much the only time that this sort of thing pops up is when you have to declare a variable that's a range (or some other similarly generic type) separately from where it's initialized. I'd expect that your application would have to be very large to have 50 - 100 instances of that. If you really were hitting it a lot, then maybe it would make sense to try and figure out a way to avoid having to declare a wrapper function, but in my experience, this sort of thing simply doesn't come up all that often. It's definitely an issue, and occasionally someone will come here and ask how to deal with it, but I'd be worried if it came up often enough that creating a wrapper function to deal with it was a problem. The other way to fix the problem is to just call std.array.array on the range to get a dynamic array. It does mean allocating, but you run into fewer problems related to type inference, since you can then easily type the type rather than having to use type inference to get it. - Jonathan M Davis
Re: auto & class members
On Tuesday, May 22, 2018 10:43:38 Robert M. Münch via Digitalmars-d-learn wrote: > On 2018-05-21 20:17:04 +, Jonathan M Davis said: > > On Monday, May 21, 2018 16:05:00 Steven Schveighoffer via Digitalmars-d- > > > > learn wrote: > >> Well one thing that seems clear from this example -- we now have > >> __traits(isSame) to tell if lambdas are the same, but it looks like the > >> compiler doesn't subscribe to that belief... > >> > >> https://run.dlang.io/is/FW3mVq > >> > >> We should fix that... > > > > Yeah. That part of lambdas has always been a problem. My guess here is > > that the problem stems from the fact that they're declared in separate > > scopes, but I don't know. Regardless of the reason for the failure > > though, that example really needs to work, or most anything that cares > > about lambdas being the same is going to have problems. > > I think that's exactly the problem: I assumed that it's about the > lambdas and associated types but would have never guessed that names, > scope etc. play a role as well. Is this somewhere documented? Or at > least a hint, would help a lot to be aware of this pitfall. The issue is that you actually have different lambdas. They _look_ the same, but they aren't actually the same function. The compiler is not good about recognizing that two lambdas are identical. When Steven said that they had different names, he meant that it was like if you had declared: int foo(int i) { return i + 42; } int bar(int i) { return i + 42; } Both functions are identical, but the compiler doesn't see that. It just looks at the signatures - and while everything about them is functionally equivalent, they have different names. Basically, the compiler is too dumb to figure out when two lambdas are actually identical. Some work has been done towards making it that smart, but there is still clearly more work to be done. As for how well any of this is documented, I don't know, but I suspect that at most, the spec has a line or two about it somewhere, especially since it's really not something that was planned for per se. It's just a natural fallout of how lambdas work and is surprisingly difficult to fix. - Jonathan M Davis
Re: auto & class members
On 2018-05-21 18:55:36 +, Steven Schveighoffer said: So the issue here is that the lambda function inside myFunc is DIFFERENT than the one inside b. They are both the same function, but with essentially different names. Aha... that explains it pretty good. When you use the alias, both are using the same exact lambda. Ok. I didn't expect that the name is relevant in this case, instead assumed that only the types need to match. I see you are casting now as well, Do I? Not that I'm aware of it in my pseudo-code example... What may make more sense (both for type sanity and for code reuse) is to wrap your call to filter into one place so it can be used wherever you need it: auto wrapStream(S)(S str) { return str.filter!(x => x == myMessage); } class b { typeof(wrapStream(a.init.myStream)()) mySubStream; } void myFunc() { a myA = new a; b myB = new b; myB.mySubstream = myA.myStream.wrapStream; } This would require one wrap function per different lambda, right? Assume I have 50-100 of these. Maybe the myMessage value can be given as parameter and with this becomes more like a "filter factory". Not sure if this would work. -- Robert M. Münch http://www.saphirion.com smarter | better | faster
Re: auto & class members
On 2018-05-21 20:17:04 +, Jonathan M Davis said: On Monday, May 21, 2018 16:05:00 Steven Schveighoffer via Digitalmars-d- learn wrote: Well one thing that seems clear from this example -- we now have __traits(isSame) to tell if lambdas are the same, but it looks like the compiler doesn't subscribe to that belief... https://run.dlang.io/is/FW3mVq We should fix that... Yeah. That part of lambdas has always been a problem. My guess here is that the problem stems from the fact that they're declared in separate scopes, but I don't know. Regardless of the reason for the failure though, that example really needs to work, or most anything that cares about lambdas being the same is going to have problems. I think that's exactly the problem: I assumed that it's about the lambdas and associated types but would have never guessed that names, scope etc. play a role as well. Is this somewhere documented? Or at least a hint, would help a lot to be aware of this pitfall. -- Robert M. Münch http://www.saphirion.com smarter | better | faster
Re: auto & class members
On 2018-05-21 18:13:16 +, Ali ehreli said: Templatized range types work well when they are used as template arguments themselves. When you need to keep a single type like 'b' (i.e. b is not a template), and when you need to set a variable like mySubStream to a dynamic object, the solution is to use inputObject(): ... Thanks for the good example. The thing in my specific case is, that the streams are from a library, so no direct way to change their interface or so. But anyway, the more background about the whole topic, the better. -- Robert M. Münch http://www.saphirion.com smarter | better | faster
Re: auto & class members
On Monday, May 21, 2018 16:05:00 Steven Schveighoffer via Digitalmars-d- learn wrote: > On 5/21/18 3:22 PM, Jonathan M Davis wrote: > > That's basically what I was suggesting that he do, but I guess that I > > wasn't clear enough. > > Well one thing that seems clear from this example -- we now have > __traits(isSame) to tell if lambdas are the same, but it looks like the > compiler doesn't subscribe to that belief... > > https://run.dlang.io/is/FW3mVq > > We should fix that... Yeah. That part of lambdas has always been a problem. My guess here is that the problem stems from the fact that they're declared in separate scopes, but I don't know. Regardless of the reason for the failure though, that example really needs to work, or most anything that cares about lambdas being the same is going to have problems. - Jonathan M Davis
Re: auto & class members
On 5/21/18 3:22 PM, Jonathan M Davis wrote: That's basically what I was suggesting that he do, but I guess that I wasn't clear enough. Well one thing that seems clear from this example -- we now have __traits(isSame) to tell if lambdas are the same, but it looks like the compiler doesn't subscribe to that belief... https://run.dlang.io/is/FW3mVq We should fix that... -Steve
Re: auto & class members
On Monday, May 21, 2018 11:13:16 Ali Çehreli via Digitalmars-d-learn wrote: > On 05/20/2018 10:46 AM, Robert M. Münch wrote: > > But I still don't understand why I can't write things explicitly but > > have to use an alias for this. > > Templatized range types work well when they are used as template > arguments themselves. > > When you need to keep a single type like 'b' (i.e. b is not a template), > and when you need to set a variable like mySubStream to a dynamic > object, the solution is to use inputObject(): > > import std.algorithm; > import std.range; > > class a { > int[] myStream = [ 1, 2, 42, 100 ]; > } > > > int myMessage = 42; > > class b { > InputRange!int mySubStream; > } > > void myFunc() { > a myA = new a(); > b myB = new b(); > > myB.mySubStream = inputRangeObject(myA.myStream.filter!(x => x == > myMessage)); > > assert(myB.mySubStream.equal([myMessage])); > } > > void main() { > myFunc(); > } > > Now, mySubStream is a range variable that satisfies the input range > interface and produces int elements. (Adjust accordingly.) You can use a > more specialized range kind other than InputRange if the actual range > supports it (e.g. ForwardRange!int, etc.): > > > http://ddili.org/ders/d.en/ranges_more.html#ix_ranges_more.inputRangeObjec > t > >https://dlang.org/phobos/std_range_interfaces.html#inputRangeObject Wow. Someone actually uses those? I don't think that I've ever seen anyone try except when they didn't understand ranges properly and thought that all ranges derived from the interfaces in that module. I guess that they would work in this case, but I think that the normal solution is to use typeof (though as Robert here found, that can get a bit problematic when lambdas get involved, whereas your solution here is pretty straightforward). I'd be _very_ leery of using ForwardRange and the like though, since they're going to have to allocate on every call to save, which gets expensive, and far too often, range-based code doesn't call save correctly, meaning that you'll often hit bugs using a forward range that's a class. Phobos is a _lot_ better about it than it used to be, but I expect that there are still a few such lingering bugs in there, and I'd expect the average range-based code to screw it up. Really, the only way to get it right is to actually test your code with reference type ranges. If all you're using is a basic input range, then those interfaces just cost you the one allocation and should be fine, but beyond that, I wouldn't suggest using them if you can reasonably avoid it. And personally, I'd just use Steven's solution of using a wrapper function so that you can ensure that there's really only one lambda type involved, and typeof then works. - Jonathan M Davis
Re: auto & class members
On Monday, May 21, 2018 14:55:36 Steven Schveighoffer via Digitalmars-d- learn wrote: > On 5/20/18 1:46 PM, Robert M. Münch wrote: > > On 2018-05-20 17:40:39 +, Robert M. Münch said: > >> Hi Jonathan, great! This got me a step further. So I can declare my > >> member now. But I get an implict cast error when I try: > >> > >> class a { > >> ... myStream; > >> } > >> > >> class b { > >> typeof(a.myStream.filter!(x => x == myMessage)) mySubStream; > >> } > >> > >> void myFunc() { > >> a myA = new a(); > >> b myB = new b(); > >> > >> myB.mySubstream = myA.myStream.filter!(x => x == myMessage); > >> } > >> > >> This gives (unnecessary stuff stripped): > >> > >> Error: cannot implicitly convert expression filter(...) of type > >> app.myFunc.filter!(x => x == myMessage) to app.b.filter!(x => x == > >> myMessage) > > > > Answering myself: Using an alias helps. > > > > alias typeof(a.myStream.filter!(x => x == myMessage)) myMessageType; > > So the issue here is that the lambda function inside myFunc is DIFFERENT > than the one inside b. They are both the same function, but with > essentially different names. > > When you use the alias, both are using the same exact lambda. > > I see you are casting now as well, which looks horrible to me -- if you > change something in your lambda now you are in for some trouble. > > What may make more sense (both for type sanity and for code reuse) is to > wrap your call to filter into one place so it can be used wherever you > need it: > > auto wrapStream(S)(S str) { return str.filter!(x => x == myMessage); } > > class b > { > typeof(wrapStream(a.init.myStream)()) mySubStream; > } > > void myFunc() { > a myA = new a; > b myB = new b; > myB.mySubstream = myA.myStream.wrapStream; > } That's basically what I was suggesting that he do, but I guess that I wasn't clear enough. - Jonathan M Davis
Re: auto & class members
On 5/20/18 1:46 PM, Robert M. Münch wrote: On 2018-05-20 17:40:39 +, Robert M. Münch said: Hi Jonathan, great! This got me a step further. So I can declare my member now. But I get an implict cast error when I try: class a { ... myStream; } class b { typeof(a.myStream.filter!(x => x == myMessage)) mySubStream; } void myFunc() { a myA = new a(); b myB = new b(); myB.mySubstream = myA.myStream.filter!(x => x == myMessage); } This gives (unnecessary stuff stripped): Error: cannot implicitly convert expression filter(...) of type app.myFunc.filter!(x => x == myMessage) to app.b.filter!(x => x == myMessage) Answering myself: Using an alias helps. alias typeof(a.myStream.filter!(x => x == myMessage)) myMessageType; So the issue here is that the lambda function inside myFunc is DIFFERENT than the one inside b. They are both the same function, but with essentially different names. When you use the alias, both are using the same exact lambda. I see you are casting now as well, which looks horrible to me -- if you change something in your lambda now you are in for some trouble. What may make more sense (both for type sanity and for code reuse) is to wrap your call to filter into one place so it can be used wherever you need it: auto wrapStream(S)(S str) { return str.filter!(x => x == myMessage); } class b { typeof(wrapStream(a.init.myStream)()) mySubStream; } void myFunc() { a myA = new a; b myB = new b; myB.mySubstream = myA.myStream.wrapStream; } -Steve
Re: auto & class members
On 05/20/2018 10:46 AM, Robert M. Münch wrote: > But I still don't understand why I can't write things explicitly but > have to use an alias for this. Templatized range types work well when they are used as template arguments themselves. When you need to keep a single type like 'b' (i.e. b is not a template), and when you need to set a variable like mySubStream to a dynamic object, the solution is to use inputObject(): import std.algorithm; import std.range; class a { int[] myStream = [ 1, 2, 42, 100 ]; } int myMessage = 42; class b { InputRange!int mySubStream; } void myFunc() { a myA = new a(); b myB = new b(); myB.mySubStream = inputRangeObject(myA.myStream.filter!(x => x == myMessage)); assert(myB.mySubStream.equal([myMessage])); } void main() { myFunc(); } Now, mySubStream is a range variable that satisfies the input range interface and produces int elements. (Adjust accordingly.) You can use a more specialized range kind other than InputRange if the actual range supports it (e.g. ForwardRange!int, etc.): http://ddili.org/ders/d.en/ranges_more.html#ix_ranges_more.inputRangeObject https://dlang.org/phobos/std_range_interfaces.html#inputRangeObject Ali
Re: auto & class members
On 2018-05-20 17:40:39 +, Robert M. Münch said: Hi Jonathan, great! This got me a step further. So I can declare my member now. But I get an implict cast error when I try: class a { ... myStream; } class b { typeof(a.myStream.filter!(x => x == myMessage)) mySubStream; } void myFunc() { a myA = new a(); b myB = new b(); myB.mySubstream = myA.myStream.filter!(x => x == myMessage); } This gives (unnecessary stuff stripped): Error: cannot implicitly convert expression filter(...) of type app.myFunc.filter!(x => x == myMessage) to app.b.filter!(x => x == myMessage) Answering myself: Using an alias helps. alias typeof(a.myStream.filter!(x => x == myMessage)) myMessageType; class b { myMessageType mySubStream; } void myFunc() { a myA = new a(); b myB = new b(); myB.mySubstream = cast(myMessageType)myA.myStream.filter!(x => x == myMessage); } But I still don't understand why I can't write things explicitly but have to use an alias for this. -- Robert M. Münch http://www.saphirion.com smarter | better | faster
Re: auto & class members
On 2018-05-20 14:49:59 +, Jonathan M Davis said: In cases like this, typeof is your friend. e.g. something like typeof(myStream.filter!(a => a == myMessage)) mySubStream; Hi Jonathan, great! This got me a step further. So I can declare my member now. But I get an implict cast error when I try: class a { ... myStream; } class b { typeof(a.myStream.filter!(x => x == myMessage)) mySubStream; } void myFunc() { a myA = new a(); b myB = new b(); myB.mySubstream = myA.myStream.filter!(x => x == myMessage); } This gives (unnecessary stuff stripped): Error: cannot implicitly convert expression filter(...) of type app.myFunc.filter!(x => x == myMessage) to app.b.filter!(x => x == myMessage) Why is myFunc now entering the game? I mean it's just the function containing the code. It seems that: typeof(myA.myStream.filter!(x => x == myMessage)) and typeof(a.myStream.filter!(x => x == myMessage)) are not the same. But inside class b I can't use a specific variable instance. And in myFunc, I can't use a class type but need the specific instance. Any further idea? though you might have trouble with the lambda being subtly different type even if you replace myMessage in it with something that will work in the scope that mySubStream is being declared. Not sure if the above problem is exactly what you mention here. This is all pretty tricky. However, that could be fixed by doing something like replacing the lambda with a free function or just creating a function that returns what you want to assign to mySubStream. Then you could just do something like typeof(myHelperFunc(myStream)) mySubStream; The exact solution can get a bit annoying in cases like this (it's arguably the biggest downside to auto returns), but typeof does provide a way out if you can get the expression to it to work. It is easier with local variables than member variables though, since you don't necessarily have everything you want to use in the expression that will give the variable its value available at the point that the variable is declared - but that's why a helper function can help, since it provides a way to encapsulate the expression and reuse it between the assignment and the declaration. Not sure I understand every aspect but it's getting clearer... Thanks so far. -- Robert M. Münch http://www.saphirion.com smarter | better | faster
Re: auto & class members
On Sunday, May 20, 2018 16:30:10 Robert M. Münch via Digitalmars-d-learn wrote: > I use the D RX lib [1] and can create a filtered stream using the auto > keyword: > > struct a { > SubjectObject!myType myStream; > ??? mySubStream; > } > > void myfunc(){ > a myA = new a(); > > auto mySubStream = a.myStream.filter!(a => a == myMessage); > ... > } > > The problem is, that I don't find out what the type of mySubStream is, > which I would like to make a member of the struct, so that I can > reference it outside the function too. > > How can I find out the type of an auto? This here seems to be a pretty > complicated templated, nested type, whatever result. > > [1] https://github.com/lempiji/rx In cases like this, typeof is your friend. e.g. something like typeof(myStream.filter!(a => a == myMessage)) mySubStream; though you might have trouble with the lambda being subtly different type even if you replace myMessage in it with something that will work in the scope that mySubStream is being declared. However, that could be fixed by doing something like replacing the lambda with a free function or just creating a function that returns what you want to assign to mySubStream. Then you could just do something like typeof(myHelperFunc(myStream)) mySubStream; The exact solution can get a bit annoying in cases like this (it's arguably the biggest downside to auto returns), but typeof does provide a way out if you can get the expression to it to work. It is easier with local variables than member variables though, since you don't necessarily have everything you want to use in the expression that will give the variable its value available at the point that the variable is declared - but that's why a helper function can help, since it provides a way to encapsulate the expression and reuse it between the assignment and the declaration. - Jonathan M Davis
Re: Auto expiring cache library
On Friday, 27 April 2018 at 09:07:31 UTC, Pasqui23 wrote: I want a library that offers an in-memory data structure,such that I can write,for example: cache.insert(key,value,expiry) and I can retrieve the value with something like cache[key],unless it has passed expiry seconds. Can be done?What library should I use? Memcached
Re: auto-decoding
On Sunday, 1 April 2018 at 02:44:32 UTC, Uknown wrote: If you want to stop auto-decoding, you can use std.string.representation like this: import std.string : representation; auto no_decode = some_string.representation; Now no_decode wont be auto-decoded, and you can use it in place of some_string. You can also use std.utf to decode by graphemes instead. .representation gives you an const(ubyte)[] What you typically want is const(char)[], for this you can use std.utf.byCodeUnit https://dlang.org/phobos/std_utf.html#byCodeUnit There's also this good article: https://tour.dlang.org/tour/en/gems/unicode
Re: auto-decoding
On Sunday, 1 April 2018 at 01:19:08 UTC, auto wrote: What is auto decoding and why it is a problem? Auto-decoding is essentially related to UTF representation of Unicode strings. In D, `char[]` and `string` represent UTF8 strings, `wchar[]` and `wstring` represent UTF16 strings and `dchar[]` and `dstring` represent UTF32 strings. You need to know how UFT works in order to understand auto-decoding. Since in practice most code deals with UTF8 I'll explain wrt that. Essentially, the problem comes down to the fact that not all the Unicode characters are representable by 8 bit `char`s (for UTF8). Only the ASCII stuff is represented by the "normal" way. UTF8 uses the fact that the first few buts in a char are never used in ASCII, to tell how many more `char`s ahead that character is encoded in. You can watch this video for a better understanding[0]. By default though, if one were to traverse a `char` looking for characters, they would get unexpected results with Unicode data Auto-decoding tries to solve this by automatically applying the algorithm to decode the characters to Unicode "Code-Points". This is where my knowledge ends though. I'll give you pros and cons of auto-decoding. Pros: * It makes Unicode string handeling much more easier for beginners. * Much less effort in general, it seems to "just work™" Cons: * It makes string handling slow by default * It may be the wrong thing, since you may not want Unicode code-points, but graphemes instead. * Auto-decoding throws exceptions on reaching invalid code-points, so all string handling code in general throws exceptions. If you want to stop auto-decoding, you can use std.string.representation like this: import std.string : representation; auto no_decode = some_string.representation; Now no_decode wont be auto-decoded, and you can use it in place of some_string. You can also use std.utf to decode by graphemes instead. You should also read this blog post: https://jackstouffer.com/blog/d_auto_decoding_and_you.html And this forum post: https://forum.dlang.org/post/eozguhavggchzzruz...@forum.dlang.org [0]: https://www.youtube.com/watch?v=MijmeoH9LT4
Re: Auto-decoding
On Saturday, 15 July 2017 at 18:47:25 UTC, Joakim wrote: On Saturday, 15 July 2017 at 18:14:48 UTC, aberba wrote: So what is the current plan? :) Andrei has talked about having a non-auto-decoding path for those who know what they're doing and actively choose that path, while keeping auto-decoding the default, so as not to break existing code. Jack has been submitting PRs for this, but it is probably tedious work, so progress is slow and I don't know how much more remains to be done: https://github.com/dlang/phobos/pulls?q=is%3Apr+auto-decoding+is%3Aclosed The idea is that once DIP1000 has matured, more focus on compiler support for reference-counting will be given with the aim of improving the @nogc experience. One example is DIP1008 for @nogc exceptions [1], but another one that is important in this context is RCString [2]. The idea is that RCString will be a new opt-in string type without auto-decoding and GC. Another idea in the game is `version(NoAutoDecode)`: https://github.com/dlang/phobos/pull/5513 However, here's unfortunately still unclear whether that could result in a working solution. [1] https://github.com/dlang/DIPs/blob/master/DIPs/DIP1008.md [2] https://github.com/dlang/phobos/pull/4878
Re: Auto-decoding
On Saturday, 15 July 2017 at 18:14:48 UTC, aberba wrote: On Saturday, 15 July 2017 at 05:54:32 UTC, ag0aep6g wrote: On 07/15/2017 06:21 AM, bauss wrote: [...] 1) Drop two elements from "Bär". With auto-decoding you get "r", which is nice. Without auto-decoding you get [0xA4, 'r'] where 0xA4 is the second half of the encoding of 'ä'. You have to know your Unicode to understand what is going on there. [...] So what is the current plan? :) Andrei has talked about having a non-auto-decoding path for those who know what they're doing and actively choose that path, while keeping auto-decoding the default, so as not to break existing code. Jack has been submitting PRs for this, but it is probably tedious work, so progress is slow and I don't know how much more remains to be done: https://github.com/dlang/phobos/pulls?q=is%3Apr+auto-decoding+is%3Aclosed
Re: Auto-decoding
On 07/15/2017 08:14 PM, aberba wrote: So what is the current plan? :) As far as I'm aware, there's no concrete plan to change anything. We just gotta deal with auto-decoding for the time being.
Re: Auto-decoding
On Saturday, 15 July 2017 at 05:54:32 UTC, ag0aep6g wrote: On 07/15/2017 06:21 AM, bauss wrote: [...] 1) Drop two elements from "Bär". With auto-decoding you get "r", which is nice. Without auto-decoding you get [0xA4, 'r'] where 0xA4 is the second half of the encoding of 'ä'. You have to know your Unicode to understand what is going on there. [...] So what is the current plan? :)
Re: Auto-decoding
On 07/15/2017 06:21 AM, bauss wrote: I understand what it is and how it works, but I don't understand anything of how it solves any problems? Could someone give an example of when auto-decoding actually is useful in contrast to not using it? 1) Drop two elements from "Bär". With auto-decoding you get "r", which is nice. Without auto-decoding you get [0xA4, 'r'] where 0xA4 is the second half of the encoding of 'ä'. You have to know your Unicode to understand what is going on there. 2) Search for 'ä' (one wchar/dchar) in the `string` "Bär". With auto-decoding, you pop the 'B' and then there's your 'ä'. Without auto-decoding, you can't find 'ä', because "Bär" doesn't have a single element that matches 'ä'. You have to search for "ä" (two `char`s) instead. The goal of auto-decoding was to make it so that you don't have to think about Unicode all the time when processing strings. Instead you could think in terms of "characters". But auto-decoding falls flat on that goal, which is why it's disliked. You still have to think about Unicode stuff for correctness (combining characters, graphemes), and now you also have to worry about the performance of auto-decoding.
Re: Auto recursive function
On Wednesday, 11 January 2017 at 19:23:10 UTC, Razvan Nitu wrote: Hi, I am currently trying to create a function makeMultidimensionalArray which allocates memory for a multidimensional array. You were very close to the answer: auto makeMultidimensionalArray(int N, T, Allocator)(auto ref Allocator alloc, size_t[N] lengths) { static if (lengths.length == 1) { return makeArray!T(alloc, lengths[0]); } else { alias E = typeof(makeMultidimensionalArray!(N-1,T)(alloc, lengths[1..$])); auto ret = makeArray!E(alloc, lengths[0]); foreach (ref e; ret) e = makeMultidimensionalArray!(N-1, T)(alloc, lengths[1..$]); return ret; } } The key point is that return type depends on length of "lengths" array (dimensionality), so if this length is only known at runtime this is a dependent type, something D lacks (you'll need Idris or Agda for those). In D return type must be known at compile time and hence the length of "lengths" must be a compile time argument. With such argument everything compiles smoothly.
Re: Auto recursive function
On Thursday, 12 January 2017 at 00:30:33 UTC, Ignacious wrote: On Wednesday, 11 January 2017 at 19:23:10 UTC, Razvan Nitu wrote: [...] If you change the return type to a void* your code basically works. void* makeMultidimensionalArray(T, Allocator)(auto ref Allocator alloc, size_t[] lengths) { if (lengths.length == 1) { int x = 0x01FEEF01; return cast(void*)makeArray!T(alloc, lengths[0], x); } else { alias E = typeof(makeMultidimensionalArray!T(alloc, lengths[1..$])); auto ret = makeArray!E(alloc, lengths[0]); foreach (ref e; ret) e = makeMultidimensionalArray!T(alloc, lengths[1..$]); return cast(void*)ret; } } The problem is that then you need to cast back and that essentially results in the original problem. Can be done but probably gonna have to use string mixins. That isn't a solution and will probably introduce other bugs. As soon as you have to result to using void* is an indication of bad design IMO, because it leads to very unsafe possibilities.
Re: Auto recursive function
On Wednesday, 11 January 2017 at 19:23:10 UTC, Razvan Nitu wrote: Hi, I am currently trying to create a function makeMultidimensionalArray which allocates memory for a multidimensional array. It is very similar with [1], the difference being that it is uninitialized. Here is the code: auto makeMultidimensionalArray(T, Allocator)(auto ref Allocator alloc, size_t[] lengths) { if (lengths.length == 1) { return makeArray!T(alloc, lengths[0]); } else { alias E = typeof(makeMultidimensionalArray!T(alloc, lengths[1..$])); auto ret = makeArray!E(alloc, lengths[0]); foreach (ref e; ret) e = makeMultidimensionalArray!T(alloc, lengths[1..$]); return ret; } } The lengths[] specifies the lengths for each dimension. The problem with this code is that auto is going to be evaluated to T[] for the first time and when it recurs, creating T[][] I get the error "mismatched function return type inference of T[][] and T[]". Is there a way to surpass that? I saw that in [1] the recursive call is done by prefixing the function name with a '.'; I tried that but it doesn't work. I must be missing something, any ideas? Thanks, RazvanN [1] https://github.com/dlang/phobos/blob/master/std/experimental/ndslice/slice.d#L834 If you change the return type to a void* your code basically works. void* makeMultidimensionalArray(T, Allocator)(auto ref Allocator alloc, size_t[] lengths) { if (lengths.length == 1) { int x = 0x01FEEF01; return cast(void*)makeArray!T(alloc, lengths[0], x); } else { alias E = typeof(makeMultidimensionalArray!T(alloc, lengths[1..$])); auto ret = makeArray!E(alloc, lengths[0]); foreach (ref e; ret) e = makeMultidimensionalArray!T(alloc, lengths[1..$]); return cast(void*)ret; } } The problem is that then you need to cast back and that essentially results in the original problem. Can be done but probably gonna have to use string mixins.
Re: Auto recursive function
On Wednesday, 11 January 2017 at 19:23:10 UTC, Razvan Nitu wrote: Hi, I am currently trying to create a function makeMultidimensionalArray which allocates memory for a multidimensional array. It is very similar with [1], the difference being that it is uninitialized. Here is the code: auto makeMultidimensionalArray(T, Allocator)(auto ref Allocator alloc, size_t[] lengths) { if (lengths.length == 1) { return makeArray!T(alloc, lengths[0]); } else { alias E = typeof(makeMultidimensionalArray!T(alloc, lengths[1..$])); auto ret = makeArray!E(alloc, lengths[0]); foreach (ref e; ret) e = makeMultidimensionalArray!T(alloc, lengths[1..$]); return ret; } } The lengths[] specifies the lengths for each dimension. The problem with this code is that auto is going to be evaluated to T[] for the first time and when it recurs, creating T[][] I get the error "mismatched function return type inference of T[][] and T[]". Is there a way to surpass that? I saw that in [1] the recursive call is done by prefixing the function name with a '.'; I tried that but it doesn't work. I must be missing something, any ideas? Thanks, RazvanN [1] https://github.com/dlang/phobos/blob/master/std/experimental/ndslice/slice.d#L834 This is probably not possible. You are trying to have multiple return types for the same function. You are thinking that each recursive call is a new template but that doesn't seem to be the case. Instead, maybe try using string mixins to generate the allocations. Should be quite easy and will work. You could also try to use a helper function that you pass the fully declared array(all dimensions) and the helper function then allocates each dimension recursively... The difference is that you are not passing around/returning sub-arrays so you don't have to worry about type mismatches.
Re: Auto recursive function
On Wednesday, 11 January 2017 at 19:39:17 UTC, Ali Çehreli wrote: return choose(lengths.length == 1, one!T(alloc, lengths[0]), two!T(alloc, lengths)); Well, choose is the right tool when the choice can only be made at runtime. That would be uncommon for dimensionality. Anyhow mentioning ndslice for multi-dim seems like the sanest tip here. https://github.com/libmir/mir
Re: Auto recursive function
On Wednesday, 11 January 2017 at 19:30:05 UTC, Stefan Koch wrote: On Wednesday, 11 January 2017 at 19:23:10 UTC, Razvan Nitu wrote: Hi, I am currently trying to create a function makeMultidimensionalArray which allocates memory for a multidimensional array. It is very similar with [1], the difference being that it is uninitialized. Here is the code: [...] I believe you should not do this with recursion. Because that'll instantiate the template multiple times with different types. What is wrong with using ndslice here ? Maybe you want to allocate memory for more complex data structures; Using the function I am implementing, you will have the multidimensional array initialized with the default values; you don't have to pass a slice from which the initialization data is taken.
Re: Auto recursive function
On 01/11/2017 11:30 AM, Stefan Koch wrote: On Wednesday, 11 January 2017 at 19:23:10 UTC, Razvan Nitu wrote: Hi, I am currently trying to create a function makeMultidimensionalArray which allocates memory for a multidimensional array. It is very similar with [1], the difference being that it is uninitialized. Here is the code: [...] I believe you should not do this with recursion. Because that'll instantiate the template multiple times with different types. What is wrong with using ndslice here ? Agreed but the question is still valid. I had similar cases before where std.range.choose looked like a solution but did not work. Here's my current attempt, which fails: import std.stdio; import std.experimental.allocator.gc_allocator; import std.experimental.allocator; auto one(T, Allocator)(auto ref Allocator alloc, size_t length) { return makeArray!T(alloc, length); } auto two(T, Allocator)(auto ref Allocator alloc, size_t[] lengths) { // Error: forward reference to inferred return type of function call 'makeMultidimensionalArray!int(alloc, lengths[1..__dollar])' alias E = typeof(makeMultidimensionalArray!T(alloc, lengths[1..$])); auto ret = makeArray!E(alloc, lengths[0]); foreach (ref e; ret) e = makeMultidimensionalArray!T(alloc, lengths[1..$]); return ret; } auto makeMultidimensionalArray(T, Allocator)(auto ref Allocator alloc, size_t[] lengths) { import std.range: choose; return choose(lengths.length == 1, one!T(alloc, lengths[0]), two!T(alloc, lengths)); } void main() { writeln(makeMultidimensionalArray!int(GCAllocator.instance, [3, 4])); } Ali
Re: Auto recursive function
On Wednesday, 11 January 2017 at 19:23:10 UTC, Razvan Nitu wrote: auto makeMultidimensionalArray(T, Allocator)(auto ref Allocator alloc, size_t[] lengths) { if (lengths.length == 1) Looks like `static if` would fix your specific problem.
Re: Auto recursive function
On Wednesday, 11 January 2017 at 19:23:10 UTC, Razvan Nitu wrote: Hi, I am currently trying to create a function makeMultidimensionalArray which allocates memory for a multidimensional array. It is very similar with [1], the difference being that it is uninitialized. Here is the code: [...] I believe you should not do this with recursion. Because that'll instantiate the template multiple times with different types. What is wrong with using ndslice here ?
Re: Auto field member?
On 02/03/16 3:50 PM, Hanh wrote: Hi, Is there a way to declare a class field 'auto'? I have a problem when I try to 'promote' a variable to a field. import std.csv; import std.typecons; class Test { this() { auto text = "Joe,Carpenter,30\nFred,Blacksmith,40\r\n"; auto reader = csvReader!(Tuple!(string, string, int))(text); // how to make this a field? } } csvReader returns a private type so I can't specify the type explicitly. Thanks, --h You have two options. a) parse and store into your own data structure. b) use std.traits ReturnType to get the type to declare.
Re: Auto ref function : How is this possible ?
On 04/15/2015 10:50 AM, Ali Çehreli wrote: pragma(msg) has been added to Programming in D but it is not available online yet: Sorry for the spam :( but apparently it is already online: http://ddili.org/ders/d.en/templates.html#ix_templates.pragma Ali
Re: Auto ref function : How is this possible ?
On 04/13/2015 07:44 AM, matovitch wrote: Thanks for the tip ! I was looking at something like this. pragma(msg) has been added to Programming in D but it is not available online yet: https://bitbucket.org/acehreli/ddili/src/ae49747a850fabc3a3e66dcdb3626a991c53632e/src/ders/d.en/templates.d?at=master#cl-696 Ali
Re: Auto ref function : How is this possible ?
Thanks for the tip ! I was looking at something like this.
Re: Auto ref function : How is this possible ?
On 4/11/15 6:08 AM, matovitch wrote: Hi, I just learn about auto ref functions and tried this : import std.stdio; auto ref foo(int i, ref float f) { if (i f) { return i; } else { return f; } } void main() { int i = 1; float f1 = 1.1; float f2 = 0.9; writeln(foo(i, f1)); writeln(foo(i, f2)); } Tricky questions : Does it compiles ? If yes what does it do ? Then my question : How is this possible ? D has great compile-time tools to examine what the compiler is doing. A great feature of D for investigating compiler internals is pragma(msg, ...). This prints at compile time some message (a string) that is based on the state at the time. For example: void main() { int i = 1; float f1 = 1.1; float f2 = 0.9; pragma(msg, typeof(foo(i, f1)).stringof); // prints what type foo returns auto x = foo(i, f2); pragma(msg, typeof(x).stringof); // same thing, but easier to understand. } result (prints while compiling): float float -Steve
Re: Auto ref function : How is this possible ?
In fact I am now thinking it's great...I tried with string instead of float and got a clear error message. I should have read the spec more thoroughly.
Re: Auto ref function : How is this possible ?
(you can remove the ref stuff)
Re: Auto ref function : How is this possible ?
Ok this explain it : http://dlang.org/function.html#auto-functions. It should return a float.
Re: auto function attributes based on type
On Thu, 12 Mar 2015 04:51:40 +, amber wrote: On Thursday, 12 March 2015 at 04:04:28 UTC, weaselcat wrote: On Thursday, 12 March 2015 at 03:12:15 UTC, amber wrote: ... http://dlang.org/function.html#function-attribute-inference might be a good read if you haven't read it already. I did read it but didn't really understand it, so I've come to D.learn for more help. I think it means I can just write the function like so: struct S(T) { someFunc(int i) {// impl} } and if possible it will be pure, nothrow, @safe and @nogc. yes. all templated functions (and `someFunc()` is templated due to `S` being templated) are subjects of attribute inference. due to this fact people sometimes writing even free functions as argument-less templates, void freeFunc() (...) { ... } so compiler will infer attributes for `freeFunc()`. this has almost no cost, as compiler will merge all produced templates into one. signature.asc Description: PGP signature
Re: auto function attributes based on type
On Thursday, 12 March 2015 at 05:01:50 UTC, amber wrote: On Thursday, 12 March 2015 at 04:51:42 UTC, amber wrote: On Thursday, 12 March 2015 at 04:04:28 UTC, weaselcat wrote: On Thursday, 12 March 2015 at 03:12:15 UTC, amber wrote: ... http://dlang.org/function.html#function-attribute-inference might be a good read if you haven't read it already. I did read it but didn't really understand it, so I've come to D.learn for more help. I think it means I can just write the function like so: struct S(T) { someFunc(int i) {// impl} } and if possible it will be pure, nothrow, @safe and @nogc. thanks, amber This works nicely after checking with __traits(getFunctionAttributes, S!T.someFunc) Very cool :) bye, amber You can also use the __PRETTY_FUNCTION__ keyword to display information about a function. http://dlang.org/traits.html#specialkeywords
Re: auto function attributes based on type
On Thursday, 12 March 2015 at 03:12:15 UTC, amber wrote: ... http://dlang.org/function.html#function-attribute-inference might be a good read if you haven't read it already.
Re: auto function attributes based on type
On Thursday, 12 March 2015 at 04:04:28 UTC, weaselcat wrote: On Thursday, 12 March 2015 at 03:12:15 UTC, amber wrote: ... http://dlang.org/function.html#function-attribute-inference might be a good read if you haven't read it already. I did read it but didn't really understand it, so I've come to D.learn for more help. I think it means I can just write the function like so: struct S(T) { someFunc(int i) {// impl} } and if possible it will be pure, nothrow, @safe and @nogc. thanks, amber
Re: auto function attributes based on type
On Thursday, 12 March 2015 at 04:51:42 UTC, amber wrote: On Thursday, 12 March 2015 at 04:04:28 UTC, weaselcat wrote: On Thursday, 12 March 2015 at 03:12:15 UTC, amber wrote: ... http://dlang.org/function.html#function-attribute-inference might be a good read if you haven't read it already. I did read it but didn't really understand it, so I've come to D.learn for more help. I think it means I can just write the function like so: struct S(T) { someFunc(int i) {// impl} } and if possible it will be pure, nothrow, @safe and @nogc. thanks, amber This works nicely after checking with __traits(getFunctionAttributes, S!T.someFunc) Very cool :) bye, amber
Re: Auto-add static field when inherit // mixins, templates?
class A { string getName(this Klass)() { return Klass.stringof; } } class B : A {} void main() { import std.stdio; auto a = new A; auto b = new B; writeln(a.getName()); writeln(b.getName()); } ## This is about as close as you're going to get without some hackery.
Re: Auto-add static field when inherit // mixins, templates?
I found a rough solution. It's not ideal and I still want to make autoinject, but it works. mixin template Manager(T) {}; class Component {}; class Sprite:Component { mixin Manager!Sprite; }; 1) How to make mixin inject automatic? 2) If it's impossible, how to use mixin Manager; without !Sprite ? mixin template Manager(this T) {}; isn't working. Regards, Alex On Thursday, 21 August 2014 at 09:38:13 UTC, MarisaLovesUsAll wrote: tl;dr - how to get child classname from inherited parent function at compile time? class A { string getName(); }; class B { }; B foo = new B; assert(foo.getName() == B); ... Hi! I'm stuck at one issue, and I don't know how to solve it. I think this is about mixins/templates, isn't it? When inherit from base class Component, I need to auto-create child own static fields with child type. It should look like this, after compilation: class Component { //it doesn't matter to have any fields here //but it's important to be able to create an instance of Component //and when inherit, all childs will get their own static T list; where T is a type of child. }; class Sprite:Component { static Sprite list; //auto-added static void fun() { } //auto-added, operates with Sprite } class Camera:Component { static Camera list; //auto-added static void fun() { } //auto-added, operates with Camera instead of Sprite } ... //so this must be correct: Component foo; Sprite bar; void foobar(Component one) { } foobar(Sprite); ... Sorry for bad English. Best regards, Alex
Re: Auto-add static field when inherit // mixins, templates?
On Thursday, 21 August 2014 at 12:58:13 UTC, MarisaLovesUsAll wrote: I found a rough solution. It's not ideal and I still want to make autoinject, but it works. mixin template Manager(T) {}; class Component {}; class Sprite:Component { mixin Manager!Sprite; }; 1) How to make mixin inject automatic? You could use this pattern: interface Component {} class ComponentImpl(T) {} class Sprite : ComponentImpl!Sprite {} It's not 100% automatic, but the duplication of Sprite is in the same line. And it's not as easy to forget as a mixin, especially when Component does declare methods that ComponentImpl implements. 2) If it's impossible, how to use mixin Manager; without !Sprite ? mixin template Manager(this T) {}; isn't working. You can use `typeof(this)` in Manager: mixin template Manager() { void someMethod(typeof(this) otherInstance) {} }
Re: Auto-add static field when inherit // mixins, templates?
On Thursday, 21 August 2014 at 13:19:06 UTC, anonymous wrote: 1) How to make mixin inject automatic? You could use this pattern: interface Component {} class ComponentImpl(T) {} class Sprite : ComponentImpl!Sprite {} From my view, it's an architectural crutch. %) You can use `typeof(this)` in Manager: mixin template Manager() { void someMethod(typeof(this) otherInstance) {} } Thanks, it works. ...I also have more questions %) When I make mixin injection in one class, I want auto-injection in another class. How can I do this? class Component:GameObject { //second injection must be here and must be automatic }; class Sprite:Component { mixin Manager; //first injection must activate second injection by misterious way }; mixin template Manager() {} mixin template ComponentCaster(string type) {} //where 'type' is a type obtained from Manager //by typeof(this).stringof. As example, Sprite. ...compile-time code generation is pain %) I think, it will be 50 times easier if we have built-in compiler script language. Or just a library that will be able to execute code in compile time. Sorry for Engrish. Regards, Alex
Re: Auto-add static field when inherit // mixins, templates?
On 8/21/14, 6:38 AM, MarisaLovesUsAll wrote: tl;dr - how to get child classname from inherited parent function at compile time? class A { string getName(); }; class B { }; B foo = new B; assert(foo.getName() == B); ... Hi! I'm stuck at one issue, and I don't know how to solve it. I think this is about mixins/templates, isn't it? When inherit from base class Component, I need to auto-create child own static fields with child type. It should look like this, after compilation: class Component { //it doesn't matter to have any fields here //but it's important to be able to create an instance of Component //and when inherit, all childs will get their own static T list; where T is a type of child. }; class Sprite:Component { static Sprite list; //auto-added static void fun() { } //auto-added, operates with Sprite } class Camera:Component { static Camera list; //auto-added static void fun() { } //auto-added, operates with Camera instead of Sprite } ... //so this must be correct: Component foo; Sprite bar; void foobar(Component one) { } foobar(Sprite); ... Sorry for bad English. Best regards, Alex I'll tell you how it's done in Crystal in case someone wants to come up with a proposal to make it work in D. ~~~ class Foo macro inherited def method_in_{{@class_name.downcase.id}} puts Hello {{@class_name.id}}! end end end class Bar Foo end Bar.new.method_in_bar #= Hello Bar! ~~~ When you inherit a class, the macro inherited is automatically executed by the compiler in the context of the inheriting class. There you can use special variables like @class_name and interpolate them with {{ ... }}. I guess a similar thing to do in D would be to define a function to be executed at compile time and automatically mix it, and the context of execution would be the inherited class. (sorry if this is of no interest to all of you, let me know if I should stop trying to bring ideas to D from other languages)
Re: Auto-add static field when inherit // mixins, templates?
On Thursday, 21 August 2014 at 19:58:18 UTC, MarisaLovesUsAll wrote: When I make mixin injection in one class, I want auto-injection in another class. How can I do this? class Component:GameObject { //second injection must be here and must be automatic }; class Sprite:Component { mixin Manager; //first injection must activate second injection by misterious way }; I don't think this is possible. mixin template Manager() {} mixin template ComponentCaster(string type) {} //where 'type' is a type obtained from Manager //by typeof(this).stringof. As example, Sprite. Maybe you can explain what you're trying to achieve with all this. There may be a different/better way to do it.
Re: Auto-add static field when inherit // mixins, templates?
On Thursday, 21 August 2014 at 20:05:13 UTC, Ary Borenszweig wrote: I'll tell you how it's done in Crystal in case someone wants to come up with a proposal to make it work in D. ~~~ class Foo macro inherited def method_in_{{@class_name.downcase.id}} puts Hello {{@class_name.id}}! end end end class Bar Foo end Bar.new.method_in_bar #= Hello Bar! ~~~ I think such a feature would clash with a D principle: A base class (Foo) cannot know about (or depend on) all its subclasses (Bar), because it may be compiled separately from them. Now, if it were only about printing the most derived class name (I know, it isn't), you could that in D with typeid: import std.stdio; class Foo { void whoami() { writeln(typeid(this)); } } class Bar : Foo {} void main() { Foo f = new Bar; f.whoami(); }
Re: Auto-add static field when inherit // mixins, templates?
On Thursday, 21 August 2014 at 20:16:33 UTC, anonymous wrote: Maybe you can explain what you're trying to achieve with all this. There may be a different/better way to do it. Sure. Class tree: GameObject-Component-Sprite. GameObject structure: Component[]; Component addComponent(Component component); First feature is Components Manager. It's an array and register()/remove() functions, just like in GameObject, but it's static and unique to all inherited classes. static T[] list; static void register(T obj); static void remove(T obj); So, if I do this class Sprite:Component {}; 'T' becomes 'Sprite', and Manager functionality adds to class. It also will be able to create instance of class Component because of Components list in GameObject. And Component type must be one because it's easier to use one name for inheritance and for storing Components. I did this by mixins, but it's not automatic. And second feature. When I create Sprite and add it in GameObject, there will be no 'cast(Sprite)' constructions; type of return value must be argument's type. Code: Component addComponent(Component component); Sprite shell = cast(Sprite) this.addComponent(new Sprite(shell_1.png)); //I want remove 'cast(Sprite)' from here I found a solution for one class: class Component { Sprite toSprite() @property { return cast(Sprite) this; } alias toSprite this; } And it works. Now I want to add this solution in class Component, working with all inherited classes. As I realize, this is rough and impossible, and I need to do some template magic in GameObject code. Sorry for Engrish. Regards, Alex
Re: Auto attributes for functions
On Wed, 20 Aug 2014 01:38:52 + uri via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: Hi all, Bit new to D so this might be a very naive question... Can the compiler auto infer function attributes? I am often adding as many attributes as possible and use the compiler to show me where they're not applicable and take them away. It would be great if this could be achieved like so: auto function() @auto {} instead of manually writing: auto function() pure @safe nothrow @nogc const {} Currently, just templated functions get their attributes inferred. The biggest problem with inferring them for all functions is that you can declare a function without defining it in the same place (e.g. if you're using .di files), in which case the compiler has no function body to use for attribute inferrence. There have been discussions on ways to reasonably infer attributes under more circumstances, but nothing has come of them yet. However, I'd expect that there will be at least some improvements to the situation at some point given that there is a general consensus that while the attributes are quite useful, it's also rather annoying to have to keep typing them all. - Jonathan M Davis
Re: Auto attributes for functions
On Wednesday, 20 August 2014 at 09:13:15 UTC, Jonathan M Davis via Digitalmars-d-learn wrote: On Wed, 20 Aug 2014 01:38:52 + uri via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: Hi all, Bit new to D so this might be a very naive question... Can the compiler auto infer function attributes? I am often adding as many attributes as possible and use the compiler to show me where they're not applicable and take them away. It would be great if this could be achieved like so: auto function() @auto {} instead of manually writing: auto function() pure @safe nothrow @nogc const {} Currently, just templated functions get their attributes inferred. The biggest problem with inferring them for all functions is that you can declare a function without defining it in the same place (e.g. if you're using .di files), in which case the compiler has no function body to use for attribute inferrence. There have been discussions on ways to reasonably infer attributes under more circumstances, but nothing has come of them yet. However, I'd expect that there will be at least some improvements to the situation at some point given that there is a general consensus that while the attributes are quite useful, it's also rather annoying to have to keep typing them all. - Jonathan M Davis Thanks guys for the info. /uri
Re: Auto attributes for functions
On Wednesday, 20 August 2014 at 01:38:53 UTC, uri wrote: Hi all, Bit new to D so this might be a very naive question... Can the compiler auto infer function attributes? I am often adding as many attributes as possible and use the compiler to show me where they're not applicable and take them away. It would be great if this could be achieved like so: auto function() @auto {} instead of manually writing: auto function() pure @safe nothrow @nogc const {} cheers, uri Only if they're template functions. //inferred as @safe pure nothrow @nogc auto fun()() {} //Compiler treats this is @system impure throwing @gc //(if the latter three existed) auto fun() {} I think Andrei suggested in the past that functions with a return type of auto have attributes inferred for them as well, but some people were against it, and nobody's tried implementing it yet.
Re: auto ref function parameters in a free function
On Sunday, 3 August 2014 at 19:07:32 UTC, Vlad Levenfeld wrote: This doesn't work: bool less_than (T)(auto ref T a, auto ref T b) { return a b; } Error: auto can only be used for template function parameters What am I doing wrong? Is this not a template function? I think you can just skip 'auto'. Have a look at http://dlang.org/function.html , especially the function parameters section.