{"id":256,"date":"2016-06-09T08:18:19","date_gmt":"2016-06-09T08:18:19","guid":{"rendered":"http:\/\/www.rangakrish.com\/?p=256"},"modified":"2016-06-09T11:06:00","modified_gmt":"2016-06-09T11:06:00","slug":"pattern-matching-with-optima-lisp-library","status":"publish","type":"post","link":"https:\/\/www.rangakrish.com\/index.php\/2016\/06\/09\/pattern-matching-with-optima-lisp-library\/","title":{"rendered":"Pattern Matching with Optima Lisp Library"},"content":{"rendered":"<p>In the previous two posts, we looked at external tools and libraries that can be used along with <a href=\"https:\/\/opusmodus.com\" target=\"_blank\"><strong>Opusmodus<\/strong><\/a> for algorithmic composition. In this post, I want to introduce\u00a0another interesting Lisp library called <a href=\"https:\/\/github.com\/m2ym\/optima\" target=\"_blank\"><strong>Optima<\/strong><\/a>.<\/p>\n<p>Optima is a powerful library for pattern matching. Often, when we talk of pattern matching, the topic revolves around <a href=\"https:\/\/en.wikipedia.org\/wiki\/Regular_expression\">regular expressions<\/a>. No doubt, regular expressions are quite\u00a0powerful and are widely used. However, in the context of Lisp, we have one more possible use case, that of pattern matching within S-expressions. One of the best introductions to this can be found in the book <a href=\"http:\/\/norvig.com\/paip.html\" target=\"_blank\"><strong>Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp<\/strong><\/a> by <strong>Peter Norvig<\/strong>. The Lisp code used in the book is available <a href=\"http:\/\/norvig.com\/paip\/README.html\" target=\"_blank\">here<\/a>. It is a great\u00a0place to start if you are new to S-expression pattern matching.<\/p>\n<p>Optima is far more powerful and capable than the system described in PAIP. In this and the next few posts, I will walk you through\u00a0its capabilities.<\/p>\n<p>The main top-level matcher is the <em><strong>match<\/strong><\/em> macro:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>match argument &amp;body clauses<\/strong><\/em><\/p>\n<p>Here, the argument is matched against clauses. Each element of the clauses is of the type<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>(&lt;pattern&gt; . &lt;action&gt;)<\/strong><\/em><\/p>\n<p>If the argument matches the <em><strong>&lt;pattern&gt;<\/strong><\/em>, the corresponding <em><strong>&lt;action&gt;<\/strong><\/em> is evaluated and the value returned from <em><strong>match<\/strong><\/em>. <em><strong>&lt;action&gt;<\/strong><\/em> is an implicit <em><strong>progn<\/strong><\/em>.<\/p>\n<p>Let us start by looking at a very simple example:<\/p>\n<p style=\"padding-left: 30px;\"><strong>(match 1<\/strong><\/p>\n<p style=\"padding-left: 30px;\"><strong>\u00a0\u00a0 \u00a0 \u00a0 (0 &#8220;Zero&#8221;)<\/strong><\/p>\n<p style=\"padding-left: 30px;\"><strong>\u00a0\u00a0 \u00a0 \u00a0 (x (print x) (1+ x)))<\/strong><\/p>\n<p>In this example, <em><strong>argument<\/strong><\/em> is 1. There are two clauses. The first clause has a constant pattern of <em><strong>0<\/strong><\/em>, and if it matches the incoming argument, then <em><strong>&#8220;Zero&#8221;<\/strong><\/em> is returned. In this case, the second clause pattern will match. It is a variable pattern and will match any argument. The <em><strong>&lt;action&gt;<\/strong><\/em> here is printing the matched value as bound to the variable <em><strong>x<\/strong><\/em> and then returning <em>one plus that value<\/em>. Notice that the clauses are tried in the given lexical order, and the first match causes the remaining clauses to be ignored. If the form <em><strong>(fail)<\/strong><\/em> is executed as part of any clause, then that clause is deemed to have failed.<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>(match 100\u00a0<\/strong><\/em><\/p>\n<p style=\"padding-left: 30px;\"><em><strong>\u00a0\u00a0 \u00a0 \u00a0 (100 (print &#8220;matches 100&#8221;) (fail))<\/strong><\/em><\/p>\n<p style=\"padding-left: 30px;\"><em><strong>\u00a0\u00a0 \u00a0 \u00a0 (x x))<\/strong><\/em><\/p>\n<p>In this case, the first pattern matches, but because the action invokes <em><strong>(fail)<\/strong><\/em>, the first clause <strong>failed<\/strong> and the next clause is tried. Since the second pattern is a variable, it matches anything, and the value returned is whatever it matches (i.e., 100).<\/p>\n<p>If no pattern matches the incoming argument, <em><strong>match<\/strong><\/em> returns nil. If you explicitly wish to handle the <strong>no match<\/strong> case, you can have the special pattern <em><strong>otherwise<\/strong><\/em> as the last pattern, which will match any argument.<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>(match 1<\/strong><\/em><\/p>\n<p style=\"padding-left: 30px;\"><em><strong>\u00a0\u00a0 \u00a0 \u00a0 (0 &#8220;Zero&#8221;)<\/strong><\/em><\/p>\n<p style=\"padding-left: 30px;\"><em><strong>\u00a0\u00a0 \u00a0 \u00a0 (2 2)<\/strong><\/em><\/p>\n<p style=\"padding-left: 60px;\"><em><strong>(otherwise -1))<\/strong><\/em><\/p>\n<p>This will return <em><strong>-1<\/strong><\/em>. Since the order of clauses is important and since <em><strong>otherwise<\/strong><\/em> matches everything, it usually makes sense to keep\u00a0it\u00a0in\u00a0the last clause.<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>(match 2<\/strong><\/em><\/p>\n<p style=\"padding-left: 30px;\"><em><strong>\u00a0\u00a0 \u00a0 \u00a0 (0 &#8220;Zero&#8221;)<\/strong><\/em><\/p>\n<p style=\"padding-left: 60px;\"><em><strong>(otherwise -1)<\/strong><\/em><\/p>\n<p style=\"padding-left: 30px;\"><em><strong>\u00a0\u00a0 \u00a0 \u00a0 (2 2))<\/strong><\/em><\/p>\n<p>This will return <em><strong>-1<\/strong><\/em> and not <em><strong>2<\/strong><\/em>, even though the last clause is a better match. <em>So watch out.<\/em><\/p>\n<p>Instead of <em><strong>otherwise<\/strong><\/em>, since an unconstrained variable can match anything, you can have it as the last pattern as an escape clause. Even simpler is the use of the underscore character <strong>&#8220;_&#8221;<\/strong> which denotes an <em>unnamed<\/em> variable.<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>(match 1<\/strong><\/em><\/p>\n<p style=\"padding-left: 30px;\"><em><strong>\u00a0\u00a0 \u00a0 \u00a0 (0 &#8220;Zero&#8221;)<\/strong><\/em><\/p>\n<p style=\"padding-left: 30px;\"><em><strong>\u00a0\u00a0 \u00a0 \u00a0 (2 2)<\/strong><\/em><\/p>\n<p style=\"padding-left: 60px;\"><em><strong>(_ -1))<\/strong><\/em><\/p>\n<h2><span style=\"text-decoration: underline;\"><b>Simple Patterns<\/b><\/span><\/h2>\n<p>Let us look at examples of simple patterns involving numbers, symbols and strings.<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>(match 12.34<\/strong><\/em><\/p>\n<p style=\"padding-left: 60px;\"><em><strong>(x (values (round x))))<\/strong><\/em><\/p>\n<p style=\"padding-left: 30px;\"><em><strong>=&gt; 12<\/strong><\/em><\/p>\n<p>Here, the variable pattern matches anything and the clause returns the rounded value.<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>(match &#8220;foobar&#8221;<\/strong><\/em><\/p>\n<p style=\"padding-left: 60px;\"><em><strong>((and (type string) x ) (format nil &#8220;Hello &#8211; ~A&#8221; x)))<\/strong><\/em><\/p>\n<p style=\"padding-left: 30px;\"><em><strong>=&gt; &#8220;Hello &#8211; foobar&#8221;<\/strong><\/em><\/p>\n<p>Notice the use of <em><strong>and<\/strong><\/em> to combine multiple sub patterns, and also the <em><strong>type<\/strong><\/em> qualifier to specify the expected type of argument. Only if the argument is a string, the pattern will match, binding the variable <em><strong>x<\/strong><\/em>\u00a0to the supplied argument. The action part of the clause essentially concatenates two strings, and this is the value returned from the clause and the match function.<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>(match 100\u00a0<\/strong><\/em><\/p>\n<p style=\"padding-left: 60px;\"><em><strong>((satisfies evenp) \u2018even)<\/strong><\/em><\/p>\n<p style=\"padding-left: 60px;\"><em><strong>((satisfies oddp) \u2018odd))<\/strong><\/em><\/p>\n<p style=\"padding-left: 30px;\"><em><strong>=&gt; even<\/strong><\/em><\/p>\n<p>The <em><strong>satisfies<\/strong><\/em> pattern applies a predicate on the incoming argument to see if it is a valid match. Instead of a predefined predicate you can have a lambda as well.<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>(match 10<\/strong><\/em><\/p>\n<p style=\"padding-left: 30px;\"><em><strong>\u00a0\u00a0 \u00a0 \u00a0 ((satisfies (lambda (x) (and (&gt; x 0) (&lt; x 100)))) t))<\/strong><\/em><\/p>\n<p style=\"padding-left: 30px;\"><em><strong>=&gt; t<\/strong><\/em><\/p>\n<p>Here the pattern checks if the given number is greater than zero and less than 100.<\/p>\n<p>You can use <em><strong>not<\/strong><\/em> to check for the negation of a condition:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>(match &#8220;hello&#8221;<\/strong><\/em><\/p>\n<p style=\"padding-left: 30px;\"><em><strong>\u00a0\u00a0 \u00a0 \u00a0 ((not (equal &#8220;hi&#8221;)) t))<\/strong><\/em><\/p>\n<p style=\"padding-left: 30px;\"><em><strong>=&gt; t<\/strong><\/em><\/p>\n<p>Since the argument is <em><strong>\u201chello\u201d<\/strong><\/em> and not <em><strong>\u201chi\u201d<\/strong><\/em>, it succeeds and returns t.<\/p>\n<p>In addition to <em><strong>and<\/strong><\/em> and <em><strong>not<\/strong><\/em>, we can also use <em><strong>or<\/strong><\/em>:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>(match &#8220;hello&#8221;<\/strong><\/em><\/p>\n<p style=\"padding-left: 30px;\"><em><strong>\u00a0\u00a0 \u00a0 \u00a0 ((not (equal &#8220;hello&#8221;)) \u2018hi)<\/strong><\/em><\/p>\n<p style=\"padding-left: 30px;\"><em><strong>\u00a0\u00a0 \u00a0 \u00a0 ((or (and (type string) (equal &#8220;hello&#8221;)) (equal &#8220;dear&#8221;)) t))<\/strong><\/em><\/p>\n<p style=\"padding-left: 30px;\"><em><strong>=&gt; t<\/strong><\/em><\/p>\n<p>Here, the second clause pattern is satisfied.<\/p>\n<p>Quite interesting, isn&#8217;t it? Well, there are many more pattern matching features in Optima. We will continue our\u00a0discussion in the next post.<\/p>\n<p>Bye, till then. Take care.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the previous two posts, we looked at external tools and libraries that can be used along with Opusmodus for algorithmic composition. In this post, I want to introduce\u00a0another interesting Lisp library called Optima. Optima is a powerful library for pattern matching. Often, when we talk of pattern matching, the topic revolves around regular expressions. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[18,17],"tags":[61,62],"class_list":["post-256","post","type-post","status-publish","format-standard","hentry","category-lisp","category-programming","tag-optima","tag-pattern-matching"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p9OLnF-48","jetpack-related-posts":[{"id":268,"url":"https:\/\/www.rangakrish.com\/index.php\/2016\/06\/29\/pattern-matching-with-optima-lisp-library-part-3\/","url_meta":{"origin":256,"position":0},"title":"Pattern Matching with Optima Lisp Library &#8211; Part 3","author":"admin","date":"June 29, 2016","format":false,"excerpt":"In the previous two posts on this topic, I explained some of the basic pattern matching facilities of Optima\u00a0library. There are many\u00a0more advanced features in the library and I will try to discuss them in future posts. In today\u2019s post, I will outline a straightforward application of the library for\u2026","rel":"","context":"In &quot;LISP&quot;","block_context":{"text":"LISP","link":"https:\/\/www.rangakrish.com\/index.php\/category\/lisp\/"},"img":{"alt_text":"Optima Example","src":"https:\/\/i0.wp.com\/www.rangakrish.com\/wp-content\/uploads\/2016\/06\/Optima-Example-1024x622.png?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.rangakrish.com\/wp-content\/uploads\/2016\/06\/Optima-Example-1024x622.png?resize=350%2C200 1x, https:\/\/i0.wp.com\/www.rangakrish.com\/wp-content\/uploads\/2016\/06\/Optima-Example-1024x622.png?resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.rangakrish.com\/wp-content\/uploads\/2016\/06\/Optima-Example-1024x622.png?resize=700%2C400 2x"},"classes":[]},{"id":263,"url":"https:\/\/www.rangakrish.com\/index.php\/2016\/06\/17\/pattern-matching-with-optima-lisp-library-part-2\/","url_meta":{"origin":256,"position":1},"title":"Pattern Matching with Optima Lisp Library &#8211; Part 2","author":"admin","date":"June 17, 2016","format":false,"excerpt":"Let us continue where we left off last time. List Patterns If the incoming argument is a list, then we can use two types of list patterns to match the list elements, namely, list and list*. (match '(a b c)\u00a0 ((list 'a 'b X) X)) => c This list pattern\u2026","rel":"","context":"In &quot;LISP&quot;","block_context":{"text":"LISP","link":"https:\/\/www.rangakrish.com\/index.php\/category\/lisp\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2377,"url":"https:\/\/www.rangakrish.com\/index.php\/2021\/04\/12\/book-review-programming-algorithms-in-lisp\/","url_meta":{"origin":256,"position":2},"title":"Book Review: Programming Algorithms in Lisp","author":"admin","date":"April 12, 2021","format":false,"excerpt":"Title: Programming Algorithms in Lisp: Writing Efficient Programs with Examples in ANSI Common Lisp Author: Vsevolod Domkin Publisher: Apress Year: 2021 It is only about 5 months since I read and reviewed\u00a0a good book on Lisp written by Micha\u0142 \u201cphoe\u201d Herda. The present book is by Vsevolod Domkin\u00a0and I purchased\u2026","rel":"","context":"In &quot;Book Review&quot;","block_context":{"text":"Book Review","link":"https:\/\/www.rangakrish.com\/index.php\/category\/book-review\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.rangakrish.com\/wp-content\/uploads\/2021\/04\/Book-Cover-209x300.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":2927,"url":"https:\/\/www.rangakrish.com\/index.php\/2022\/10\/20\/why-learn-lisp\/","url_meta":{"origin":256,"position":3},"title":"Why Learn Lisp?","author":"admin","date":"October 20, 2022","format":false,"excerpt":"In the last article, I had shared my views on why programmers should learn Prolog, preferably as the first language. What language should one learn next? I strongly pitch for Lisp, to be precise, \u201cCommon Lisp\u201d. Lisp happens to be the second oldest (1958) programming language, only after Fortran (1957)!\u2026","rel":"","context":"In &quot;LISP&quot;","block_context":{"text":"LISP","link":"https:\/\/www.rangakrish.com\/index.php\/category\/lisp\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":3312,"url":"https:\/\/www.rangakrish.com\/index.php\/2024\/01\/28\/the-hy-programming-language\/","url_meta":{"origin":256,"position":4},"title":"The Hy Programming Language","author":"admin","date":"January 28, 2024","format":false,"excerpt":"In an earlier article\u00a0I had explained how to execute Python code from within Common Lisp using \u201cCLPython\u201d package. In contrast to that approach, \u201cHy\u201d\u00a0is a Lisp-style language (not compatible with Common Lisp) that is embedded in Python and hence provides seamless interoperability with Python code. Installation is straightforward (it is\u2026","rel":"","context":"In &quot;Hy Language&quot;","block_context":{"text":"Hy Language","link":"https:\/\/www.rangakrish.com\/index.php\/category\/hy-language\/"},"img":{"alt_text":"Hy REPL","src":"https:\/\/i0.wp.com\/www.rangakrish.com\/wp-content\/uploads\/2024\/01\/console-300x148.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":2057,"url":"https:\/\/www.rangakrish.com\/index.php\/2020\/07\/19\/calling-lisp-functions-from-elixir\/","url_meta":{"origin":256,"position":5},"title":"Calling Lisp Functions from Elixir","author":"admin","date":"July 19, 2020","format":false,"excerpt":"In the last article\u00a0I showed how we can simulate the idea of Lisp's \"closure\" in Elixir. Today, I would like to demonstrate how we can call Lisp functions from Elixir using the NIF interface. What is the need to integrate Elixir with another language? I can think of two reasons:\u2026","rel":"","context":"In &quot;Elixir&quot;","block_context":{"text":"Elixir","link":"https:\/\/www.rangakrish.com\/index.php\/category\/elixir\/"},"img":{"alt_text":"Using the Lisp Functions","src":"https:\/\/i0.wp.com\/www.rangakrish.com\/wp-content\/uploads\/2020\/07\/Session.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.rangakrish.com\/wp-content\/uploads\/2020\/07\/Session.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.rangakrish.com\/wp-content\/uploads\/2020\/07\/Session.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/www.rangakrish.com\/wp-content\/uploads\/2020\/07\/Session.jpg?resize=700%2C400&ssl=1 2x"},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.rangakrish.com\/index.php\/wp-json\/wp\/v2\/posts\/256","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.rangakrish.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.rangakrish.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.rangakrish.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.rangakrish.com\/index.php\/wp-json\/wp\/v2\/comments?post=256"}],"version-history":[{"count":0,"href":"https:\/\/www.rangakrish.com\/index.php\/wp-json\/wp\/v2\/posts\/256\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.rangakrish.com\/index.php\/wp-json\/wp\/v2\/media?parent=256"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.rangakrish.com\/index.php\/wp-json\/wp\/v2\/categories?post=256"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.rangakrish.com\/index.php\/wp-json\/wp\/v2\/tags?post=256"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}