From mboxrd@z Thu Jan  1 00:00:00 1970
Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail
From: Tomas Volf <wolf@wolfsden.cz>
Newsgroups: gmane.lisp.guile.devel
Subject: [PATCH v2] doc: Extend documentation for (ice-9 match)
Date: Sun, 15 Oct 2023 20:39:23 +0200
Message-ID: <20231015184127.7089-1-wolf@wolfsden.cz>
Mime-Version: 1.0
Content-Transfer-Encoding: 8bit
Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214";
	logging-data="35618"; mail-complaints-to="usenet@ciao.gmane.io"
Cc: Tomas Volf <wolf@wolfsden.cz>
To: guile-devel@gnu.org
Original-X-From: guile-devel-bounces+guile-devel=m.gmane-mx.org@gnu.org Sun Oct 15 20:42:09 2023
Return-path: <guile-devel-bounces+guile-devel=m.gmane-mx.org@gnu.org>
Envelope-to: guile-devel@m.gmane-mx.org
Original-Received: from lists.gnu.org ([209.51.188.17])
	by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
	(Exim 4.92)
	(envelope-from <guile-devel-bounces+guile-devel=m.gmane-mx.org@gnu.org>)
	id 1qs640-00094b-8l
	for guile-devel@m.gmane-mx.org; Sun, 15 Oct 2023 20:42:08 +0200
Original-Received: from localhost ([::1] helo=lists1p.gnu.org)
	by lists.gnu.org with esmtp (Exim 4.90_1)
	(envelope-from <guile-devel-bounces@gnu.org>)
	id 1qs63c-00078C-Us; Sun, 15 Oct 2023 14:41:45 -0400
Original-Received: from eggs.gnu.org ([2001:470:142:3::10])
 by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.90_1) (envelope-from <ws@wolfsnet.cz>) id 1qs63a-00077z-RJ
 for guile-devel@gnu.org; Sun, 15 Oct 2023 14:41:42 -0400
Original-Received: from wolfsden.cz ([37.205.8.62])
 by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
 (Exim 4.90_1) (envelope-from <ws@wolfsnet.cz>) id 1qs63Y-0001Sn-F0
 for guile-devel@gnu.org; Sun, 15 Oct 2023 14:41:42 -0400
Original-Received: by wolfsden.cz (Postfix, from userid 104)
 id F3C3A26C94D; Sun, 15 Oct 2023 18:41:35 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=wolfsden.cz; s=mail;
 t=1697395296; bh=XMGhmC2+m9bZ+afvQHgO57gjFkZaiQfARw1fcQli9nQ=;
 h=From:To:Cc:Subject:Date;
 b=EGDPsrc7KJs+RD975q8yRZyreE8w5Kqjlt5Z/zQBNbuDRuqJvc6SljPj+X9K3H1EL
 9rs1wDwlgCA9uyam54ok3TbdwqMG0CLSDqOqZVF3Q0mUQW1td3SV8XXNMWt1rXgeiT
 C3pHf9hW7OHwBc46OnrV0wufUDZeKTlJVB5y8p5tNX+mwPoHuhiIELm+Mu5lTz7UKf
 vA1MCEJWyx9M3f/s3Qq5D32L0e5VUPq8Ml3VM+tULM39DhQO8JoMXdZ8zETJM1OP1I
 EM5LnKuDs+p1iCG4a7SrXRDHnPJK0f1snYxvvYQ68Tsiy7tgW0AFKE/uhMdL3jsjmN
 usxGEwUF6u01U3KSYq6jXHYP8zqVYiJ4y2AIPuQPlhN11OvQzyqVDU3XuHKJqP1Y1r
 yqBPlH3MvVqMnuo2HyYX0cL3swFRKa/v9oLYiweK9wt7Fj41e4V1eegdbBA2nXm5cX
 S1RvuSKL7+XrOxA1YiljwlAX3y+54aYjHITAu/94EGYX7fP25gblZV5bk8BnEkwd/0
 laPmddJdjUosDn4wZhmq49Yl0bO2jBnGu4JBZGforUrjWpo42PYa0/TJ20ORwOmZyZ
 5F+bBvwIi2j7mNM/nR10tvle8ZLC7AlZ27BORTW2iawyNIyQ+inSZyagJuF+rBuVYN
 hU1jhSu0y5BoVWL16W/NoYyU=
Original-Received: from localhost (unknown [146.70.134.168])
 by wolfsden.cz (Postfix) with ESMTPSA id 6E15826D595;
 Sun, 15 Oct 2023 18:41:35 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=wolfsden.cz; s=mail;
 t=1697395295; bh=XMGhmC2+m9bZ+afvQHgO57gjFkZaiQfARw1fcQli9nQ=;
 h=From:To:Cc:Subject:Date;
 b=tekwFhkwkAvaitWCASu7hADZuczVawHRAFC+PQBLTIVeW4q8yg+YelpPsggIyDvIY
 p9won0eGvTb22m4RSgGMgB5rCyWcMq9UrJT0VHWiitVT4vnCVcxUUYzj1fDDTFPKhr
 YRTFWTaVgg4VYzcvddGXMev9h/23pBHHAmnRe0xFpHOMzkFDRBGIEUCx8oUh/qOiJQ
 ePWvWjXtoYH1MBihCslQ68eWgUkGqJ6GD6ozpBKZQ/axP1LeS4uSFN26xuUX7Dmyg/
 h3/R6YSUyRvN2WvXtOSxze5C3S/b3KXpBAWwyu0vvpQKCftGxdASzTiUWNzSThBXsG
 MfVLPjcPfggOEqDMBwoo0M6vZ4lyXHg6pqkjHXwULxk8vCgce7aTKuMUs7Psnf1pWG
 zeKi9kQfco2Jq89QQI9YtZzs9V01uf7X7cLAuHP/Ik132/kQtUI/IULZxQXRMReXAQ
 z9wkzsHvrHDn+0Sr1a8a8GysuzVEgA04pvM9Dk1mbxMOEoNMGh9hXyt7aRlEWqeW2M
 7MocUUGFYuHjDA/zxgLOAbyuAWc+hEX+ZgDnObijwV1yGEqcOgVXEw6d21get1PBwp
 i9n3vWBBtN0X2tglqgLpOoaOKgXT8s4A6hUdbnaF0elMVszVFZoozl7VzI2b1W0Co/
 W7Cbo810wHMShxnzspKRbSGI=
Original-Received: from localhost (localhost [local])
 by localhost (OpenSMTPD) with ESMTPA id 2cde413f;
 Sun, 15 Oct 2023 18:41:34 +0000 (UTC)
X-Mailer: git-send-email 2.41.0
Received-SPF: none client-ip=37.205.8.62; envelope-from=ws@wolfsnet.cz;
 helo=wolfsden.cz
X-Spam_score_int: -16
X-Spam_score: -1.7
X-Spam_bar: -
X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1,
 DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.25,
 SPF_HELO_PASS=-0.001, SPF_NONE=0.001,
 UNPARSEABLE_RELAY=0.001 autolearn=no autolearn_force=no
X-Spam_action: no action
X-BeenThere: guile-devel@gnu.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: "Developers list for Guile,
 the GNU extensibility library" <guile-devel.gnu.org>
List-Unsubscribe: <https://lists.gnu.org/mailman/options/guile-devel>,
 <mailto:guile-devel-request@gnu.org?subject=unsubscribe>
List-Archive: <https://lists.gnu.org/archive/html/guile-devel>
List-Post: <mailto:guile-devel@gnu.org>
List-Help: <mailto:guile-devel-request@gnu.org?subject=help>
List-Subscribe: <https://lists.gnu.org/mailman/listinfo/guile-devel>,
 <mailto:guile-devel-request@gnu.org?subject=subscribe>
Errors-To: guile-devel-bounces+guile-devel=m.gmane-mx.org@gnu.org
Original-Sender: guile-devel-bounces+guile-devel=m.gmane-mx.org@gnu.org
Xref: news.gmane.io gmane.lisp.guile.devel:22028
Archived-At: <http://permalink.gmane.org/gmane.lisp.guile.devel/22028>

Extend the documentation for (ice-9 match) module with explanations of
some of the patterns and also provide more examples for them.  That
should make it more useful for people trying to use the module for the
first time just based on the documentation.

* doc/ref/match.texi (Pattern Matching): Explain some patterns and
provide more examples.
---
Incorporate feedback from the review, mainly:
- drop myself from THANKS file, someone else can thank me if they want to
- remove most of unnecessary lets
- spelling and wording fixes
- add new paragraph describing (and ...)

 doc/ref/match.texi | 84 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 84 insertions(+)

diff --git a/doc/ref/match.texi b/doc/ref/match.texi
index f5ea43118..6e43d59b1 100644
--- a/doc/ref/match.texi
+++ b/doc/ref/match.texi
@@ -181,6 +181,90 @@ The names @code{quote}, @code{quasiquote}, @code{unquote},
 @code{or}, @code{not}, @code{set!}, @code{get!}, @code{...}, and
 @code{___} cannot be used as pattern variables.
 
+@code{string}, @code{number}, and others refer to literal strings,
+numbers, and others.  Therefore, the pattern @code{string} binds the
+value to the identifier @code{string} and the pattern @code{"string"}
+matches if the value is @code{"string"}.  An example demonstrating this
+(by using very bad naming):
+
+@example
+(match "foo"
+  (number number))
+@result{} "foo"
+@end example
+
+The field operator (@code{(= field pat)}) has no relation to the fields
+of records.  The @code{field} should be an expression evaluating to a
+procedure taking a single argument, and @code{pat} is matched against
+the return value.  Simple example:
+
+@example
+(match '(1 2)
+  ((= cadr x)
+   x))
+@result{} 2
+@end example
+
+The record operator(@code{($ record-name pat_1 ... pat_n)}) can be used
+for matching records.  Patterns are matched against the slots in order,
+not all have to be present, and there is no way to skip a slot.  An
+example demonstrating the usage:
+
+@example
+(define-record-type <foo>
+  (make-foo bar baz zab)
+  foo?
+  (bar foo-bar)
+  (baz foo-baz)
+  (zab foo-zab))
+
+(let ((obj (make-foo 1 '2 "three")))
+  (match obj
+    ;; Make sure obj is a <foo> instance, with bar slot being a number
+    ;; and zab slot being a string.  We do not care about baz slot,
+    ;; therefore we use _ to match anything.
+    (($ <foo> (? number?) _ (? string?))
+     "ok")))
+@result{} "ok"
+@end example
+
+If you need to ensure that a value is of a specific record type and at
+the same time bind it to a variable, the record operator will not be
+enough by itself, since you can only capture the fields.  You would need
+to combine it with other patterns, for example @code{(? foo? obj)}.
+
+When you need to apply multiple patterns, or a check and a pattern, you
+can use (@code{(? predicate pat_1 ... pat_n)}) for that.  The patterns
+are evaluated as if in the @code{(and ...)}.  If, for example, you want
+to check whether something is a symbol and at the same time bind the
+value to a variable, it could look like this:
+
+@example
+(match '(delete . some-id)
+  (('delete . (? symbol? id))
+   ;; We now could, for example, use the id to delete from some alist.
+   id))
+@result{} some-id
+@end example
+
+The @code{(and ...)} is of course useful as well, especially if no
+predicate is required.  While you could use @code{(const #t)} as the
+predicate, using @code{(and ...)} is better.  For example, capturing an
+object iff it is a list of at least two items can be done like this:
+
+@example
+(match '(foo baz bar)
+  ((and (a b ...) lst)
+   lst))
+@result{} (foo baz bar)
+@end example
+
+@c FIXME: Remove this remark once everything is clearly described and
+@c consulting the comment is no longer necessary.
+If you are unclear about how something works, you can try consulting the
+large comment at the top of the @code{module/ice-9/match.upstream.scm}
+file in your guile distribution.
+
 Here is a more complex example:
 
 @example
-- 
2.41.0