gabrielperales / elm-native-module

Example of how to do an Elm native module
34 stars 5 forks source link

Add a note about functions with more than one argument #3

Closed gurdiga closed 6 years ago

gurdiga commented 7 years ago

Hi Gabriel! ๐Ÿ‘‹

Thank you for putting this together: It helped me get started with Native modules in Elm 0.18! ๐Ÿค“

NOTE: This is not really an issue, itโ€™s more like an idea to add to the README, if it looks useful to you. ๐Ÿ˜‰

So, in my case I needed a function thatโ€™d take 2 arguments:

// src/Native/Intl.js
var _gurdiga$xo_elm$Native_Intl = function() {
  function formatMoneyAmount(localeName, amount) {
    return "yes";
  }

  return {
    formatMoneyAmount: formatMoneyAmount
  };
}();

and then I tried to call it like this:

Native.Intl.formatMoneyAmount "ro-MD" 42

It compiled, but when run in the browser (through elm-reactor) it crashed the whole Elm app with something like this in the Chrome console:๐Ÿ˜ถ

Main.elm:93 Uncaught TypeError: fun(...) is not a function
    at A2 (Main.elm:93)
    at _gurdiga$xo_elm$Utils_Money$format (Main.elm:13254)
    at _gurdiga$xo_elm$Dosar_Actiune_IncheiereIntentare_RezultatIncercareConciliere_PartileNuAjungLaIntelegere_BunuriUrmarite_BunUrmarit$view (Main.elm:15783)
    at itemView (Main.elm:15967)
    at Function.func (Main.elm:1390)
    at A2 (Main.elm:92)
    at Function.foldr [as func] (Main.elm:1116)
    at A3 (Main.elm:98)
    at Function.func (Main.elm:1384)
    at A2 (Main.elm:92)

Then I went on to look how itโ€™s done in the elm-lang/core and found this in Native/Debug.js:

return {
    crash: crash,
    log: F2(log)           // โ† See the F2 thingy?
};

Then I looked in my bundle and found F2:

function F2(fun)
{
  function wrapper(a) { return function(b) { return fun(a,b); }; }
  wrapper.arity = 2;
  wrapper.func = fun;
  return wrapper;
}

So my guess after all of this, is that if a native function that we want to use in Elm takes more than one argument, it has to be wrapped into an F<number> thing like that โ€” it seems like further on Elm decides how many arguments to pass it. ๐Ÿค” (I found F1 to F9 in my bundle. ๐Ÿค“)

Iโ€™m not sure where would this insight go in the README, but I thought this may be useful for someone! ๐Ÿค“

Cheers! ๐Ÿ™‚

gabrielperales commented 7 years ago

Have you tried elm ports? I think they are the best way to do js interoperability. In my opinion native modules is for stuff that needs low level interop, is that your case?

gurdiga commented 7 years ago

Yes, I have tried ports, and I will probably switch to them as soon as I clarify what exactly do I need to get from outside Elm. Right now Iโ€™m trying to rich to Intl, for some number- and date-formatting functions.

gabrielperales commented 6 years ago

@gurdiga Hi!, sorry for the delay, but I have updated the example with a function with two parameters as you were expecting. I hope this can help you.