Thread overview
Voldemort toHexString Compile Error
Mar 17
kdevel
Mar 17
kdevel
March 17
void main()
{
  import std.stdio;

  "Hello D".toHexString.writeln;
}

struct HexString
{
  int i;

  auto nibbleSplit()
  {
    auto MSB = i >> 4;
    auto LSB = i & 15;
    return [MSB, LSB];
  }
}

auto toHexString(string str)
{
  struct Hex { int i;
    auto nibbleSplit() {
      auto MSB = i >> 4;
      auto LSB = i & 15;
      return [MSB, LSB];
    }
  }

  import std.algorithm : map;
  import std.conv, std.range : join;

  return str.map!Hex//String
            .map!(e => e.nibbleSplit).join
            .map!(n => n += n > 9 ? '7' : '0')
            .map!(c => c.to!char);
}

Why doesn't the function compile? But the code is compiled with the HexString structure. The error given by the compiler is as follows:

>

/dlang/dmd/linux/bin64/../../src/phobos/std/algorithm/iteration.d(582): Error: cannot access frame pointer of onlineapp.toHexString.Hex
/dlang/dmd/linux/bin64/../../src/phobos/std/algorithm/iteration.d(479): Error: template instance std.algorithm.iteration.MapResult!(Hex, string) error instantiating
onlineapp.d(33): instantiated from here: map!string
onlineapp.d(34): Error: template onlineapp.toHexString.map!((e) => e.nibbleSplit).map is not callable using argument types !()(MapResult!(Hex, string))
/dlang/dmd/linux/bin64/../../src/phobos/std/algorithm/iteration.d(446): Candidate is: map(Range)(Range r)
with Range = MapResult!(Hex, string)
must satisfy the following constraint:
` isInputRange!(Unqual!Range)

March 18
It is because Hex is nested, it has an outer pointer to the call frame of toHexString.

Make Hex static, and it works.
March 17
On Sunday, 17 March 2024 at 13:08:14 UTC, Richard (Rikki) Andrew Cattermole wrote:
> It is because Hex is nested, it has an outer pointer to the call frame of toHexString.
>
> Make Hex static, and it works.

Not really. Have you ever tried?

   "abc äöü߀ D".toHexString.writeln;

March 18
On 18/03/2024 5:45 AM, kdevel wrote:
> On Sunday, 17 March 2024 at 13:08:14 UTC, Richard (Rikki) Andrew Cattermole wrote:
>> It is because Hex is nested, it has an outer pointer to the call frame of toHexString.
>>
>> Make Hex static, and it works.
> 
> Not really. Have you ever tried?
> 
>     "abc äöü߀ D".toHexString.writeln;
> 

I did run it, both with and without static on Hex.

Without did not work on run.dlang.io which was consistent with the error that Salih had provided.

The error is clear on the first line: "cannot access frame pointer of onlineapp.toHexString.Hex"
March 17
On Sunday, 17 March 2024 at 16:48:23 UTC, Richard (Rikki) Andrew Cattermole wrote:
> [...]
>>> Make Hex static, and it works.
>> 
>> Not really. Have you ever tried?
>> 
>>     "abc äöü߀ D".toHexString.writeln;
>> 
>
> I did run it, both with and without static on Hex.
>
> Without did not work on run.dlang.io which was consistent with the error that Salih had provided.
>
> The error is clear on the first line: "cannot access frame pointer of onlineapp.toHexString.Hex"

I meant the compiled executable, not the compilation. The code has an
autodecoding issue which goes unnoticed due to using int (instead of
ubyte?) for i. When I run the executable I get a three screens stack
trace.

std.conv.ConvOverflowException@[...]linux/bin64/../../src/phobos/std/conv.d(1556): Conversion positive overflow

BTW: What is the purpose of not writing a free function like this?:

auto nibbleSplit(ubyte b)
{
  auto MSB = b >> 4;
  auto LSB = b & 15;
  return [MSB, LSB];
}

auto toHexString(string str)
{
  import std.algorithm : map;
  import std.conv, std.range : join;
  import std.utf;

  return str
//            .byCodeUnit // <-- solves the auto-decoding issue
            .map!(e => e.nibbleSplit).join
            .map!(n => n += n > 9 ? '7' : '0')
            .map!(c => c.to!char);
}

March 18

On Sunday, 17 March 2024 at 13:08:14 UTC, Richard (Rikki) Andrew Cattermole wrote:

>

It is because Hex is nested, it has an outer pointer to the call frame of toHexString.

Make Hex static, and it works.

Thank you for your contributions. It's great to develop something with you. So is having such a forum. Thanks everyone, here is the new version:

auto toHexRange(T)(const char[] str)
{
  static struct HexRange {
    int i;
    auto nibbleSplit() {
      auto MSB = i >> 4;
      auto LSB = i & 15;
      return [MSB, LSB];
    }
  }
  import std.utf : byCodeUnit;
  import std.algorithm : map;
  import std.range : join;

  return str.byCodeUnit.map!HexRange
            .map!(e => e.nibbleSplit).join
            .map!(n => n += n > 9 ? '7' : '0')
            .map!(c => c.to!T);
}

auto toHex(T)(const char[] str)
{
  static if(is(T : string))
  {

    import std.algorithm : copy;

    auto result = new char[str.length * 2];
    str.toHexRange!char.copy(result);

    return cast(string)result;

  } else {

    import std.array;

    return str.toHexRange!T.array;
  }
}

unittest
{
  enum Expected = "61626320C3A4C3B6C3BC50C39FE282AC207B447D";
  enum str = "abc äöüP߀ {D}";

  assert(str.toHex!string == Expected);

  import std.conv : hexString;
  static assert(hexString!Expected == str);

  enum NATO {
    Alpha = '0', Bravo, Charlie, Delta, Echo,
    Foxtrot, Golf, Hotel, India, Juliett,
    Kilo = 'A', Lima, Mike, November, Oscar, Papa
  }

  auto test = str.toHex!NATO;
  assert(is(typeof(test) : NATO[]));
}

SDB@79