{"id":567,"date":"2017-07-22T09:13:44","date_gmt":"2017-07-22T09:13:44","guid":{"rendered":"http:\/\/www.rangakrish.com\/?p=567"},"modified":"2017-07-22T09:18:36","modified_gmt":"2017-07-22T09:18:36","slug":"clpython-python-in-common-lisp-part-2","status":"publish","type":"post","link":"https:\/\/www.rangakrish.com\/index.php\/2017\/07\/22\/clpython-python-in-common-lisp-part-2\/","title":{"rendered":"CLPython: Python in Common Lisp &#8211; Part 2"},"content":{"rendered":"<p>We looked at the basic features of <a href=\"https:\/\/common-lisp.net\/project\/clpython\/\" target=\"_blank\">CLPython<\/a>\u00a0in our <a href=\"http:\/\/www.rangakrish.com\/index.php\/2017\/07\/07\/clpython-python-in-common-lisp\/\" target=\"_blank\">last blog<\/a>. In today&#8217;s post let us look at the support for Python classes.<\/p>\n<p style=\"padding-left: 30px;\"><strong><span style=\"color: #0000ff;\">PYTEST 130 &gt; (defun pyclass ()<\/span><\/strong><\/p>\n<p style=\"padding-left: 30px;\"><strong><span style=\"color: #0000ff;\">\u00a0 (run\u00a0<\/span><\/strong><\/p>\n<p style=\"padding-left: 30px;\"><strong><span style=\"color: #0000ff;\">&#8220;class Employee:<\/span><\/strong><\/p>\n<p style=\"padding-left: 30px;\"><strong><span style=\"color: #0000ff;\">\u00a0\u00a0 def __init__(self, name, dept):<\/span><\/strong><\/p>\n<p style=\"padding-left: 30px;\"><strong><span style=\"color: #0000ff;\">\u00a0\u00a0 \u00a0 self.name = name<\/span><\/strong><\/p>\n<p style=\"padding-left: 30px;\"><strong><span style=\"color: #0000ff;\">\u00a0\u00a0 \u00a0 self.dept = dept<\/span><\/strong><\/p>\n<p style=\"padding-left: 30px;\"><strong><span style=\"color: #0000ff;\">\u00a0\u00a0 def dump(self):<\/span><\/strong><\/p>\n<p style=\"padding-left: 30px;\"><strong><span style=\"color: #0000ff;\">\u00a0\u00a0 \u00a0 print &#8216;Name = &#8216;, self.name, &#8216;, Dept = &#8216;, self.dept<\/span><\/strong><\/p>\n<p style=\"padding-left: 30px;\"><strong><span style=\"color: #0000ff;\">\u00a0\u00a0 def setDept(self, dept):<\/span><\/strong><\/p>\n<p style=\"padding-left: 30px;\"><strong><span style=\"color: #0000ff;\">\u00a0\u00a0 \u00a0 self.dept = dept<\/span><\/strong><\/p>\n<p style=\"padding-left: 30px;\"><strong><span style=\"color: #0000ff;\">&#8220;))<\/span><\/strong><\/p>\n<p style=\"padding-left: 30px;\"><strong><span style=\"color: #0000ff;\">PYCLASS<\/span><\/strong><\/p>\n<p style=\"padding-left: 30px;\"><strong><span style=\"color: #0000ff;\">PYTEST 131 &gt; (setf cls (pyclass))<\/span><\/strong><\/p>\n<p style=\"padding-left: 30px;\"><strong><span style=\"color: #0000ff;\">#&lt;class Employee 40202F63AB&gt;<\/span><\/strong><\/p>\n<p>We have now defined a Python class (called <em><strong>Employee<\/strong><\/em>) on the fly. The variable <em><strong>cls<\/strong><\/em> stores the Lisp representation of the class.<\/p>\n<p>One way to create an instance of this class is execute a corresponding Python command in Lisp:<\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\"><strong>PYTEST 132 &gt; (setf obj (run &#8220;x = Employee(&#8216;John&#8217;, &#8216;Sales&#8217;)&#8221;))<\/strong><\/span><\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\"><strong>#&lt;Employee 402008052B&gt;<\/strong><\/span><\/p>\n<p>As you can guess, <em><strong>x<\/strong><\/em> is a Python variable and <em><strong>obj<\/strong><\/em> is a Lisp variable, both referencing\u00a0the same <em><strong>Employee<\/strong><\/em> object. Another way is to create the instance directly in Lisp using the CLPython function <em><strong>py-call<\/strong><\/em>:<\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\"><strong>PYTEST 133 &gt; (setf obj2 (py-call cls &#8220;Mary&#8221; &#8220;HR&#8221;))<\/strong><\/span><\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\"><strong>#&lt;Employee 40200932F3&gt;<\/strong><\/span><\/p>\n<p>Note that in both cases, we have to supply the constructor arguments.<\/p>\n<p>We can invoke the <em><strong>dump<\/strong><\/em> method and see the the values of the instance varables:<\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\"><strong>PYTEST 134 &gt; (run &#8220;x.dump()&#8221;)<\/strong><\/span><\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\"><strong>Name =\u00a0 John , Dept =\u00a0 Sales<\/strong><\/span><\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\"><strong>None<\/strong><\/span><\/p>\n<p>What about accessing the methods through the Lisp object? Unfortunately, I could not find a way to do this.<\/p>\n<p>The documentation says that Python class is mapped to CLOS class and instance is mapped to CLOS instance. So I decided to introspect the class\/object using methods in the CLOS Meta Object Protocol (MOP).<\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\"><strong>PYTEST 135 &gt; (class-slots cls)<\/strong><\/span><\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\"><strong>(#&lt;STANDARD-EFFECTIVE-SLOT-DEFINITION CLPYTHON::DICT 4020155263&gt;)<\/strong><\/span><\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\"><strong>PYTEST 136 &gt; (mapcar #&#8217;slot-definition-name (class-slots cls))<\/strong><\/span><\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\"><strong>(CLPYTHON::DICT)<\/strong><\/span><\/p>\n<p>It appears as if there is just one slot called <em><strong>DICT<\/strong><\/em> in the corresponding Lisp class. We can retrieve its values thus:<\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\"><strong>PYTEST 137 &gt; (slot-value obj &#8216;CLPYTHON::dict)<\/strong><\/span><\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\"><strong>((CLPYTHON.USER::|dept| . &#8220;Sales&#8221;) (CLPYTHON.USER::|name| . &#8220;John&#8221;))<\/strong><\/span><\/p>\n<p>So the various instance variables and values are stored as <em><strong>cons pairs<\/strong><\/em> in this single slot.<\/p>\n<p>OK, can we change the vaue of the field directly via the slot?<\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\"><strong>PYTEST 138 &gt; (setf (first (slot-value obj &#8216;CLPYTHON::dict)) &#8216;(CLPYTHON.USER::|dept| . &#8220;PR&#8221;))<\/strong><\/span><\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\"><strong>(CLPYTHON.USER::|dept| . &#8220;PR&#8221;)<\/strong><\/span><\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\"><strong>PYTEST 139 &gt; (run &#8220;x.dump()&#8221;)<\/strong><\/span><\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\"><strong>Name =\u00a0 John , Dept =\u00a0 PR<\/strong><\/span><\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\"><strong>None<\/strong><\/span><\/p>\n<p>OK, that is nice!<\/p>\n<p>We can change the <em><strong>dept<\/strong><\/em> by invoking the instance method as well:<\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\"><strong>PYTEST 140\u00a0&gt; (run &#8220;x.setDept(&#8216;Mktg&#8217;)&#8221;)<\/strong><\/span><\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\"><strong>None<\/strong><\/span><\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\"><strong>PYTEST 141\u00a0&gt; (run &#8220;x.dump()&#8221;)<\/strong><\/span><\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\"><strong>Name =\u00a0 John , Dept =\u00a0 Mktg<\/strong><\/span><\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\"><strong>None<\/strong><\/span><\/p>\n<p>This is confirmed via the other Lispy check:<\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\"><strong>PYTEST 142\u00a0&gt; (slot-value obj &#8216;CLPYTHON::dict)<\/strong><\/span><\/p>\n<p style=\"padding-left: 30px;\"><span style=\"color: #0000ff;\"><strong>((CLPYTHON.USER::|dept| . &#8220;Mktg&#8221;) (CLPYTHON.USER::|name| . &#8220;John&#8221;))<\/strong><\/span><\/p>\n<p>One thing that is apparent from my investigation is that the mapping from Python class to Lisp class is not exact. What I mean is that Python class is not mapped to Lisp class with the fields being mapped to <em><strong>slots<\/strong><\/em> and methods to <em><strong>defmethods<\/strong><\/em>. Maybe there was a reason to do it this way. That is perfectly understandable.<\/p>\n<p>Well, that concludes my brief study of CLPython. Have a great day!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We looked at the basic features of CLPython\u00a0in our last blog. In today&#8217;s post let us look at the support for Python classes. PYTEST 130 &gt; (defun pyclass () \u00a0 (run\u00a0 &#8220;class Employee: \u00a0\u00a0 def __init__(self, name, dept): \u00a0\u00a0 \u00a0 self.name = name \u00a0\u00a0 \u00a0 self.dept = dept \u00a0\u00a0 def dump(self): \u00a0\u00a0 \u00a0 print &#8216;Name [&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,103],"tags":[104,19,105,106],"class_list":["post-567","post","type-post","status-publish","format-standard","hentry","category-lisp","category-programming","category-python","tag-clpython","tag-lisp","tag-meta-object-protocol","tag-mop"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p9OLnF-99","jetpack-related-posts":[{"id":558,"url":"https:\/\/www.rangakrish.com\/index.php\/2017\/07\/07\/clpython-python-in-common-lisp\/","url_meta":{"origin":567,"position":0},"title":"CLPython &#8211; Python in Common Lisp","author":"admin","date":"July 7, 2017","format":false,"excerpt":"My work in the area of NLP requires\u00a0me to work with several frameworks across multiple languages such as Java, Python and Lisp. Sometime ago I got a chance to experiment with CLPython, an open-source implementation of Python in Common Lisp. Although CLPython is not under active development now, I found\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":567,"position":1},"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":3199,"url":"https:\/\/www.rangakrish.com\/index.php\/2023\/09\/04\/simulating-python-zip-in-lisp\/","url_meta":{"origin":567,"position":2},"title":"Simulating Python Zip in Lisp","author":"admin","date":"September 4, 2023","format":false,"excerpt":"The zip() function in Python is a convenient mechanism for iterating over multiple \u201citerables\u201d in parallel. Looping over lists is a common scenario. Here is the output generated by the above code: Common Lisp does not have such a feature built into the language or as part of the standard\u2026","rel":"","context":"In &quot;LISP&quot;","block_context":{"text":"LISP","link":"https:\/\/www.rangakrish.com\/index.php\/category\/lisp\/"},"img":{"alt_text":"Python Zip() Feature","src":"https:\/\/i0.wp.com\/www.rangakrish.com\/wp-content\/uploads\/2023\/09\/python-code-300x99.jpg?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":2645,"url":"https:\/\/www.rangakrish.com\/index.php\/2021\/12\/25\/calling-lisp-functions-from-d-language\/","url_meta":{"origin":567,"position":3},"title":"Calling Lisp Functions from D Language","author":"admin","date":"December 25, 2021","format":false,"excerpt":"After exploring \"newLisp\" in the past few posts, I would like to start looking at the \"D Programming Language\"\u00a0(DLang). DLang\u00a0has been around since 2001. It was originally created by Walter Bright and later Andrei Alexandrescu joined the team in 2007. The main inspiration for DLang was C++, although it uses\u2026","rel":"","context":"In &quot;D Language&quot;","block_context":{"text":"D Language","link":"https:\/\/www.rangakrish.com\/index.php\/category\/d-language\/"},"img":{"alt_text":"Lisp Function Called from D","src":"https:\/\/i0.wp.com\/www.rangakrish.com\/wp-content\/uploads\/2021\/12\/Lisp-300x107.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.rangakrish.com\/wp-content\/uploads\/2021\/12\/Lisp-300x107.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/www.rangakrish.com\/wp-content\/uploads\/2021\/12\/Lisp-300x107.jpg?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":122,"url":"https:\/\/www.rangakrish.com\/index.php\/2016\/01\/06\/lisp-returning-multiple-values-from-a-function\/","url_meta":{"origin":567,"position":4},"title":"Lisp: Returning Multiple Values From A Function","author":"admin","date":"January 6, 2016","format":false,"excerpt":"One of the interesting features of Lisp is its support for returning multiple values from a function, without bundling the values in a special container. Languages such as Python and Ruby support multi-value return (although there are subtle differences from Lisp). In C++11, we can use std::make_tuple() and std::tie(). To\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":2200,"url":"https:\/\/www.rangakrish.com\/index.php\/2020\/11\/08\/book-review-the-common-lisp-condition-system-beyond-exception-handling-with-control-flow-mechanisms\/","url_meta":{"origin":567,"position":5},"title":"Book Review &#8211; The Common Lisp Condition System: Beyond Exception Handling with Control Flow Mechanisms.","author":"admin","date":"November 8, 2020","format":false,"excerpt":"Title: The Common Lisp Condition System: Beyond Exception Handling with Control Flow Mechanisms Author: Micha\u0142 \"phoe\" Herda Publisher: Apress Year: 2020 Unlike with other languages, it is rare to find new books being published on Lisp. The last book on Lisp, which I purchased was \u201cCommon Lisp Recipes\u201d\u00a0\u00a0by Edmund Weitz\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\/2020\/11\/Cover-page-209x300.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.rangakrish.com\/index.php\/wp-json\/wp\/v2\/posts\/567","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=567"}],"version-history":[{"count":0,"href":"https:\/\/www.rangakrish.com\/index.php\/wp-json\/wp\/v2\/posts\/567\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.rangakrish.com\/index.php\/wp-json\/wp\/v2\/media?parent=567"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.rangakrish.com\/index.php\/wp-json\/wp\/v2\/categories?post=567"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.rangakrish.com\/index.php\/wp-json\/wp\/v2\/tags?post=567"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}