Strange compile result

42 views
Skip to first unread message

Andreas Köberle

unread,
Feb 12, 2016, 1:18:36 PM2/12/16
to Elm Discuss
I have the following elm function: 

labToColor : { l : Float, a : Float, b : Float } -> Color
labToColor { l, a, b } =
    let
        y = (l + 16) / 116

        x = y + a / 500

        z = y - b / 200

        y' = d y

        x' =(d x) * 0.95047

        z' = (d z) * 1.08883

        r = x' * 3.2404542 + y' * -1.5371385 + z' * -0.4986

        g = x' * -0.969266 + y' * 1.8760108 + z' * 4.1556e-2

        b = x' * 5.56434e-2 + y' * 0.2040259 + z' * 1.0572252
    in
        Debug.log
            "rgb"
            (rgb
                (round (f r) * 255)
                (round (f g) * 255)
                (round (f b) * 255)
            )

Note the order of z and z' variable in the compiled result

var labToColor = function (_p0) {
      var _p1 = _p0;
      var y = (_p1.l + 16) / 116;
      var x = y + _p1.a / 500;
      var x$ = d(x) * 0.95047;
      var y$ = d(y);
      var b = x$ * 5.56434e-2 + y$ * 0.2040259 + z$ * 1.0572252;
      var z$ = d(z) * 1.08883;
      var z = y - _p1.b / 200;
      var r = x$ * 3.2404542 + y$ * -1.5371385 + z$ * -0.4986;
      var g = x$ * -0.969266 + y$ * 1.8760108 + z$ * 4.1556e-2;
      return A2($Debug.log,
      "rgb",
      A3($Color.rgb,
      $Basics.round(f(r)) * 255,
      $Basics.round(f(g)) * 255,
      $Basics.round(f(b)) * 255));
   };
For some reasons now z' is used before z is declared. Is this a problem with the code or the compiler?

Nick H

unread,
Feb 12, 2016, 2:01:11 PM2/12/16
to elm-d...@googlegroups.com
Is your program behaving unexpectedly?

The order in which you declare things does not change the behavior of the program. In Elm, you have constants and functions, but variables do not exist.


--
You received this message because you are subscribed to the Google Groups "Elm Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elm-discuss...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Chris Schneider

unread,
Feb 12, 2016, 2:35:57 PM2/12/16
to elm-d...@googlegroups.com
I think it's the compiled javascript that's the problem, and JS certainly does care about order, and dependencies like that.

      var z$ = d(z) * 1.08883;
      var z = y - _p1.b / 200;

z$ is using the z value that's not defined until the next line.

Nick H

unread,
Feb 12, 2016, 2:49:36 PM2/12/16
to elm-d...@googlegroups.com
Oh, right.

I'll just, um, see myself out.

Andreas Köberle

unread,
Feb 12, 2016, 2:54:52 PM2/12/16
to Elm Discuss
So the order of the constance declaration is not reliable? Is this documented somewhere?

Nick H

unread,
Feb 12, 2016, 3:30:11 PM2/12/16
to elm-d...@googlegroups.com
I meant that order doesn't matter in the Elm language. I misunderstood what your problem was, so my answer wasn't very relevant.

Joey Eremondi

unread,
Feb 12, 2016, 3:33:12 PM2/12/16
to elm-d...@googlegroups.com
Here's the thing: the order that you declare values in a let statement does not matter. It is not "reliable" in the sense that the order you say won't necessarily correspond to the JavaScript code that's outputted, but it's "reliable" in the sense that the Elm compiler looks at the dependencies and will order the declarations in such a way that there is never an error. (If there is, it's a compiler bug).

For example, the two snippets are semantically identical in Elm:

let
  x = 3
  y = x + 2
in x*y

let
  y = x + 2
  x = 3
in x * y

In terms of scoping, all values in a let-statement are assumed to be mutually recursive: the definitions of any of the right-hand sides can refer to any variables defined on any of the left-hand sides, within the given let statement.

As for your example, I think this is a compiler bug, and I'm suspicious that it has to do with the renaming of primed variables.

The real question is: has anyone tried running this code? Does the JS throw an error? I'm just firing up my editor to check, but it would be useful to have something to compare to.

Joey Eremondi

unread,
Feb 12, 2016, 3:39:31 PM2/12/16
to elm-d...@googlegroups.com
Okay, after running it, I can confirm, no JS error is thrown but it gives garbage values at runtime (thanks JavaScript).

This looks to me like a very serious compiler bug. I'll open an issue on this.

Joey Eremondi

unread,
Feb 12, 2016, 3:57:20 PM2/12/16
to elm-d...@googlegroups.com
I've diagnosed the problem! You have a naming conflict between the "b" in your input record, and the "b" of your RBG output.

It compiles it improperly because there is a dependency cycle. The "b" in the record is ignored, and the let-statement defining z based on the b of the let statement, which depends on z', which depends on z.

I've got a fixed version below. The key is to use nested let-statements, to create a separate scope for the different "b" variables.

Not reporting dependency cycles like this is a long-standing issue, so there's not need to open a new issue.

labToColor : { l : Float, a : Float, b : Float } -> Color
labToColor { l, a, b } =
    let
        y = (l + 16) / 116

        x = y + a / 500

        z = y - b / 200

        y' = d y

        x' =(d x) * 0.95047

        z' = (d z) * 1.08883
    in
      let

Joey Eremondi

unread,
Feb 12, 2016, 3:59:28 PM2/12/16
to elm-d...@googlegroups.com
Bah, google mangled my formatting. Here's a gist with the proper code.
https://gist.github.com/JoeyEremondi/76a46d796f903b74de9c

Max Goldstein

unread,
Feb 12, 2016, 4:20:00 PM2/12/16
to Elm Discuss
google mangled my formatting

Yeah, that's happened to me several times. It's quite annoying. Good diagnostic work! 

Andreas Köberle

unread,
Feb 12, 2016, 4:56:04 PM2/12/16
to Elm Discuss
Thanks for the answer

Joey Eremondi

unread,
Feb 12, 2016, 4:59:16 PM2/12/16
to elm-d...@googlegroups.com
As an alternate solution to Nested Let-statements, you could just rename r,g,b to rVal, gVal, bVal and avoid the naming conflict altogether.

Max Goldstein

unread,
Feb 12, 2016, 5:32:37 PM2/12/16
to Elm Discuss
Soo... are we convinced that variable shadowing should be disallowed yet?

Joey Eremondi

unread,
Feb 12, 2016, 5:34:58 PM2/12/16
to elm-d...@googlegroups.com
Not fully for me. This error is easily avoided with cycle detection. I'd made some progress on that this summer, but didn't get all the way there.

On Fri, Feb 12, 2016 at 2:32 PM, Max Goldstein <maxgol...@gmail.com> wrote:
Soo... are we convinced that variable shadowing should be disallowed yet?

--

Evan Czaplicki

unread,
Feb 12, 2016, 7:02:55 PM2/12/16
to elm-d...@googlegroups.com
Detecting cycles of values like this is pretty high on my todo list for compiler related tasks! I don't know the exact timeline, but I'd expect it to get fixed on the next serious pass over the compiler (a.k.a. as soon as possible)

Sorry Andreas for the trouble, and thanks Joey for figuring out exactly what was going wrong! :D
Reply all
Reply to author
Forward
0 new messages