Thread overview
toLower
Aug 15, 2023
Joel
Aug 15, 2023
FeepingCreature
Aug 15, 2023
Joel
Aug 15, 2023
bachmeier
Aug 16, 2023
FeepingCreature
Aug 17, 2023
Joel
Aug 17, 2023
bachmeier
Aug 17, 2023
Joel
Aug 18, 2023
Nick Treleaven
Aug 15, 2023
ryuukk_
August 15, 2023

How come toLower works in the sort quotes, but not in the map?

void main() {
    import std;
    "EzraTezla"
        .to!(char[])
        .byCodeUnit
        .sort!"a.toLower<b.toLower"
        .map!(c => c.toLower)
        .writeln;
}

onlineapp.d(60): Error: toLower matches conflicting symbols:
/dlang/dmd/linux/bin64/../../src/phobos/std/uni/package.d(9819): function std.uni.toLower
/dlang/dmd/linux/bin64/../../src/phobos/std/ascii.d(637): function std.ascii.toLower!char.toLower
/dlang/dmd/linux/bin64/../../src/phobos/std/algorithm/iteration.d(479): instantiated from here: MapResult!(__lambda4, SortedRange!(ByCodeUnitImpl, "a.toLower>b.toLower", SortedRangeOptions.assumeSorted))
onlineapp.d(60): instantiated from here: map!(SortedRange!(ByCodeUnitImpl, "a.toLower>b.toLower", SortedRangeOptions.assumeSorted))

August 15, 2023

On Tuesday, 15 August 2023 at 16:47:36 UTC, Joel wrote:

>

How come toLower works in the sort quotes, but not in the map?

void main() {
    import std;
    "EzraTezla"
        .to!(char[])
        .byCodeUnit
        .sort!"a.toLower<b.toLower"
        .map!(c => c.toLower)
        .writeln;
}

When you pass a string to a lambda, it's evaluated in std.functional.unaryFun/binaryFun.

At that point, these modules are imported for use in string expressions:

import std.algorithm, std.conv, std.exception, std.math, std.range, std.string;
import std.meta, std.traits, std.typecons;

And std.string itself publically imports:

public import std.uni : icmp, toLower, toLowerInPlace, toUpper, toUpperInPlace;

But does not import std.ascii! So there's no ambiguity inside the sort string expression between the two toLower functions..

August 15, 2023

On Tuesday, 15 August 2023 at 16:47:36 UTC, Joel wrote:

>

How come toLower works in the sort quotes, but not in the map?

void main() {
    import std;
    "EzraTezla"
        .to!(char[])
        .byCodeUnit
        .sort!"a.toLower<b.toLower"
        .map!(c => c.toLower)
        .writeln;
}

onlineapp.d(60): Error: toLower matches conflicting symbols:
/dlang/dmd/linux/bin64/../../src/phobos/std/uni/package.d(9819): function std.uni.toLower
/dlang/dmd/linux/bin64/../../src/phobos/std/ascii.d(637): function std.ascii.toLower!char.toLower
/dlang/dmd/linux/bin64/../../src/phobos/std/algorithm/iteration.d(479): instantiated from here: MapResult!(__lambda4, SortedRange!(ByCodeUnitImpl, "a.toLower>b.toLower", SortedRangeOptions.assumeSorted))
onlineapp.d(60): instantiated from here: map!(SortedRange!(ByCodeUnitImpl, "a.toLower>b.toLower", SortedRangeOptions.assumeSorted))

This error message is unreadable, maybe an issue should be opened about it, so it could be improved, took me a while to understand, or rather "decipher", what it says..

August 15, 2023

On Tuesday, 15 August 2023 at 16:54:49 UTC, FeepingCreature wrote:

>

On Tuesday, 15 August 2023 at 16:47:36 UTC, Joel wrote:

>

[...]
When you pass a string to a lambda, it's evaluated in std.functional.unaryFun/binaryFun.

At that point, these modules are imported for use in string expressions:

import std.algorithm, std.conv, std.exception, std.math, std.range, std.string;
import std.meta, std.traits, std.typecons;

And std.string itself publically imports:

public import std.uni : icmp, toLower, toLowerInPlace, toUpper, toUpperInPlace;

But does not import std.ascii! So there's no ambiguity inside the sort string expression between the two toLower functions..

How do I get it to work?

I tried std.ascii.toLower. And using alias toLower=std.ascii.toLower;

August 15, 2023

On Tuesday, 15 August 2023 at 20:09:28 UTC, Joel wrote:

>

On Tuesday, 15 August 2023 at 16:54:49 UTC, FeepingCreature wrote:

>

On Tuesday, 15 August 2023 at 16:47:36 UTC, Joel wrote:

>

[...]
When you pass a string to a lambda, it's evaluated in std.functional.unaryFun/binaryFun.

At that point, these modules are imported for use in string expressions:

import std.algorithm, std.conv, std.exception, std.math, std.range, std.string;
import std.meta, std.traits, std.typecons;

And std.string itself publically imports:

public import std.uni : icmp, toLower, toLowerInPlace, toUpper, toUpperInPlace;

But does not import std.ascii! So there's no ambiguity inside the sort string expression between the two toLower functions..

How do I get it to work?

I tried std.ascii.toLower. And using alias toLower=std.ascii.toLower;

Changing your map line to

.map!(c => std.uni.toLower(c))

works for me.

August 16, 2023

On Tuesday, 15 August 2023 at 20:09:28 UTC, Joel wrote:

>

On Tuesday, 15 August 2023 at 16:54:49 UTC, FeepingCreature wrote:

>

But does not import std.ascii! So there's no ambiguity inside the sort string expression between the two toLower functions..

How do I get it to work?

I tried std.ascii.toLower. And using alias toLower=std.ascii.toLower;

To elaborate more, toLower doesn't work because function-scope aliases are not considered for UFCS.

    alias toLower = std.ascii.toLower;

    ...
    // So this does actually work:
        .map!toLower
    // but this does not, because it looks for a UFCS-capable symbol
        .map!(c => c.toLower)
    // but this does again
        .map!(c => toLower(c))

August 17, 2023

On Wednesday, 16 August 2023 at 05:40:09 UTC, FeepingCreature wrote:

>

On Tuesday, 15 August 2023 at 20:09:28 UTC, Joel wrote:

>

On Tuesday, 15 August 2023 at 16:54:49 UTC, FeepingCreature wrote:

>

But does not import std.ascii! So there's no ambiguity inside the sort string expression between the two toLower functions..

How do I get it to work?

I tried std.ascii.toLower. And using alias toLower=std.ascii.toLower;

To elaborate more, toLower doesn't work because function-scope aliases are not considered for UFCS.

    alias toLower = std.ascii.toLower;

    ...
    // So this does actually work:
        .map!toLower
    // but this does not, because it looks for a UFCS-capable symbol
        .map!(c => c.toLower)
    // but this does again
        .map!(c => toLower(c))

I get an compile time error with sort after using toLower, putting in array before sort, didn’t work:

```d
void main() {
    Import std;

    "EzraTezla"
        .to!(char[])
        .byCodeUnit
        .map!(std.uni.toLower)
        .sort!"a<b"
        .writeln;
}
```
onlineapp.d(8): Error: none of the overloads of template `std.algorithm.sorting.sort` are callable using argument types `!("a<b")(MapResult!(toLower, ByCodeUnitImpl))`
/dlang/dmd/linux/bin64/../../src/phobos/std/algorithm/sorting.d(1925):        Candidate is: `sort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, Range)(Range r)`
  with `less = "a<b",
       ss = SwapStrategy.unstable,
       Range = MapResult!(toLower, ByCodeUnitImpl)`
  must satisfy one of the following constraints:
`       hasSwappableElements!Range
       hasAssignableElements!Range
       ss != SwapStrategy.unstable`
August 17, 2023

On Thursday, 17 August 2023 at 09:28:05 UTC, Joel wrote:

>

I get an compile time error with sort after using toLower, putting in array before sort, didn’t work:

```d
void main() {
    Import std;

    "EzraTezla"
        .to!(char[])
        .byCodeUnit
        .map!(std.uni.toLower)
        .sort!"a<b"
        .writeln;
}
```

It works for me. Modifying your code to

void main() {
    import std;

    "EzraTezla"
        .to!(char[])
        .byCodeUnit
        .map!(std.uni.toLower)
        .array
        .sort!"a<b"
        .writeln;
}

compiles and gives the expected output. https://run.dlang.io/is/85VjiL

August 17, 2023

On Thursday, 17 August 2023 at 14:14:00 UTC, bachmeier wrote:

>

On Thursday, 17 August 2023 at 09:28:05 UTC, Joel wrote:

>

I get an compile time error with sort after using toLower, putting in array before sort, didn’t work:

```d
void main() {
    Import std;

    "EzraTezla"
        .to!(char[])
        .byCodeUnit
        .map!(std.uni.toLower)
        .sort!"a<b"
        .writeln;
}
```

It works for me. Modifying your code to

void main() {
    import std;

    "EzraTezla"
        .to!(char[])
        .byCodeUnit
        .map!(std.uni.toLower)
        .array
        .sort!"a<b"
        .writeln;
}

compiles and gives the expected output. https://run.dlang.io/is/85VjiL

void main() {
    import std;

    "EzraTezla"
        .to!(char[])
        .byCodeUnit
        .map!(std.ascii.toLower)
        .array
        .sort!"a<b"
        .writeln;
}

std.uni.toLower works, but not ascii. Ascii works with bycode after map, though.

/Library/D/dmd/src/phobos/std/algorithm/sorting.d(1936): Error: static assert: "When using SwapStrategy.unstable, the passed Range 'char[]' must either fulfill hasSwappableElements, or hasAssignableElements, both were not the case"
once.d(9): instantiated from here: sort!("a<b", SwapStrategy.unstable, char[])

August 18, 2023

On Thursday, 17 August 2023 at 09:28:05 UTC, Joel wrote:

>
        .map!(std.uni.toLower)
        .sort!"a<b"
        .writeln;
}
```
onlineapp.d(8): Error: none of the overloads of template `std.algorithm.sorting.sort` are callable using argument types `!("a<b")(MapResult!(toLower, ByCodeUnitImpl))`
/dlang/dmd/linux/bin64/../../src/phobos/std/algorithm/sorting.d(1925):        Candidate is: `sort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, Range)(Range r)`
  with `less = "a<b",
       ss = SwapStrategy.unstable,
       Range = MapResult!(toLower, ByCodeUnitImpl)`
  must satisfy one of the following constraints:
`       hasSwappableElements!Range
       hasAssignableElements!Range
       ss != SwapStrategy.unstable`

map generates a range r whose elements can be accessed by mutable reference only if the result of calling the map function (on a source element) is a mutable reference. But std.uni.toLower returns by value, and sort requires r.front to be a mutable reference.

I'll look at improving the docs.