digitalmars.D.learn - varargs when they're not all the same type?
- Andy Valencia (13/13) Mar 14 Can somebody give me a starting point for understanding varadic
- monkyyy (8/21) Mar 14 there are 3 (or 4?) variadic functions
- H. S. Teoh (19/32) Mar 14 [...]
- Andy Valencia (6/10) Mar 14 Thank you. The first parenthetical list is of types, is it not?
- Basile B. (21/32) Mar 14 Most of the time the variadic template parameters are infered
- Andy Valencia (5/10) Mar 14 Which statement leads me to section 77.2 of "Programming in D",
- Andy Valencia (17/20) Mar 16 As some fruits of my labors here, below is a link to a "fmt"
- H. S. Teoh (21/32) Mar 14 [...]
Can somebody give me a starting point for understanding varadic functions? I know that we can declare them int[] args... and pick through whatever the caller provided. But if the caller wants to pass two int's and a _string_? That declaration won't permit it. I've looked into the formatter, and also the varargs implementation. But it's a bit of a trip through a funhouse full of mirrors. Can somebody describe the basic language approach to non-uniform varargs, and then I can take it the rest of the way reading the library. Thanks in advance! Andy
Mar 14
On Thursday, 14 March 2024 at 17:57:21 UTC, Andy Valencia wrote:Can somebody give me a starting point for understanding varadic functions? I know that we can declare them int[] args... and pick through whatever the caller provided. But if the caller wants to pass two int's and a _string_? That declaration won't permit it. I've looked into the formatter, and also the varargs implementation. But it's a bit of a trip through a funhouse full of mirrors. Can somebody describe the basic language approach to non-uniform varargs, and then I can take it the rest of the way reading the library. Thanks in advance! Andythere are 3 (or 4?) variadic functions try ```d auto foo(T...)(T args){ static foreach(arg;args){ ... ```
Mar 14
On Thu, Mar 14, 2024 at 05:57:21PM +0000, Andy Valencia via Digitalmars-d-learn wrote:Can somebody give me a starting point for understanding varadic functions? I know that we can declare them int[] args... and pick through whatever the caller provided. But if the caller wants to pass two int's and a _string_? That declaration won't permit it. I've looked into the formatter, and also the varargs implementation. But it's a bit of a trip through a funhouse full of mirrors. Can somebody describe the basic language approach to non-uniform varargs, and then I can take it the rest of the way reading the library.[...] The best way to do multi-type varags in D is to use templates: import std; void myFunc(Args...)(Args args) { foreach (i, arg; args) { writefln("parameter %d is a %s with value %s", i, typeof(arg), arg); } } void main() { myFunc(123, 3.14159, "blah blah", [ 1, 2, 3 ], new Object()); } D also supports C-style varags (without templates), but it's not recommended because it's not type-safe. You can find the description in the language docs. T -- "Maybe" is a strange word. When mom or dad says it it means "yes", but when my big brothers say it it means "no"! -- PJ jr.
Mar 14
On Thursday, 14 March 2024 at 18:05:59 UTC, H. S. Teoh wrote:... The best way to do multi-type varags in D is to use templates: import std; void myFunc(Args...)(Args args) {Thank you. The first parenthetical list is of types, is it not? I can't find anywhere which says what "type" is inferred for "Args..."? (gdb pretends like "arg" is not a known symbol.) Is it basically a tuple of the suitable type? Andy
Mar 14
On Thursday, 14 March 2024 at 20:58:21 UTC, Andy Valencia wrote:On Thursday, 14 March 2024 at 18:05:59 UTC, H. S. Teoh wrote:Most of the time the variadic template parameters are infered from the run time parameters. In that case indeed `Args` will be a type tuple of `args` types. ```d void myFunc(Args...)(Args args) {} myFunc(0,0.1); // is like the more verbose `myFunc!(int,double)(0,0.1)` ``` However explicit instantiation can take whatever is known at compile time, such as constant expressions or even certain static variables. So that is rather called an `alias sequence` in D. That being said and with the signature of `myFunc` that will effectively only work if `Args` is made of types. About debugging, each individual runtime arg can be inspected using a bit of knowledge of D internals. ![](https://i.imgur.com/XW74nke.png) As you can see the elements are named following this pattern `__param_[0-9]+`. So with gdb used as CLI, `$ p __param_0` will (🤞🤞) print the first variadic element, and so on.... The best way to do multi-type varags in D is to use templates: import std; void myFunc(Args...)(Args args) {Thank you. The first parenthetical list is of types, is it not? I can't find anywhere which says what "type" is inferred for "Args..."? (gdb pretends like "arg" is not a known symbol.) Is it basically a tuple of the suitable type? Andy
Mar 14
On Thursday, 14 March 2024 at 23:13:51 UTC, Basile B. wrote:... However explicit instantiation can take whatever is known at compile time, such as constant expressions or even certain static variables. So that is rather called an `alias sequence` in D.Which statement leads me to section 77.2 of "Programming in D", and now I am deep into the mechanisms behind what you have very kindly shared. Thank you once more. Andy
Mar 14
On Friday, 15 March 2024 at 00:11:11 UTC, Andy Valencia wrote: (varargs & friends)Which statement leads me to section 77.2 of "Programming in D", and now I am deep into the mechanisms behind what you have very kindly shared. Thank you once more.As some fruits of my labors here, below is a link to a "fmt" module which does C-style formatting. It supports int/long signed/unsigned, right/left padding and zero padding, plus strings (w. padding). It's memory and type safe; I ended up using unions to tabulate the arguments as I need to access them as an array (rather than walking them--I'm walking the format string instead). It adds 6k to an executable, which means dlang will work out fine for all of my smaller scripting needs in the future. Calls look like: auto s = fmt("%d %u - %20s", 123, 456, "Hi, Mom"); https://sources.vsta.org:7100/dlang/file?name=fmt.d&ci=tip Comments are welcome! I'd post here, but it seems a little long for that? Andy
Mar 16
On Thu, Mar 14, 2024 at 08:58:21PM +0000, Andy Valencia via Digitalmars-d-learn wrote:On Thursday, 14 March 2024 at 18:05:59 UTC, H. S. Teoh wrote:[...] The first set of parenthesis specify compile-time arguments. The specification `Args...` means "zero or more types". So it could be any list of types, which naturally would be chosen according to the arguments given. For example, to pass an int and a float, you'd do something like: myFunc!(int, float)(123, 3.14159f); and to pass a string, two ints, and a char, you'd write: myFunc!(string, int, int, char)("abc", 123, 456, 'z'); Having to specify types manually, of course, is a lot of unnecessary typing, since the compiler already knows what the types are based on what you write in the second pair of parentheses. For this reason, typical D code will omit the first pair of parentheses (the `!(...)`, that is, the compile-time arguments) and just let the compiler infer the types automatically: myFunc(123, 3.14159f); // compiler figures out Args = (int, float) myFunc("abc", 123, 456, 'z'); // compiler figures out Args = (string, int, int, char) T -- A program should be written to model the concepts of the task it performs rather than the physical world or a process because this maximizes the potential for it to be applied to tasks that are conceptually similar and, more important, to tasks that have not yet been conceived. -- Michael B. Allen... The best way to do multi-type varags in D is to use templates: import std; void myFunc(Args...)(Args args) {Thank you. The first parenthetical list is of types, is it not? I can't find anywhere which says what "type" is inferred for "Args..."? (gdb pretends like "arg" is not a known symbol.) Is it basically a tuple of the suitable type?
Mar 14