{"id":3829,"date":"2022-08-23T22:49:04","date_gmt":"2022-08-24T03:49:04","guid":{"rendered":"https:\/\/www.becomebetterprogrammer.com\/?p=3829"},"modified":"2022-08-26T18:17:38","modified_gmt":"2022-08-26T23:17:38","slug":"rust-then-vs-and_then-vs-or_else","status":"publish","type":"post","link":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-then-vs-and_then-vs-or_else\/","title":{"rendered":"Rust | Difference between then() vs and_then() vs or_else()"},"content":{"rendered":"\n<p>As you learn Rust, you find out more and more functions that sound like they behave in a similar way, when in reality they differ in subtle ways. This is the case for the functions <code>then()<\/code> , <code>and_then()<\/code> , and <code>or_else()<\/code>. No worries, this article will cover each of these methods as well as their differences.<\/p>\n\n\n\n<p><strong>The functions <code>then()<\/code> , which is part of the<code>FutureExt<\/code> trait,<code>and_then()<\/code> and <code>or_else()<\/code> , which are part of the <code>TryFutureExt<\/code> trait, are combinators that allow building complex values of based on a successfully completing a Future. These functions are accessible to the <code>Future<\/code> trait because <code>FutureExt<\/code> and <code>TryFutureExt<\/code> traits are extensions of the <code>Future<\/code> trait.<\/strong><\/p>\n\n\n\n<p>The previous definition sounds complex and hard to understand, especially after mentioning the term &#8220;combinators&#8221;. Don&#8217;t worry, in the next sections you will learn what a combinator is and how to use <code>then()<\/code> , <code>and_then()<\/code>, and <code>or_else()<\/code> functions. <\/p>\n\n\n\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_82_2 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\"><p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<\/div><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-then-vs-and_then-vs-or_else\/#What_is_a_combinator\" >What is a combinator?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-then-vs-and_then-vs-or_else\/#How_then_works\" >How then() works<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-then-vs-and_then-vs-or_else\/#How_and_then_works\" >How and_then() works<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-then-vs-and_then-vs-or_else\/#How_or_else_works\" >How or_else() works<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-then-vs-and_then-vs-or_else\/#Differences_between_then_vs_and_then_vs_or_else\" >Differences between then() vs and_then() vs or_else()<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-then-vs-and_then-vs-or_else\/#Conclusion\" >Conclusion<\/a><\/li><\/ul><\/nav><\/div>\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"What_is_a_combinator\"><\/span>What is a combinator?<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>In Rust, there is not a clear definition for combinators. However, I will share my interpretation of this definition. Hence, I encourage doing additional research if you need more clarity.<\/p>\n\n\n\n<p>The term combinator exists as Rust provides combinator functions. Combinator functions are available to build complex fragments of a program from an initial flow or process. This means, extending the behavior of a program based on the result of an existing process.<\/p>\n\n\n\n<p>To make things more clear let&#8217;s analyze the following scenario. A program has a process to calculate two numbers in function <code>sum(a:u8, b:u8)<\/code>.  <code>a + b<\/code> produces <code>c<\/code>. The result of <code>c<\/code> will always be the same unless the values <code>a<\/code> or <code>b<\/code> change.<\/p>\n\n\n\n<p>If the program needs to multiply <code>d<\/code>  times the result of <code>a + b<\/code> , you could add to the logic of <code>(a + b ) * d<\/code> to the <code>sum<\/code> function. However, this will no longer represent a true generic sum.<\/p>\n\n\n\n<p>Ideally, you will keep the <code>sum<\/code> function as it is (<code>a + b<\/code> , which equals <code>c<\/code>) and trigger another logic that does <code>c * d<\/code> right after executing the <code>sum<\/code> process. <\/p>\n\n\n\n<p>This is where the term combinator function starts making its introduction as the final result will no longer be <code>c<\/code>, but instead the combination of two processes on a type <code>T<\/code>( in this case, the type <code>u8<\/code>) that generates  the result of <code>c * d<\/code>, which ends up being <code>e<\/code>.<\/p>\n\n\n\n<p>In this scenario, we are introducing only a combinator function. Combinator functions could represent in this example additional mathematical operations such as subtracting, dividing, generating percentages, generating ratios, etc. Meaning that you could introduce as many combinator functions as possible that modify the result of a given type <code>T<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"How_then_works\"><\/span>How then() works<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Different from <code>and_then()<\/code> and <code>or_else()<\/code>, the <code>then()<\/code> function is part of the <code>FutureExt<\/code> trait.<\/p>\n\n\n\n<p><strong>The <code>then()<\/code> combinator function can execute whenever a <code>Future<\/code> value becomes available after a successful completion of the <code>Future<\/code>. In other words, the logic inside the <code>then()<\/code> function is triggered once the execution of an asynchronous operation successfully completes.<\/strong><\/p>\n\n\n\n<p>You can find the function definition of <code>then()<\/code> in <a href=\"https:\/\/github.com\/rust-lang\/futures-rs\/blob\/42bd7a6d95093beef3660a1025fb6f19f459eb65\/futures-util\/src\/future\/future\/mod.rs#L191-L198\" target=\"_blank\" rel=\"noopener\">here<\/a> or in the following code snippet,<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>fn then&lt;Fut, F&gt;(self, f: F) -&gt; Then&lt;Self, Fut, F&gt;\n    where\n        F: FnOnce(Self::Output) -&gt; Fut,\n        Fut: Future,\n        Self: Sized,\n    {\n        assert_future::&lt;Fut::Output, _&gt;(Then::new(self, f))\n    }<\/code><\/pre>\n\n\n\n<p>which <code>f<\/code> is a closure. Hence, to use the <code>then()<\/code> function, you need to pass a closure.<\/p>\n\n\n\n<p>Below you will find an example of using the <code>then()<\/code> function. <\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>use futures::future::FutureExt;\n\n#&#91;tokio::main]\nasync fn main() {\n    test_then_method().await;\n}\n\nasync fn test_then_method() {\n    let my_future_is_bright = async { String::from(\"bright\") };\n    let my_future_is_not_bright =\n        my_future_is_bright.then(|x| async move { format!(\"{} {}\", String::from(\"not\"), x) });\n\n    assert_eq!(my_future_is_not_bright.await, String::from(\"not bright\"));\n}<\/code><\/pre>\n\n\n\n<p class=\"language-toml has-luminous-vivid-amber-background-color has-background\"><strong>Note:<\/strong> Add <code>futures = \"0.3\"<\/code> and <code>tokio = { version = \"1\", features = [\"full\"] }<\/code> dependencies in the <em>Cargo.toml<\/em> file if you want to execute the run the previous code snippet.<\/p>\n\n\n\n<p>What happens in <code>test_then_method<\/code> function is:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Generate a <code>Future<\/code> that returns a <code>String<\/code> output <code>\"bright\"<\/code>.<\/li><li>Add <code>then()<\/code> combinator function to modify the original future result <code>\"bright\"<\/code> to generate the <code>Future<\/code> result <code>\"not bright\"<\/code> .<\/li><li>Validate the modified <code>Future<\/code> result equals <code>\"not bright\"<\/code> .<\/li><\/ol>\n\n\n\n<p>It is important to reiterate that the <strong>closure passed to the <code>then()<\/code> function will only execute if the previous <code>Future<\/code> successfully completes its asynchronous operation<\/strong>. Otherwise, that closure will never be executed.<\/p>\n\n\n\n<p class=\"language-rust has-vivid-green-cyan-background-color has-background\">Notice the import <code>futures::future::FutureExt;<\/code> . Failing to import the <code>FutureExt<\/code> trait will result in compilation errors as the <code>then()<\/code> function won&#8217;t be available to the <code>my_future_is_bright<\/code> future.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"How_and_then_works\"><\/span>How and_then() works<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>The <code>and_then()<\/code> function is available when implementing the <code>TryFutureExt<\/code> trait.<\/p>\n\n\n\n<p><strong>Then <code>and_then()<\/code> combinator function executes another <code>Future<\/code> if a <code>Future<\/code> successfully completes its asynchronous operations and the value resolved is <code>Ok<\/code> .<\/strong><\/p>\n\n\n\n<p>You can find the function definition of <code>and_then()<\/code> in <a href=\"https:\/\/github.com\/rust-lang\/futures-rs\/blob\/42bd7a6d95093beef3660a1025fb6f19f459eb65\/futures-util\/src\/future\/try_future\/mod.rs#L395-L402\" target=\"_blank\" rel=\"noopener\">here<\/a> or in the following code snippet,<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>fn and_then&lt;Fut, F&gt;(self, f: F) -&gt; AndThen&lt;Self, Fut, F&gt;\n    where\n        F: FnOnce(Self::Ok) -&gt; Fut,\n        Fut: TryFuture&lt;Error = Self::Error&gt;,\n        Self: Sized,\n    {\n        assert_future::&lt;Result&lt;Fut::Ok, Fut::Error&gt;, _&gt;(AndThen::new(self, f))\n    }<\/code><\/pre>\n\n\n\n<p>in which <code>f<\/code> is a closure. Hence, to use the <code>and_then()<\/code> function, you need to pass a closure.<\/p>\n\n\n\n<p>Below you will find an example of using the <code>and_then()<\/code> function.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>use futures::TryFutureExt;\n\n#&#91;tokio::main]\nasync fn main() {\n    test_and_then_method().await;\n}\n\nasync fn test_and_then_method() {\n    let ok_future = async { Ok::&lt;u8, u8&gt;(1) };\n    let updated_ok_future = ok_future.and_then(|x| async move { Ok(x + 5) });\n\n    assert_eq!(updated_ok_future.await, Ok(6));\n}<\/code><\/pre>\n\n\n\n<p class=\"language-toml has-luminous-vivid-amber-background-color has-background\"><strong>Note:<\/strong> Add <code>futures = \"0.3\"<\/code> and <code>tokio = { version = \"1\", features = [\"full\"] }<\/code> dependencies in the <em>Cargo.toml<\/em> file if you want to execute the run the previous code snippet.<\/p>\n\n\n\n<p>What happens in <code>test_and_then_method<\/code> function is:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Generate a <code>Future<\/code> that returns a <code>Ok(1)<\/code>output.<\/li><li>Use the <code>and_then()<\/code> combinator function to modify the original future result <code>Ok(1)<\/code> to generate a new<code>Future<\/code> result <code>Ok(x + 5)<\/code> .<\/li><li>Validate the modified <code>Future<\/code> result equals <code>Ok(x + 5)<\/code> which is <code>Ok(6)<\/code> .<\/li><\/ol>\n\n\n\n<p>Once again, the <strong>closure passed to the <code>and_then()<\/code> function will only execute if the previous <code>Future<\/code> successfully completes its asynchronous operation<\/strong>. Otherwise, that closure will never be executed.<\/p>\n\n\n\n<p><strong>Also, the closure passed to the <code>and_then()<\/code> must resolve an <code>Ok<\/code>  value.<\/strong><\/p>\n\n\n\n<p class=\"language-rust has-vivid-green-cyan-background-color has-background\">Notice the import <code>futures::future::TryFutureExt;<\/code> . Failing to import the <code>TryFutureExt<\/code> trait will result in compilation errors as the <code>and_then()<\/code> function won&#8217;t be available to the <code>ok_future<\/code> future.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"How_or_else_works\"><\/span>How or_else() works<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>The <code>or_else()<\/code> function is available when implementing the <code>TryFutureExt<\/code> trait.<\/p>\n\n\n\n<p>Similar to the <code>then()<\/code> and <code>and_then()<\/code> functions, <strong>the <code>or_else()<\/code> function executes whenever the another <code>Future<\/code> successfully resolves after completing the asynchronous operation. The resolved value must be an <code>Err<\/code>. <\/strong><\/p>\n\n\n\n<p>You can find the function definition of <code>or_else<\/code>() in <a href=\"https:\/\/github.com\/rust-lang\/futures-rs\/blob\/42bd7a6d95093beef3660a1025fb6f19f459eb65\/futures-util\/src\/future\/try_future\/mod.rs#L440-L447\" target=\"_blank\" rel=\"noopener\">here<\/a> or in the following code snippet,<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>fn or_else&lt;Fut, F&gt;(self, f: F) -&gt; OrElse&lt;Self, Fut, F&gt;\n    where\n        F: FnOnce(Self::Error) -&gt; Fut,\n        Fut: TryFuture&lt;Ok = Self::Ok&gt;,\n        Self: Sized,\n    {\n        assert_future::&lt;Result&lt;Fut::Ok, Fut::Error&gt;, _&gt;(OrElse::new(self, f))\n    }<\/code><\/pre>\n\n\n\n<p>which <code>f<\/code> is a closure. Hence, to use the <code>or_else()<\/code> function, you need to pass a closure.<\/p>\n\n\n\n<p>Below you will find an example of using the <code>or_else()<\/code> function.<\/p>\n\n\n\n<pre class=\"wp-block-code language-rust\"><code>use futures::{future::err, TryFutureExt};\n\n#&#91;tokio::main]\nasync fn main() {\n    test_or_else_method().await;\n}\n\nasync fn test_or_else_method() {\n    let err_future = err::&lt;String, String&gt;(String::from(\"Expected Error\"));\n    let updated_err_future = err_future.or_else(|x| async move {\n       Err(\n        format!(\"{} {}\", String::from(\"&#91;Error]\"), x)\n       )\n    });\n\n    assert_eq!(updated_err_future.await, Err(String::from(\"&#91;Error] Expected Error\")));\n}<\/code><\/pre>\n\n\n\n<p class=\"language-toml has-luminous-vivid-amber-background-color has-background\"><strong>Note:<\/strong> Add <code>futures = \"0.3\"<\/code> and <code>tokio = { version = \"1\", features = [\"full\"] }<\/code> dependencies in the <em>Cargo.toml<\/em> file if you want to execute the run the previous code snippet.<\/p>\n\n\n\n<p>What happens in <code>test_and_then_method<\/code> function is:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Generate a <code>Future<\/code> that returns a <code>Ok(String::from(\"Expected Error\"))<\/code>output.<\/li><li>Use the <code>or_else()<\/code> combinator function to modify the original future result <code>Ok(String::from(\"Expected Error\"))<\/code> to generate a new<code>Future<\/code> result<code>Err(format!(\"{} {}\", String::from(\"[Error]\"), x))<\/code><\/li><li>Validate the modified <code>Future<\/code> result resolved value equals <code>Err(String::from(\"[Error] Expected Error\")<\/code> .<\/li><\/ol>\n\n\n\n<p><strong>Remember, the closure passed to the <code>or_else()<\/code> function will only execute if the previous Future successfully completes its asynchronous operation and the value resolved is an <code>Err<\/code>.<\/strong> Otherwise, that closure will never be executed.<\/p>\n\n\n\n<p class=\"language-rust has-vivid-green-cyan-background-color has-background\">Notice the import <code>futures::future::TryFutureExt;<\/code> . Failing to import the <code>TryFutureExt<\/code> trait will result in compilation errors as the <code>or_else()<\/code> function won&#8217;t be available to the <code>err_future<\/code>  future.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Differences_between_then_vs_and_then_vs_or_else\"><\/span>Differences between then() vs and_then() vs or_else()<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>then()<\/th><th>and_then()<\/th><th>or_else()<\/th><\/tr><\/thead><tbody><tr><td>Implemented by the <code>FutureExt<\/code> trait.<\/td><td>Implemented by the <code>TryFutureExt<\/code> trait.<\/td><td>Implemented by the <code>TryFutureExt<\/code> trait.<\/td><\/tr><tr><td>Execution of the closure <code>f<\/code> as long as the previous Future successfully completes the asynchronous operation.<\/td><td>Execution of the closure <code>f<\/code> as long as the previous Future successfully completes the asynchronous operation and resolves a value <code>Ok<\/code>.<\/td><td>Execution of the closure <code>f<\/code> as long as the previous Future successfully completes the asynchronous operation and resolves a value <code>Err<\/code>.<\/td><\/tr><tr><td>It will never execute if previous Future panics<\/td><td>It will never execute if previous Future panics, resolves an <code>Err<\/code> , or is dropped.<\/td><td>It will never execute if previous Future panics, resolves <code>Ok<\/code> , or is dropped.<\/td><\/tr><tr><td>The closure <code>f<\/code> can resolve a different value type from the original Future.<\/td><td>The closure <code>f<\/code> must resolve an <code>Ok<\/code> value.<\/td><td>The closure f must resolve an <code>Err<\/code> value.<\/td><\/tr><\/tbody><\/table><figcaption>comparison table of then(), and_then(), and or_else() functions<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Conclusion\"><\/span>Conclusion<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>All in all, this article explained the differences between combinator functions <code>then()<\/code>, <code>and_then()<\/code> , and <code>or_else()<\/code>. In short, all of the functions will trigger a closure <code>f<\/code> as long as the previous future successfully executes its asynchronous operation. However, the execution closure <code>f<\/code> is dependent on the value resolved from the previous future:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Use <code>then()<\/code> when <code>Future<\/code> successfully resolves.<\/li><li>Use <code>and_then()<\/code> when <code>Future<\/code> successfully resolves an <code>Ok<\/code> .<\/li><li>Use <code>or_else()<\/code> when Future successfully resolves an <code>Err<\/code>.<\/li><\/ul>\n\n\n\n<p>If you need to check the repository with the code examples used in this article, click the following link:<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/arealesramirez\/rust-then--vs-and_then--vs_or_else- \" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/arealesramirez\/rust-then&#8211;vs-and_then&#8211;vs_or_else- <\/a><\/p>\n\n\n\n<p><strong>Did you learn the differences between <code>then()<\/code> , <code>and_then()<\/code> , and <code>or_else()<\/code>?<\/strong><\/p>\n\n\n\n<p>Let me know by sharing your comments on <a href=\"https:\/\/twitter.com\/bbprogrammer\" target=\"_blank\" rel=\"noopener\">Twitter of Become A Better Programmer<\/a> or to <a href=\"https:\/\/twitter.com\/arealesramirez\" target=\"_blank\" rel=\"noopener\">my personal Twitter account<\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-embed aligncenter is-type-rich is-provider-twitter wp-block-embed-twitter\"><div class=\"wp-block-embed__wrapper\">\n<blockquote class=\"twitter-tweet\" data-width=\"550\" data-dnt=\"true\"><p lang=\"en\" dir=\"ltr\">There are several methods available in <a href=\"https:\/\/twitter.com\/hashtag\/rustlang?src=hash&amp;ref_src=twsrc%5Etfw\" target=\"_blank\" rel=\"noopener\">#rustlang<\/a>.<br><br>Frankly honest, this can become overwhelming.<br><br>For instance, do you know the difference between then() vs and_then() vs or_else()?<br><br>No need to go anywhere else! We covered these concepts in this article!<a href=\"https:\/\/t.co\/cH1ekxcloM\">https:\/\/t.co\/cH1ekxcloM<\/a><\/p>&mdash; Become A Better Programmer (@bbprogrammer) <a href=\"https:\/\/twitter.com\/bbprogrammer\/status\/1563304271570817027?ref_src=twsrc%5Etfw\" target=\"_blank\" rel=\"noopener\">August 26, 2022<\/a><\/blockquote><script async src=\"https:\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script>\n<\/div><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>As you learn Rust, you find out more and more functions that sound like they behave in a similar way, when in reality they differ in subtle ways. This is the case for the functions then() , and_then() , and or_else(). No worries, this article will cover each of these methods as well as their &#8230; <a title=\"Rust | Difference between then() vs and_then() vs or_else()\" class=\"read-more\" href=\"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/rust-then-vs-and_then-vs-or_else\/\" aria-label=\"More on Rust | Difference between then() vs and_then() vs or_else()\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":3838,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"nf_dc_page":"","_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[31],"tags":[],"class_list":["post-3829","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-rust","generate-columns","tablet-grid-50","mobile-grid-100","grid-parent","grid-50"],"_links":{"self":[{"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/posts\/3829","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/comments?post=3829"}],"version-history":[{"count":5,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/posts\/3829\/revisions"}],"predecessor-version":[{"id":3869,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/posts\/3829\/revisions\/3869"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/media\/3838"}],"wp:attachment":[{"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/media?parent=3829"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/categories?post=3829"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.becomebetterprogrammer.com\/staging\/4563\/wp-json\/wp\/v2\/tags?post=3829"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}