0

Just trying to generally understand what is going on here. Does this make sense to explain ReasonApolloTypes.gql as an example of using Externals.

This is the bs.module code

[@bs.module] external gql : ReasonApolloTypes.gql = "graphql-tag";

bs.module tells buckelscript that we want to use a FFI.

external tells bs the name of the FII we want to use and we set its value to ReasonApolloTypes.gql which is a globally available Reason module that we installed when we added reason-apollo in bsconfig's bs-dependencies array, and to package.json. If you open node_modules/reason-apollo/src you will see defined Reason modules that are globally available like any other.

ReasonApolloTypes.re is listed there and contains a defined type named gql. So ReasonApolloType.gql is the named module we are accessing with external gql. In ReasonApolloType.gql there is a defined type, type gql = [@bs] (string => queryString);. This tell bucklescript to assign a type of string to the gql type and the assign the value to querystring, so type querystring is of type string. Then set ReasonApolloTypes.gql to use the "graphql-tag" node library to resolve ReasonApolloTypes.gql.

Am I missing an concepts here? Is this expressed correctly? The Bucklescript/Reason docs are above my head for Externals at this point. Thanks.

armand
  • 693
  • 9
  • 29

1 Answers1

3

This question is really not very appropriate on SO (see what's on-topic here), and should perhaps be asked on the Discord instead. But here's what it means:

  • external tells the compiler we're defining something that's "external", ie. that we want to use FFI.

  • [@bs.module] tells BuckleScript that what we're referencing is a module, and that it will need to emit require calls when it's used.

  • gql is the name we're going to use to refer to it on the Reason side.

  • : means we're specifying the type of the external. ReasonApolloTypes.gql is a type defined in the ReasonApolloTypes module.

  • = "graphql-tag" tells the compiler that what we're referencing is named graphql-tag on the JavaScript side.

Furthermore, type gql = [@bs] (string => queryString); specifies that it is a function from string to queryString, and [@bs] means it should use the uncurried calling convention when calling this function.

So, on the ML side, gql is a function that takes a string and returns a queryString. When called:

let qs = [@bs] gql("some string"); /* [@bs] because it's uncurried */

BuckleScript will generate something like this:

var qs = require("graphql-tag")("some string");

PS: In general, I'd advise you to start with something simpler to try to understand the FFI system. Trying to understand everything at once makes for a very steep learning curve and drastically increases the cost of small misunderstandings, because they tend to accumulate.

glennsl
  • 28,186
  • 12
  • 57
  • 75
  • Awesome, answer. Someone should link it on the bucklescript docs. What does it look like to learn FFI in little bits? I've been through the bs docs, did every example. I think the problem for me is that they are out of context so even if you get the example to run maybe you don't see how to use it in context. Thanks for this great answer. I think it will be useful to lots of folks which is why I posted it here. – armand Nov 14 '17 at 08:45
  • Does it matter what order they are called in? I've seen [@bs.module] at the end of the statement. I've seen [@bs.module somemoduleName]. – armand Nov 14 '17 at 08:52
  • 1
    OCaml and the old Reason syntax had them at the end. The new syntax have them at the beginning. So in that sense it depends which syntax you are reading. – glennsl Nov 14 '17 at 09:10
  • 1
    I'd recommend having the the generated javascript code open next to the code you write. Like on https://reasonml.github.io/try. Start with the simplest binding (take one from https://github.com/glennsl/bucklescript-ffi-cheatsheet for example), play around with it to see what comes out on the other side. Then gradually make it more complex. Add `[@bs.module]]` to it for example, or try having it take a function type with and without `@bs]`. – glennsl Nov 14 '17 at 09:17