Giter Club home page Giter Club logo

Comments (17)

glennsl avatar glennsl commented on May 27, 2024 1

Hmm, seems to work fine here: https://github.com/reasonml-community/bs-webapi-incubator/blob/master/examples/dom_example.re

It's generally recommended to open modules as locally as possible, unless they've been explicitly designed for the purpose, precisely to avoid name collisions like this. It's still not a great idea to have a variant named None however, and I'll probably change it in the future. I'll keep this issue open as a reminder. Thanks for making me aware, and let me know if it's still blocking you.

from bs-webapi-incubator.

cassiozen avatar cassiozen commented on May 27, 2024 1

Thanks for the response - I just got it to work.

This only happens when I rely on type inference:
none_inference

If I type my variable as option(int) than None is correctly identified...
none_typed

from bs-webapi-incubator.

yawaramin avatar yawaramin commented on May 27, 2024 1

Hmm, I have an idea that's kind of a middle ground. Reopening this one.

from bs-webapi-incubator.

AriaFallah avatar AriaFallah commented on May 27, 2024

I'm getting this as well (I am able to fix it with a local open, thanks @glennsl):

  Warning number 45
  MyFile.re 3:1-15

  1 │ open Types;
  2 │
  3 │ open Webapi.Dom;
  4 │
  5 │ open Webapi.Canvas;

  this open statement shadows the constructor None (which is later used)

  We've found a bug for you!
  MyFile.re 26:51-59

  24 │ };
  25 │
  26 │ let interval: ref(option(Js.Global.intervalId)) = ref(None);
  27 │
  28 │ let create = (config: config, ctx: Canvas2d.t) : t => {

  This has type:
    ref(Webapi.Dom.eventPhase)
  But somewhere wanted:
    ref(option(Js.Global.intervalId))

  The incompatible parts:
    Webapi.Dom.eventPhase (defined as DomTypesRe.eventPhase)
    vs
    option(Js.Global.intervalId)

from bs-webapi-incubator.

alex35mil avatar alex35mil commented on May 27, 2024

In my case explicit type doesn't help, None is still shadowed.

What about namespasing it more? E.g.

module EventPhase = {
  type t =
    | ...
    | None;
};

from bs-webapi-incubator.

glennsl avatar glennsl commented on May 27, 2024

I've actually proposed that myself here: #27 (comment)

Another alternative is to use modules with constants instead of variants, which dead code eliminate well and works really well with bitmask flags, but loses out on exhaustiveness checking.

A third alternative is to use polymorphic variants, which doesn't need wrapping in modules and can potentially be eliminated completely at compile time (unfortunately I think bs.unwrap currently is unsound).

from bs-webapi-incubator.

alex35mil avatar alex35mil commented on May 27, 2024

Yeah, I like module wrapper pattern. Started using this recently and it feels very convenient:

module Foo = {
  type t = ...;

  let fromString = ...;
  let toString = ...;

  ...
};

from bs-webapi-incubator.

spocke avatar spocke commented on May 27, 2024

I made a PR to just wrap all the types here: #162 not sure if that is a to radical change. But there is a risk that other things than None conflicts as well.

from bs-webapi-incubator.

spocke avatar spocke commented on May 27, 2024

Here is a less radical PR just wrapping the EventPhase in a module. #163

from bs-webapi-incubator.

glennsl avatar glennsl commented on May 27, 2024

THanks @spocke. But I think if we're going to break things, we should do it properly to not break things more than strictly necessary. And for a change as invasive as this I think we need to make an experimental branch and try it out for a bit in real projects.

What are the options we have? From reading this thread I see:

  1. Not including the Types module in Webapi.Dom This is basically the same as namespacing the entire Types module. This resolves the shadowing/name collision issue, but not much else.

  2. Namespacing each type individually, by wrapping each of them in a sub-module. Also just resolves the shadowing/name collision issue, but is significantly nicer than a single Types namespace.

  3. Using constants instead of variants, wrapped in separate sub-modules. Dead-code eliminates really well, works consistently with bitmask flags but loses exhaustiveness checking.

  4. Using polymorphic variants with bs.as. If this works now, it's potentially zero-cost and maintains exhaustiveness checking, but does not work as well with bitmask flags.

For me it's between 3 and 4. The questions I have are, how useful is exhaustiveness checking for these types, and how important is it to be "idiomatic"? I'm leaning towards "not very much" and "not so much at this low level".

from bs-webapi-incubator.

spocke avatar spocke commented on May 27, 2024

I would go with 2 since I think it's strange that these things are root level. For example nodeType is something I would expect to be in WebApi.Dom.Node.nodeType together with the decoderNodeType or in a separate WebApi.Dom.NodeType module same with compareHow it's only used by Range so in my mind that should be WebApi.Range.compareHow together with it's encoder the same probably goes for most of those things moving them to their appropriate module or in a common shared module with the same concept if they are using in multiple places but maybe I'm missing some problem with doing it that way.

from bs-webapi-incubator.

glennsl avatar glennsl commented on May 27, 2024

3 is namespaced as well, and 4 is structural, so it doesn't really matter whether it's at root level or not. What's the reason you prefer 2 over these?

If we put the types in the modules where they seem to most belong, we'll soon encounter issues with cyclic dependencies and will have to move at least some of them to a common module to resolve that. It therefore seemed more consistent to do so with all of them from the start. But we can still alias nodeType in Dom.Node, for example.

from bs-webapi-incubator.

yawaramin avatar yawaramin commented on May 27, 2024

I'd say let's revisit a larger redesign in a separate issue. It is possible to mitigate the original issue reported here, the shadowing, by re-exporting the option type in some module before opening the Webapi.Dom module. For example,

module Option = {
  type t('a) = option('a) = None | Some('a);
};
...
open Webapi.Dom; // Although we don't recommend global opens
...
let none = Option.None; // No more shadowing error

If you don't global-open Webapi.Dom, then you can access the event phase with Webapi.Dom.None.

from bs-webapi-incubator.

TheSpyder avatar TheSpyder commented on May 27, 2024

I disagree. This library is cumbersome to use without open Webapi.Dom at the top of the file, as shown in the example code.

from bs-webapi-incubator.

yawaramin avatar yawaramin commented on May 27, 2024

The example code doesn't necessarily reflect real-world code. If you're doing a lot of DOM-heavy work, sure, it makes sense to open it in a larger scope. But chances are, most people are not (otherwise we'd see a lot more interest in this issue, for example). In any case, a mitigation for None has been provided.

from bs-webapi-incubator.

TheSpyder avatar TheSpyder commented on May 27, 2024

I am doing a lot of DOM-heavy work with this library, sometimes I wonder if I'm the only one, your workaround (using Option.None instead of None) is not acceptable to apply across an entire codebase.

Ever since @spocke made his comments and PR proposals last year we've been using our own custom-named duplication of Webapi__Dom.re that replaces include Webapi__Dom__Types; with module Types = Webapi__Dom__Types;. I guess we'll be continuing to use that for the foreseeable future.

from bs-webapi-incubator.

yawaramin avatar yawaramin commented on May 27, 2024

None constructor is namespaced, will remove the old type in a few months

from bs-webapi-incubator.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.