Comments (6)
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.
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.
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.
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.
I managed to find a more elegant solution for the problem.
from commonmark.
@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)
- Can't form Range with upperBound < lowerBound HOT 3
- Enhancement: Also provide a replace method on a node with children HOT 1
- Proposal: Move render from Document to Node HOT 1
- Memory leak when initializing CommonMark.Document via commonmark string HOT 4
- Document ignores ParsingOptions passed to it in `init(_:options:)`
- Crash when referencing children of deallocated element HOT 4
- Add NSAttributedString render format HOT 3
- Reason for using apple/swift-cmark versus commonmark/cmark?
- Direct children of Document don't have a parent node. HOT 1
- Insertion of children is broken for containers
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from commonmark.