From af6ae4960e13ca2a8b91bab841837814dc2417ce Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 11 Apr 2024 21:07:10 +0200 Subject: [PATCH 1/4] Add custom syntax highlighting theme --- theme/highlight.css | 125 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 theme/highlight.css diff --git a/theme/highlight.css b/theme/highlight.css new file mode 100644 index 0000000..7421f8d --- /dev/null +++ b/theme/highlight.css @@ -0,0 +1,125 @@ +/*! + Theme: GitHub + Description: Light theme as seen on github.com + Author: github.com + Maintainer: @Hirse + Updated: 2021-05-15 + + Outdated base version: https://github.com/primer/github-syntax-light + Current colors taken from GitHub's CSS +*/ + +.hljs { + color: #24292e; + background: #ffffff; +} + +.hljs-doctag, +.hljs-keyword, +.hljs-meta .hljs-keyword, +.hljs-template-tag, +.hljs-template-variable, +.hljs-type, +.hljs-variable.language_ { + /* prettylights-syntax-keyword */ + color: #d73a49; +} + +.hljs-title, +.hljs-title.class_, +.hljs-title.class_.inherited__, +.hljs-title.function_ { + /* prettylights-syntax-entity */ + color: #6f42c1; +} + +.hljs-attr, +.hljs-attribute, +.hljs-literal, +.hljs-meta, +.hljs-number, +.hljs-operator, +.hljs-variable, +.hljs-selector-attr, +.hljs-selector-class, +.hljs-selector-id { + /* prettylights-syntax-constant */ + color: #005cc5; +} + +.hljs-regexp, +.hljs-string, +.hljs-meta .hljs-string { + /* prettylights-syntax-string */ + color: #032f62; +} + +.hljs-built_in, +.hljs-symbol { + /* prettylights-syntax-variable */ + color: #e36209; +} + +.hljs-comment, +.hljs-code, +.hljs-formula { + /* prettylights-syntax-comment */ + color: #6a737d; +} + +.hljs-name, +.hljs-quote, +.hljs-selector-tag, +.hljs-selector-pseudo { + /* prettylights-syntax-entity-tag */ + color: #22863a; +} + +.hljs-subst { + /* prettylights-syntax-storage-modifier-import */ + color: #24292e; +} + +.hljs-section { + /* prettylights-syntax-markup-heading */ + color: #005cc5; + font-weight: bold; +} + +.hljs-bullet { + /* prettylights-syntax-markup-list */ + color: #735c0f; +} + +.hljs-emphasis { + /* prettylights-syntax-markup-italic */ + color: #24292e; + font-style: italic; +} + +.hljs-strong { + /* prettylights-syntax-markup-bold */ + color: #24292e; + font-weight: bold; +} + +.hljs-addition { + /* prettylights-syntax-markup-inserted */ + color: #22863a; + background-color: #f0fff4; +} + +.hljs-deletion { + /* prettylights-syntax-markup-deleted */ + color: #b31d28; + background-color: #ffeef0; +} + +.hljs-char.escape_, +.hljs-link, +.hljs-params, +.hljs-property, +.hljs-punctuation, +.hljs-tag { + /* purposely ignored */ +} \ No newline at end of file From 49b8f26ca7d3609bd05e56c9489fd8f80454ce86 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 11 Apr 2024 21:39:23 +0200 Subject: [PATCH 2/4] Write consumer chapter --- content/consumer.md | 58 ++++++++++++++++++++++++++++++++++++++++++++- content/provider.md | 1 - 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/content/consumer.md b/content/consumer.md index fda80ae..96bdc58 100644 --- a/content/consumer.md +++ b/content/consumer.md @@ -1,2 +1,58 @@ +# Consumer -# Consumer \ No newline at end of file +In CGP, a _consumer_ is a piece of code that consumes certain functionalities from a context. +There are several ways which a consumer may consume a functionality. At its most basic, +if a consumer has access to the _concrete_ type of a context, it can access any methods +defined by an `impl` block of that context. + +```rust +struct Person { name: String } + +impl Person { + fn name(&self) -> &str { + &self.name + } +} + +fn greet(person: &Person) { + println!("Hello, {}!", person.name()); +} +``` + +in the above example, we have a `greet` function that prints a greeting to a person using +the method `Person::name`. In other words, we say that the `greet` function is a _consumer_ +to the `Person::name` method. + +## Context-Generic Consumers + +The `greet` function in our previous example can only work with the `Person` struct. However, +if we inspect the implementation of `greet`, we can see that it is possible to generalize +`greet` to work with _any_ type that has a name. + +To generalize `greet`, we first need to define a _trait_ that acts as an _interface_ for getting +a name: + +```rust +trait HasName { + fn name(&self) -> &str; +} + +fn greet(context: &Context) +where + Context: HasName +{ + println!("Hello, {}", context.name()); +} +``` + +In the example above, we define a `HasName` trait that provides a `name` method. We then redefine +`greet` to work generically with any `Context` type, with the `where` clause requiring `Context` to +implement `HasName`. Inside the function body, we call the `name` method, and print out the greeting +of that name. + +In CGP, this new version of `greet` is considered a _context-generic_ consumer, as it is able to _generically_ +consume the `HasName::name` method from any `Context` type that implements `HasName`. + +The concept of context-generic consumer is not unique to CGP. In fact, it is already commonly used +in most of the Rust code that uses traits. However, we make an effort to study this concept, so that +we can further generalize the concept in the later chapters of this book. \ No newline at end of file diff --git a/content/provider.md b/content/provider.md index 522d51e..a325316 100644 --- a/content/provider.md +++ b/content/provider.md @@ -1,2 +1 @@ - # Provider \ No newline at end of file From 784cd70f7da331664b3ea2f7e71ca6e367b572d2 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 11 Apr 2024 23:10:39 +0200 Subject: [PATCH 3/4] Add provider chapter --- book.toml | 4 --- content/consumer.md | 4 +++ content/provider.md | 80 ++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 83 insertions(+), 5 deletions(-) diff --git a/book.toml b/book.toml index b3cd5c2..7c2f43d 100644 --- a/book.toml +++ b/book.toml @@ -10,7 +10,3 @@ edition = "2021" [build] create-missing = false - - -[output.html] -default-theme = "rust" \ No newline at end of file diff --git a/content/consumer.md b/content/consumer.md index 96bdc58..b1e6d5d 100644 --- a/content/consumer.md +++ b/content/consumer.md @@ -50,6 +50,10 @@ In the example above, we define a `HasName` trait that provides a `name` method. implement `HasName`. Inside the function body, we call the `name` method, and print out the greeting of that name. +Notice that in this example, we are able to implement `greet` _before_ we have any concrete implementation +of `HasName`. Compared to before, `greet` is now _decoupled_ from the `Person` type, thus making +our code more modular. + In CGP, this new version of `greet` is considered a _context-generic_ consumer, as it is able to _generically_ consume the `HasName::name` method from any `Context` type that implements `HasName`. diff --git a/content/provider.md b/content/provider.md index a325316..d751671 100644 --- a/content/provider.md +++ b/content/provider.md @@ -1 +1,79 @@ -# Provider \ No newline at end of file +# Provider + +In CGP, a _provider_ is a piece of code that _implements_ certain functionality +for a context. At its most basic, a provider is consist of an `impl` block for +a trait. + +```rust +trait HasName { + fn name(&self) -> &str; +} + +struct Person { name: String } + +impl HasName for Person { + fn name(&self) -> &str { + &self.name + } +} +``` + +In the above example, we implement the `HasName` for the `Person` struct. +The block `impl HasName for Person` is a _provider_ of the `HasName` trait +for the `Person` context. + +Similar to the concept of a consumer, the use of provider is common in any +Rust code that implements a trait. However, compared to cosumers, there +are limitations on how providers can be defined in Rust. + +For this example, the `impl` block is a _context-specific_ provider for the +`Person` context. Furthermore, due to the restrictions of Rust's trait system, +there can be at most one provider of `HasName` for the `Person` context. +Another common restriction is that the provider has to be defined in the same +crate as either the trait or the context. + +The asymetry between what can be done with a provider, as compared to a consumer, +is often a source of complexity in many Rust programs. As we will learn in later chapters, +one of the goals of CGP is to break this asymetry, and make it easy to implement +_context-generic providers_. + +## Providers as Consumers + +Although we have providers and consumers as distinct concepts, it is common to +have code that serve as _both_ providers and consumers. + +```rust +# trait HasName { +# fn name(&self) -> &str; +# } +# +# struct Person { name: String } +# +# impl HasName for Person { +# fn name(&self) -> &str { +# &self.name +# } +# } +# +trait CanGreet { + fn greet(&self); +} + +impl CanGreet for Person { + fn greet(&self) { + println!("Hello, {}!", self.name()); + } +} +``` + +The example above shows a new `CanGreet` trait, which provides a `greet` method. +We then implement `CanGreet` for `Person`, with the `greet` implementation using +`self.name()` to print out the name to be greeted. + +Here, the block `impl CanGreet for Person` is a provider of `CanGreet` for the `Person` +context. At the same time, it is also the _consumer_ of `HasName` for the `Person` context. +In terms of genericity, the example code is _context-specific_ to the `Person` context for both +the consumer and provider side. + +As we will see in later chapters, a powerful idea introduced by CGP is that a piece of code +can have _multiple spectrums_ of genericity on the consumer and provider sides. \ No newline at end of file From 253ed746cba21e27453c2713e452852147f9ebfb Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Thu, 11 Apr 2024 23:11:44 +0200 Subject: [PATCH 4/4] Update GitHub links --- content/introduction.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/content/introduction.md b/content/introduction.md index e5289e8..061e0ea 100644 --- a/content/introduction.md +++ b/content/introduction.md @@ -40,10 +40,10 @@ such as the similarity and differences of context-generic programming as compare ## Contribution -This book is open sourced under the MIT license on [GitHub](https://github.com/contextgeneric/context-generic-programming-patterns). +This book is open sourced under the MIT license on [GitHub](https://github.com/contextgeneric/cgp-patterns). -Anyone is welcome to contribute by submitting [pull requests](https://github.com/contextgeneric/context-generic-programming-patterns/pulls) +Anyone is welcome to contribute by submitting [pull requests](https://github.com/contextgeneric/cgp-patterns/pulls) for grammatical correction, content improvement, or adding new design patterns. -A [GitHub Discussions](https://github.com/contextgeneric/context-generic-programming-patterns/discussions) forum is available for readers +A [GitHub Discussions](https://github.com/contextgeneric/cgp-patterns/discussions) forum is available for readers to ask questions or have discussions for topics covered in this book. \ No newline at end of file