Jump to page: 1 2 3
Thread overview
iota to array
Feb 25, 2018
psychoticRabbit
Feb 25, 2018
Jonathan M Davis
Feb 25, 2018
psychoticRabbit
Feb 25, 2018
Uknown
Feb 25, 2018
Jonathan M Davis
Feb 25, 2018
psychoticRabbit
Feb 25, 2018
rumbu
Feb 25, 2018
psychoticRabbit
Feb 25, 2018
Andrea Fontana
Feb 25, 2018
psychoticRabbit
Feb 26, 2018
psychoticRabbit
Feb 27, 2018
H. S. Teoh
Feb 27, 2018
psychoticRabbit
Feb 27, 2018
H. S. Teoh
Feb 27, 2018
Jonathan M Davis
Feb 27, 2018
Jonathan M Davis
Feb 27, 2018
H. S. Teoh
Feb 25, 2018
rumbu
Feb 26, 2018
Harry
Feb 25, 2018
H. S. Teoh
Feb 27, 2018
Jonathan M Davis
Feb 27, 2018
H. S. Teoh
Feb 25, 2018
Seb
February 25, 2018
Hi. Anyone know whether something like this is possible?

I've tried various conversions/casts, but no luck yet.

Essentially, I want to cast the result set of the iota to an array, during initialisation of the variable.

no, I don't want to use 'auto'. I want an array object ;-)

--------------
module test;

import std.stdio;
import std.range : iota;

void main()
{
    int[] intArr = iota(1, 11); // 1..10
    double[] doubleArr = iota(1.0, 11.0); // 1.0..10.0
    char[] charArr = iota('a', '{');  // a..z
}
-------------

February 24, 2018
On Sunday, February 25, 2018 05:24:54 psychoticRabbit via Digitalmars-d- learn wrote:
> Hi. Anyone know whether something like this is possible?
>
> I've tried various conversions/casts, but no luck yet.
>
> Essentially, I want to cast the result set of the iota to an array, during initialisation of the variable.
>
> no, I don't want to use 'auto'. I want an array object ;-)
>
> --------------
> module test;
>
> import std.stdio;
> import std.range : iota;
>
> void main()
> {
>      int[] intArr = iota(1, 11); // 1..10
>      double[] doubleArr = iota(1.0, 11.0); // 1.0..10.0
>      char[] charArr = iota('a', '{');  // a..z
> }
> -------------

As with any range, you can call std.array.array to convert it to an array. So, you can have:

    int[] intArr = iota(1, 11).array();

or more idiomatically:

    auto intArr = iota(1, 11).array();

And auto does _not_ mean that it's not an array. It just means that the type is inferred, which is pretty much required when you're dealing with ranges, because the range types get a bit disgusting to type even if they're not Voldemort types, and if they are Voldemort types, then you pretty much have to use auto, since you can't refer to the type by name. But in general, even when you know exactly what the type is, it's good practice to use auto, since then you're avoiding repeating the type, and it makes it so that you don't have to change as much code later if the type of the variable changes. The classic example of where auto should be used when you know exactly what the type is would be with new. e.g.

    MyClass c = new MyClass;

is unnecessarily redundant, and

    auto c = new MyClass;

is preferred. In your case, providing the type isn't redundant, since the type isn't listed on the right-hand side of the expression, but it's still unnecessary to list the type, so auto is generally preferred - though obviously, if you really want to be explicit about the types everywhere, there's nothing stopping you from doing so. It just makes the code harder to maintain if the type ever changes.

- Jonathan M Davis

February 25, 2018
On Sunday, 25 February 2018 at 05:24:54 UTC, psychoticRabbit wrote:
> Hi. Anyone know whether something like this is possible?
>
> I've tried various conversions/casts, but no luck yet.
>
> Essentially, I want to cast the result set of the iota to an array, during initialisation of the variable.

You can't do that, because iota is a range and only exists as a range struct on the stack.
Think about it as a struct with three variables (start, end, stepSize) - not as an array.
Of course, iota is a lot smarter than that as things like  `10.iota[3 .. $]` or `3 in 10.iota` work, but it's important to notice that e.g. `iota[1 .. 2]` just returns a new range object. No GC allocation happens here and "the array" never actually exists in memory.

> no, I don't want to use 'auto'. I want an array object ;-)

This has nothing to do with auto. Auto is just a filler word for the compiler that says: "whatever is the type of the declaration, use this as the type".
In other words, the compiler does this automatically for you:

---
typeof(10.iota) r = 10.iota;
---

Anyhow it looks like what you want to do is to __allocate__ an array. You can do so with std.array.array.

---
import std.array, std.range;
void main()
{
   int[] arr = 10.iota.array;
}
---

https://run.dlang.io/is/kKSzjH

Again, notice that the actual implementation of array is this (in the non-optimized case):

---
auto array(Range)(Range r)
{
    auto a = appender!(E[])(); // <- allocation happens in the appender
    foreach (e; r)
        a.put(e);
    return a.data;
}
---

(without constraints for simplicity)

Of course, Phobos has a more sophisticated version of std.array.array, but it's basically like this:

https://github.com/dlang/phobos/blob/master/std/array.d#L97

> --------------
> module test;
>
> import std.stdio;
> import std.range : iota;
>
> void main()
> {
>     int[] intArr = iota(1, 11); // 1..10
>     double[] doubleArr = iota(1.0, 11.0); // 1.0..10.0
>     char[] charArr = iota('a', '{');  // a..z
> }
> -------------


February 25, 2018
On Sunday, 25 February 2018 at 05:40:19 UTC, Jonathan M Davis wrote:
>
>     int[] intArr = iota(1, 11).array();
>
>
> - Jonathan M Davis

thanks!

oh man.  It's so easy to do stuff in D ;-)

But this leads me to a new problem now.

When I run my code below, I get ints printed instead of doubles??

---------------------
module test;

import std.stdio : writeln;
import std.traits : isArray;
import std.array : array;
import std.range : iota;


void main()
{
    int[] intArr = iota(1, 11).array(); // 1..10
    double[] doubleArr = iota(1.0, 11.0).array(); // 1.0..10.0
    char[] charArr = iota('a', '{').array();  // a..z

    printArray(intArr);
    printArray(doubleArr); // why is it printing ints instead of doubles??
    printArray(charArr);
}

void printArray(T)(const ref T[] a) if (isArray!(T[]))
{
    foreach(t; a)
        writeln(t);
}

---------------------------------
February 25, 2018
On Sunday, 25 February 2018 at 06:22:03 UTC, psychoticRabbit wrote:
> On Sunday, 25 February 2018 at 05:40:19 UTC, Jonathan M Davis wrote:
>>
>>     int[] intArr = iota(1, 11).array();
>>
>>
>> - Jonathan M Davis
>
> thanks!
>
> oh man.  It's so easy to do stuff in D ;-)
>
> But this leads me to a new problem now.
>
> When I run my code below, I get ints printed instead of doubles??
>
> ---------------------
> module test;
>
> import std.stdio : writeln;
> import std.traits : isArray;
> import std.array : array;
> import std.range : iota;
>
>
> void main()
> {
>     int[] intArr = iota(1, 11).array(); // 1..10
>     double[] doubleArr = iota(1.0, 11.0).array(); // 1.0..10.0
>     char[] charArr = iota('a', '{').array();  // a..z
>
>     printArray(intArr);
>     printArray(doubleArr); // why is it printing ints instead of doubles??
>     printArray(charArr);
> }
>
> void printArray(T)(const ref T[] a) if (isArray!(T[]))
> {
>     foreach(t; a)
>         writeln(t);
> }
>
> ---------------------------------

2 Things:
1. You can just use writeln to directly print Arrays. If you want a specific format for the array you can use writef/writefln
2. By default, writeln will print [1, 2, 3] when your array contains [1.0, 2.0, 3.0], since thats considered neater. You can use writefln to address that. You can see this here: https://run.dlang.io/is/bNxIsH

You can read more about format strings here:
https://dlang.org/phobos/std_format.html#format-string
February 24, 2018
On Sunday, February 25, 2018 06:22:03 psychoticRabbit via Digitalmars-d- learn wrote:
> On Sunday, 25 February 2018 at 05:40:19 UTC, Jonathan M Davis
>
> wrote:
> >     int[] intArr = iota(1, 11).array();
> >
> > - Jonathan M Davis
>
> thanks!
>
> oh man.  It's so easy to do stuff in D ;-)
>
> But this leads me to a new problem now.
>
> When I run my code below, I get ints printed instead of doubles??
>
> ---------------------
> module test;
>
> import std.stdio : writeln;
> import std.traits : isArray;
> import std.array : array;
> import std.range : iota;
>
>
> void main()
> {
>      int[] intArr = iota(1, 11).array(); // 1..10
>      double[] doubleArr = iota(1.0, 11.0).array(); // 1.0..10.0
>      char[] charArr = iota('a', '{').array();  // a..z
>
>      printArray(intArr);
>      printArray(doubleArr); // why is it printing ints instead of
> doubles??
>      printArray(charArr);
> }
>
> void printArray(T)(const ref T[] a) if (isArray!(T[]))
> {
>      foreach(t; a)
>          writeln(t);
> }
>
> ---------------------------------

It's not printing ints. It's printing doubles. It's just that all of the doubles have nothing to the right of the decimal point, so they don't get printed with a decimal point. If you did something like start with 1.1, then you'd see decimal points, because there would be data to the right of the decimal point. The same thing happens if you do

writeln(1.0);

as opposed to something like

writeln(1.3);

BTW, you can just call writeln on the array directly, and then you'll get something like

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

- Jonathan M Davis

February 24, 2018
On Sun, Feb 25, 2018 at 06:22:03AM +0000, psychoticRabbit via Digitalmars-d-learn wrote: [..]
>     printArray(doubleArr); // why is it printing ints instead of doubles??
[...]
> void printArray(T)(const ref T[] a) if (isArray!(T[]))
> {
>     foreach(t; a)
>         writeln(t);

Try:

	writefln("%.3f", t);

instead.


> }
> 
> ---------------------------------


T

-- 
Dogs have owners ... cats have staff. -- Krista Casada
February 25, 2018
On Sunday, 25 February 2018 at 06:35:07 UTC, Jonathan M Davis wrote:
>
> It's not printing ints. It's printing doubles. It's just that all of the doubles have nothing to the right of the decimal point, so they don't get printed with a decimal point. If you did something like start with 1.1, then you'd see decimal points, because there would be data to the right of the decimal point. The same thing happens if you do
>
> writeln(1.0);
>
> as opposed to something like
>
> writeln(1.3);
>

thanks.

But umm.... what happended to the principle of least astonishment?

writeln(1.1); (prints 1.1)
whereas..
writeln(1.0); (prints 1)

I don't get it. Cause it's 'nicer'??

I ended up having to work around this..like this:

-------
void printArray(T)(const ref T[] a) if (isArray!(T[]))
{
    if( isFloatingPoint!T)
        foreach(t; a) writefln("%.1f", t);
    else
        foreach(t; a) writefln("%s", t);

}
-------
February 25, 2018
On Sunday, 25 February 2018 at 08:08:30 UTC, psychoticRabbit wrote:
>
>
> But umm.... what happended to the principle of least astonishment?
>
> writeln(1.1); (prints 1.1)
> whereas..
> writeln(1.0); (prints 1)
>
> I don't get it. Cause it's 'nicer'??
>

Because writeln(someFloat) is equivalent to writefln("%g", someFloat). And according to printf specification, "trailing zeros are removed from the fractional part of the result; a decimal point appears only if it is followed by at least one digit"

February 25, 2018
On Sunday, 25 February 2018 at 08:46:19 UTC, rumbu wrote:
> On Sunday, 25 February 2018 at 08:08:30 UTC, psychoticRabbit wrote:
>>
>>
>> But umm.... what happended to the principle of least astonishment?
>>
>> writeln(1.1); (prints 1.1)
>> whereas..
>> writeln(1.0); (prints 1)
>>
>> I don't get it. Cause it's 'nicer'??
>>
>
> Because writeln(someFloat) is equivalent to writefln("%g", someFloat). And according to printf specification, "trailing zeros are removed from the fractional part of the result; a decimal point appears only if it is followed by at least one digit"

oh. that explains it.

I would have preffered it defaulted java style ;-)

System.out.println(1.0); // i.e. it prints 'what I told it to print'.

« First   ‹ Prev
1 2 3