Giter Club home page Giter Club logo

Comments (6)

mattt avatar mattt commented on June 14, 2024

Thanks for thinking on this, @Lukas-Stuehrk. All of that repetition in the implementation is annoying and conspicuous, but it serves a specific purpose (at least I think it does).

When I first approached the problem, a Container<Child> seemed like an obvious choice. That's a textbook example of when to use generics in Swift. But I soon ran into the limitation that having an associated type requirement requires you to specify that generic type in declarations. For example, if Container has an associated Child type requirement, you can't declare a variable with type Container or use that as the return value for a function or property — you'd have to be explicit: Container<Block & Node> or Container<Inline & Node>.

IIRC, what I eventually found was that Container<Child> caused the associated type requirement to bubble all the way up to Node, which compromised my design goals for the library. Hence the ugly workaround — all of that copy-paste is for the benefit of convenience at the call site.

It could very well be that I missed something obvious in my first implementation, or wasn't clever enough to find a better solution (as you saw, managing child nodes wasn't my primary use case, and thus wasn't the focus of my efforts). If you found a solution that simplified the implementation without degrading API usability, I'd be glad to have it. But I just wanted to offer fair warning that I tried the same thing before, and wasn't able to make it work.

from commonmark.

Lukas-Stuehrk avatar Lukas-Stuehrk commented on June 14, 2024

I did a quick prototype in the Container-Simplification branch in my fork.

The first commit 7101648 removes all protocols and comes with a single container protocol. Type safety is still given, so it's not possible to add a block as a child of a container that only supports inline elements.

If we still need to be able to have the ContainerOfBlocks and the ContainerOfInlineElements protocols, and to be able to use it as a type (so they should not have associated types or Self requirements), then 1d89b50 demonstrates that this is still possible.

All changes happen in Children.swift only, so none of the complexity bubbles up to any other type.

However, I also understand that this implementation might use a certain level of "cleverness" which you might not want to have in a codebase, as it might be not obvious enough for people who are not familiar with the codebase.

from commonmark.

mattt avatar mattt commented on June 14, 2024

I stand corrected! 7101648 is exactly how this should be done. If you submit that in a PR, I'd be very happy to incorporate it for the next release.

As for 1d89b50, I'm having trouble wrapping my head around why the typealias declaration in an extension works here. Assuming we can do without ContainerOfBlocks and ContainerOfInlineElements (since now you can say Container where Child: Inline), I say let's get rid of them outright.

from commonmark.

Lukas-Stuehrk avatar Lukas-Stuehrk commented on June 14, 2024

The typealias declaration in 1d89b50 works because I kind of cheated: ContainerOfBlock and ContainerOfInlineElements do not need to conform to Container.

As for 7101648, I need to disclose one little problem: Please notice the ugly cast in line 60: 7101648#diff-6ec4af82405deaa118bdbc9885526abbR60

I'd prefer to modify the existing approach and use Children(of: self).compactMap { $0 as? ChildNode } because this would only drop a single child if there was a problem with a wrong child, instead of dropping all children like my solution. But this approach always creates an empty array now (ironically only caught by the tests I added in #10). I'm 95% sure that this is a Swift bug, because if I debug it and execute the code in lldb everything works and all types are correct. But I also did not spent too much time investigating it as this was only a quick prototype.

However, this cast should always work as it's impossible to add the wrong child.

I will open a pull request for the simplification, but just wanted to be fully transparent with this problem and not sneak it in.

from commonmark.

Lukas-Stuehrk avatar Lukas-Stuehrk commented on June 14, 2024

I managed to find a more elegant solution for the problem.

from commonmark.

mattt avatar mattt commented on June 14, 2024

@Lukas-Stuehrk A fair amount of code has changed with #22 and more stands to change with #25, so this may no longer be a concern. If it is, please let me know and I'll reopen for further discussion. Thanks!

from commonmark.

Related Issues (11)

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.