Tao of the MachineProgramming, Python, my projects, card games, books, music, Zoids, bettas, manga, cool stuff, and whatever comes to mind. |
Front page Last 10 archives 2004-02-14 2004-02-21 2004-02-28 2004-03-06 2004-03-13 2004-03-20 2004-03-27 2004-04-03 2004-04-10 2004-06-05 Category archives bettas books CCGs Charm esoterica Firedrop games general ideas internet Kaa linkstuffs Lisp manga music Mygale Nederland nostalgia programming Python SGI switch Wax Zoids :: Search All posts ...by category ...by date :: About me :: Oasis Digital :: Resume :: GeoURL :: RSS :: Atom |
My first macroThe other day I wrote my first real Lisp macro. Yay! (Not counting macros from tutorials, etc.) It's a first step in harnessing some of the amazing power of Lisp. This macro implements a C-like (defmacro ++ (x) `(let ((old-x ,x)) (progn (setq ,x (+ ,x 1)) old-x))) and it's used like this: (setq magic 42) (print (++ magic)) ;; like magic++ in C: sets magic to 43, returns 42 (print magic) ;; 43! Nothing special, and maybe not very useful, but it's always nice if you have an idea and it can actually be implemented in a few lines of code. :-) This may be an important step on the road to more Lisp. A long, long road, I suspect. Not that I will leave Python anytime soon... I'll still need to get some actual work done. [Update #1] Some people pointed out that the macro isn't 100% safe. More about this problem here. The safe solution is quite ugly, IMHO (using (It's a bit quiet here in the Python and Parentheses topic exchange. Anybody else join in?) Nu even een geintje...This code works in Lython: (import wax) (print wax.Application) (:= app (wax.Application wax.Frame)) (app.Run) Due to the limitations of Lython (which is at 0.1 currently), it's not very useful yet. If it supported keyword arguments, we could write (:= app (wax.Application wax.Frame :direction "vertical" :title "Hello")) And if it supported classes, we could subclass Unrelated: I don't see [1]> (setq a '(1 2 3 4 5)) (1 2 3 4 5) [2]> (setq b (cdr a)) (2 3 4 5) [3]> (setf (cadr a) 42) 42 [4]> a (1 42 3 4 5) [5]> b (42 3 4 5) (I'm running into the same problems for my PyZetaLisp interpreter... how to implement The Little Lisper
Posted by Hans
"and it doesn't need cartoon foxes :-)"
Nowak on 2004-02-25 16:51:44
{link}
(see old comments)
Categories: Lisp, books Lispy linksSome links that might help get the Python and Parentheses thingy going...
(import os) (:= out "/tmp/lythontest") (if (os.path.exists out) (os.unlink out) (print "target file does not exist")) (:= f (open "/tmp/lythontest" "w+")) (f.write "Hello World from Lython!") (f.close) (Lython's integration is a lot better than my PyZetaLisp interpreter's, but then again, PyZetaLisp was really meant as a prototype for a later implementation in C or OCaml or something; integration with Python was more of an afterthought. That's why PyZetaLisp has separate classes for integers, strings, etc, rather than using Python's built-in types directly.) Python and Parentheses TopicExchangehttp://topicexchange.com/t/python_and_parentheses/ Aaron Brady: "Given that Python & Scheme, and Python & Lisp have been recurring memes lately, I thought it would be good to group all of these posts tegether in one place. To that end, I've created a new topic on Phillip Pearson's *excellent* TopicExchange, for people to trackback when posting about it. It's like a manual "Buzz"." Funny this should come up... lately I've been wondering what it would be like to have a language that's a mixture of Lisp and Python. A Pythonic Lisp. A Lispy Python. A Lisp designed with Pythonic principles in mind. It could have goodies like modules and objects. (import 'foo) ;; or maybe: (import foo) ...? Maybe it could have special syntax for dicts, lists and object access. (foo.bar 42) ;; sugar for: (getattr foo 'bar) (define a (range 10)) ;; a list (print a[2]) ;; sugar for: (getitem a 2) (define b sys.modules) ;; a dict (print b["os"]) ;; sugar for: (getitem a "os") (define c (create-instance Point)) (print c.x c.y) ;; sugar for: (getattr c 'x) Maybe it could be very Pythonic. TOOWTDI, explicit is better than implicit, and all that jazz. The language that I envision would be an independent implementation. It would not be a Lisp interpreter written in Python, or Pythonic syntax and libraries tacked onto Lisp. No, I think it should be designed from scratch, critically looking at the Lisp-vs-Python balance every step of the way. Aside from the actual implementation, I think that the most difficult part would be, making it so that it would actually seem useful, natural, and a joy to program in... for people coming from Lisp, Python, and other languages. I'm not sure if that's possible. Sometimes I wonder if Lisp and Python, in spite of their similarities, are really based on vastly incompatible principles. (Aside: The TopicExchange uses trackback. To make things easier, the development version of Firedrop is now capable of sending trackback pings. No, it's not available yet. )
Posted by Hans
"just a trial balloon..."
Nowak on 2004-02-14 01:25:32
{link}
(see old comments)
Categories: Python, Lisp The lisping snakeThe time has come to look at integration of Python code with the Lisp interpreter. It's far from complete, but this time seems as good as any. The main problem is the difference in types. The Lisp interpreter currently uses several special objects: LispInteger, Pair, LispSpecialAtom (for Let's look at some (hypothetical, for the moment) example code. (setq os (py-import 'os)) (funcall (py-getattr os 'path 'join) "foo" "bar") => "foo\bar" Two conversion problems occur here: once when we call os.path.join, because the LispStrings "foo" and "bar" need to be converted to Python strings; and once when Lisp gets the return value back, in this case a Python string that needs to be converted to a LispString. This is all fairly simple. But now consider: (setq f (funcall (py-builtin open) "myfile.txt" "r")) (setq poplib (py-import 'poplib)) (setq pop (funcall (py-getattr poplib 'POP3) "host")) The Lisp interpreter now has several objects: a file object, a module, and a POP3 instance. How to represent these in Lisp? I wonder if it's best to use a thin wrapper class, call it PythonObject. PythonObjects can then be manipulated by selected "py-" functions. (For example, a file object wouldn't have dedicated Lisp functions to deal with it, but you would be able to use its methods and Python functions through the py- interface.) This would work, but we would still need an extra step or two to convert numbers and strings and such. Thoughts welcome. The little interpreter that couldMy Lisp interpreter is growing rapidly. It is really nice, how you can add little pieces to it, bit by bit, to grow a better Lisp. Since this will not be a real-world version, one of my goals is to write as much in Lisp as possible... if something can be written in Lisp, it shouldn't be a built-in function. (I realize that this will be very different when you're writing a Lisp that actually needs to have decent performance.) As said before, it's based on Zetalisp, and some differences with Common Lisp are visible already. For example, Zetalisp uses The current version is becoming more and more usable. It supports numerical comparison operators, car, cdr, cons, eq, funcall, and, cond, defun, function, if, incf, lambda, let, or, quote, and setq. It also supports Code is available in the usual place (look for
Posted by Hans
"l'empire du côté obscure"
Nowak on 2003-11-14 23:46:28
{link}
Categories: Python, Lisp SawdustSee yesterday's post about the namespace split. The decision I made can be grokked from this piece of code: (C:\cvsroot\zeta\python) $ tiny.py Welcome to PyZetalisp 0.1.5 >>> (let ((+ 3)) (+ + +)) 6 Once the interpreter is a bit more usable (currently it doesn't have Once the Lisp core is done, I wonder if some integration with Python is possible. You know, like, import Python modules, access their contents, create objects, maybe evaluate Python code, etc. But maybe that would be out of scope for a toy project. Clever readers will notice that the recent posts are just filler to keep people busy while I prepare for the next Python article. Kind of like certain coffee brands add sawdust to their melange. The question is, what shall the article be about? I'm not sure yet. (Suggestions welcome.) One of my plans for next year is to write a book. I have a number of ideas, but I haven't decided yet what the target audience will be... newbies, or advanced programmers. Possibly newbies, but I don't want to have to explain the basics of programming, or how to install Python. I will probably assume that the reader already has at least a bit of programming experience with other languages. More on the Lisp namespace splitI'm still wondering if I should implement separate namespaces in my little Lisp interpreter, or just use one, like Scheme has. On the one hand, I want to follow the manual as closely as possible, at least for now. On the other hand, I am not convinced that having separate namespaces is a good idea. This entry in the Common Lisp Cookbook illustrates the problem. You can, for example, write a function that returns a function, but you cannot call the returned function the usual way; you have to use Apparently this issue has been discussed on c.l.lisp before. Here's one argument in favor of it, but I am unconvinced. Although this argument is interesting: "What if one wrote a macro FIRST that took the CAR of a list. In CL this might look like (defmacro first (x) `(car ,x)) Well, then what if one were to write some snippet of code like the following: (let ((car 'ford) (desired-vehicles '(bmw mercedes))) (eq? car (first desired-vehicles))) Does the lexical binding of CAR to 'FORD shadow the expanded code from the macro FIRST and cause it to fail? If so, I claim that this is a bad property since one doesn't want to have to know what functions a macro uses in its expansion in order to be sure of avoiding problems." Here's what Kent Pitman has to say about it. I do like the extra bit of syntax (
Posted by Hans
"hmm, maybe it's time for a Lisp category?"
Nowak on 2003-11-11 21:31:11
{link}
Categories: programming, Lisp Writing a Lisp interpreter......is a good exercise, because it forces you to know the internals of the language. I'm not quite done yet with my version, modeled after Zetalisp, but I've already had a few moments of enlightenment. One such revelation was that symbols are not a special type. Another is, that special forms are actually, well, special... they are not functions that happen to have different evaluation rules; rather, they are (or can be) hard-coded in the interpreter. In this CLISP session, note that there is a built-in function > #'+ #<SYSTEM-FUNCTION +> > #'quote *** - FUNCTION: undefined function QUOTE > #'if *** - FUNCTION: undefined function IF > Which leads me to something else, the Lisp namespace dichotomy. Unlike Scheme (and Python), Lisp has a namespace for functions, and a separate one for variables. The following works in Scheme: > (define twice (lambda (x) (* 2 x))) #<unspecified> > (twice 3) 6 > (define (twice x) (* 2 x)) #<unspecified> > (twice 3) 6 In Lisp, this looks like: > (setq twice (lambda (x) (* 2 x))) #<CLOSURE :LAMBDA (X) (* 2 X)> > (twice 3) *** - EVAL: the function TWICE is undefined ;; this doesn't work; use funcall instead > (funcall twice 3) 6 Here, > (defun thrice (x) (* 3 x)) THRICE > (thrice 3) 9 > #'thrice #<CLOSURE THRICE (X) (DECLARE (SYSTEM::IN-DEFUN THRICE)) (BLOCK THRICE (* 3 X))> I wonder what the rationale is behind this variable/function namespace split. A namespace for code, and one for data? That seems especially odd in a language like Lisp, where code is often treated as data, or data as executed as code. Apparently the Scheme designers didn't like this either. So, I'm curious if there is a good reason for it. 1) Speech impedimentsI'm trying my hand at writing a little Lisp interpreter, just for fun. (I'm using the old Lisp Machine manuals I found earlier as a reference, by the way. Even though these documents are 20 years old, I find them a joy to work with. They're to the point, and without the hype that seems to be pervasive in modern Lisp texts.) I'm writing it in Python, so I'm obviously not too worried about performance (writing an interpreter in an interpreted language...). While this is much easier than writing it in, say, C or Pascal, I can think of a couple of drawbacks too. Python already has a list type, so my first thought was that it can be used for the Lisp lists as well. However, this is not how Lisp does it internally; rather, it uses cons cells. 1) So I added a Pair class, emulating a cell, and tried creating lists with that, and converting Python lists, but it's a big old mess. 2) After all, Lisp handles lists much differently than Python. So, back to the drawing board. Maybe I will use Python lists anyway, and put up with the obvious problems it has. (Inefficiency, for example... This is one area where a more limited language like Pascal may have unexpected benefits. Pascal doesn't have a list type, so you have to write one. And while you're at it, it's only a natural choice to create a system of linked lists like Lisp does. As a result, your list-using code will be closer to Lisp, and your expressions will be parsed into cons-cell-based expression trees. Even if I fail, writing such an interpreter is a good exercise, and I learn more about Lisp along the way. 1) 2) -- Generated by Firedrop2. |