diff --git a/qi-doc/scribblings/field-guide.scrbl b/qi-doc/scribblings/field-guide.scrbl index 8c98741c..6be4be31 100644 --- a/qi-doc/scribblings/field-guide.scrbl +++ b/qi-doc/scribblings/field-guide.scrbl @@ -308,7 +308,7 @@ Qi aims to produce good error messages that convey what the problem is and clear @bold{Meaning}: The interpreter attempted to apply a function to arguments but found that an argument was not of the expected type. -@bold{Common example}: Using @racket[map] or @racket[filter] without first @racket[(require qi/list)]. The built-in Racket versions are @emph{functions} that expect the input list argument at a specific position (i.e., on the right), whereas the Qi versions are @emph{macros} that are invariant to threading direction and expect precisely one input -- the list itself. +@bold{Common example}: Using @racket[map] or @racket[filter] without first @racket[(require qi/list)]. The built-in Racket versions are @emph{functions} that expect the input list argument at a specific position (i.e., on the right), whereas @seclink["List_Operations"]{the Qi versions} are @emph{macros} that are invariant to threading direction and expect precisely one input -- the list itself. @bold{Common example}: Using a nested flow (such as a @racket[tee] junction or an @racket[effect]) within a right-threading flow and assuming that the input arguments would be passed on the right. At the moment, Qi does not propagate the threading direction to nested clauses. You could either use a fresh right threading form or indicate the argument positions explicitly in the nested flow using an @seclink["Templates_and_Partial_Application"]{argument template}. diff --git a/qi-doc/scribblings/forms.scrbl b/qi-doc/scribblings/forms.scrbl index 38bf91ba..be738e7f 100644 --- a/qi-doc/scribblings/forms.scrbl +++ b/qi-doc/scribblings/forms.scrbl @@ -41,6 +41,7 @@ The full surface syntax of Qi is given below. Note that this expands to a @secli & OR ∥ + ! NOR NAND XNOR diff --git a/qi-doc/scribblings/intro.scrbl b/qi-doc/scribblings/intro.scrbl index 7a490238..7d087cd1 100644 --- a/qi-doc/scribblings/intro.scrbl +++ b/qi-doc/scribblings/intro.scrbl @@ -69,6 +69,29 @@ Qi is a hosted language on the @hyperlink["https://racket-lang.org/"]{Racket pla Additionally, Qi itself uses few and carefully benchmarked dependencies, so that the load-time overhead of @racket[(require qi)] is minimal. +@subsection{About Qi's Release Practices} + +Qi breaks with traditional Racket package development and occasionally ships breaking changes in a @hyperlink["https://semver.org/"]{SemVer}-style major release. For that reason, in some cases when using Qi as a dependency, it is advisable to pin to a Qi tag using a Git @tech{package source} rather than follow the main "qi" Racket @tech{package source}. Keep reading for details and examples. + +Qi follows the @hyperlink["http://timothyfitz.com/2009/02/10/continuous-deployment-at-imvu-doing-the-impossible-fifty-times-a-day/"]{continuous deployment} model of development. This means that fresh changes are pushed to the main branch of development after they pass a rigorous and comprehensive suite of tests and thorough code review. Additionally, Qi packages on the Racket package index point to this main branch on the source host, so that running @racket[raco pkg install qi] or @racket[raco pkg update qi] will always get the version on the @racket[main] branch, reflecting the latest improvements. + +This doesn't mean that you must use this version, however. The expressiveness of modern version control systems allows us to define diverse versioning protocols directly on the versioning backend (e.g., Git) to best support diverse usage needs. Towards this end, Qi follows these conventions: + +@itemlist[#:style 'ordered + @item{Each significant new release has a tagged version, which is static and immutable.} + @item{Each legacy release has a "maintenance" branch that will be stable without any backwards incompatible changes or new features, and will be supported with bug fixes as needed.} +] + +Now, traditionally, we may have grown accustomed to depending on a certain version of a package "or newer" (as are the semantics of using a Racket, rather than Git, @tech{package source}), so that we never have to update the dependency specification to get the latest improvements. We believe that this convention needlessly overburdens development while threatening application stability, requiring us to choose one or the other. + +But instead, by relying on a version with either of the above semantics, we gain stability and flexibility as users of Qi without compromising the freedom to innovate and remedy past missteps for developers of Qi. This style of dependency can be accomplished by using a Git @tech{package source} in your @racket[info.rkt], instead of a Racket @tech{package source}. Like this: + +@codeblock{ + (define deps '("git://github.com/drym-org/qi.git#v5.0")) +} + +In addition, as part of each release, backwards incompatibilities are publicly announced and an effort is made to work with dependent package and application developers to ensure compatibility with the latest release, further bridging the gap to Racket's package management practices. Thus, in practice, outside of a production deployment, relying on the Racket @tech{package source} should be fine. + @section{Relationship to the Threading Macro} The usual threading macro in @seclink["top" #:indirect? #t #:doc '(lib "scribblings/threading.scrbl")]{Threading Macros} is a purely syntactic transformation that does not make any assumptions about the expressions being threaded through, so that it works out of the box for threading values through both functions as well as macros. On the other hand, Qi is primarily oriented around @emph{functions}, and @tech{flows} are expected to be @seclink["What_is_a_Flow_"]{function-valued}. Threading values through macros using Qi requires special handling. diff --git a/qi-doc/scribblings/principles.scrbl b/qi-doc/scribblings/principles.scrbl index b4ec1dfc..95f180d3 100644 --- a/qi-doc/scribblings/principles.scrbl +++ b/qi-doc/scribblings/principles.scrbl @@ -163,7 +163,6 @@ Qi flow expressions expand to a small core language which is then @seclink["It_s (or floe ...) (not floe) NOT - ! XOR ground (thread floe ...) diff --git a/qi-doc/scribblings/qi.scrbl b/qi-doc/scribblings/qi.scrbl index b59dd460..055e1d70 100644 --- a/qi-doc/scribblings/qi.scrbl +++ b/qi-doc/scribblings/qi.scrbl @@ -32,7 +32,7 @@ Start by @seclink["Using_These_Docs"]{getting your bearings}. For an overview of @section{Using These Docs} -@secref["Introduction_and_Usage"] provides a high-level overview and includes installation and setup instructions. Learn the language by going through the @secref["Tutorial"], and read @secref["When_Should_I_Use_Qi_"] for examples illustrating its use. The many ways in which Qi may be used from the host language (e.g. Racket), as well as the ways in which Qi may be used in tandem with other DSLs, are described in @secref["Language_Interface"]. The various built-in forms of the language are documented in @secref["Qi_Forms"], while @secref["Qi_Macros"] covers using macros to extend the language by adding new features or implementing new DSLs. @secref["Principles_of_Qi"] provides a theoretical foundation to develop a sound intuition for Qi, and the @secref["Field_Guide"] contains practical advice. @secref["Flowing_with_the_Flow"] contains recommendations on editor configuration to help you to write Qi effectively. +@secref["Introduction_and_Usage"] provides a high-level overview and includes installation and setup instructions. Learn the language by going through the @secref["Tutorial"], and read @secref["When_Should_I_Use_Qi_"] for examples illustrating its use. The many ways in which Qi may be used from the host language (e.g. Racket), as well as the ways in which Qi may be used in tandem with other DSLs, are described in @secref["Language_Interface"]. The various built-in forms of the language are documented in @secref["Qi_Forms"], while @secref["Qi_Macros"] covers using macros to extend the language by adding new features or implementing new DSLs, and @secref["List_Operations"] describes forms for expressing optimized list-oriented operations. @secref["Principles_of_Qi"] provides a theoretical foundation to develop a sound intuition for Qi, and the @secref["Field_Guide"] contains practical advice. @secref["Flowing_with_the_Flow"] contains recommendations on editor configuration to help you to write Qi effectively. This site hosts @emph{user} documentation. If you are interested in contributing to Qi development you may be interested in the @emph{developer} documentation at the @hyperlink["https://github.com/drym-org/qi/wiki"]{Qi Wiki}. The wiki is also your one-stop shop for keeping up with planned events in the Qi community. diff --git a/qi-doc/scribblings/using-qi.scrbl b/qi-doc/scribblings/using-qi.scrbl index baa6384c..5ba08e48 100644 --- a/qi-doc/scribblings/using-qi.scrbl +++ b/qi-doc/scribblings/using-qi.scrbl @@ -208,6 +208,8 @@ The equivalent Qi flow is: (~> (filter odd?) (map sqr))) } +Note that @racket[filter] and @racket[map] here are the ones from @racketmodname[qi/list]. + Here, under the hood, each element of the input list is processed one at a time, with both of these functions being invoked on it in sequence, and then the output list is constructed by accumulating these individual results. This ensures that no intermediate lists are constructed along the way and that the input list is traversed just once -- a standard optimization technique called "stream fusion" or "deforestation." The Qi version produces the same result as the Racket code above, but it can be both faster as well as more memory-efficient, especially on large input lists. Note however that if the functions used in @racket[filter] and @racket[map] are not @emph{pure}, that is, if they perform side effects like printing to the screen or writing to a file, then the Qi flow would exhibit a different @seclink["Order_of_Effects"]{order of effects} than the Racket version. @section{Curbing Curries and Losing Lambdas}