(archive 'newLISPer)

March 16, 2007

Idle chatter

Filed under: newLISP — newlisper @ 16:03
Tags:

I once knew a bloke who had the disconcerting habit of interrupting a conversation without warning and staring into space for 30 seconds or so. It looked as if he was searching for inspiration, but he could well have been downloading information from the mother ship. Talking to him wasn’t always easy, or a pleasure.

I was reminded of him recently when I started using Internet Relay Chat (irc) to access the #newlisp channel. Chatting on irc is odd. You know that there’s someone at the ‘other end’, but the ‘connection’ feels peculiar. Questions and answers sometimes hang in the air for minutes – as if slowly floating through the thick atmosphere of a gravitationally-dense planet. You can’t tell whether the people you’re chatting with are still at their keyboards working on a reply, or have wandered off to do something more interesting.

You meet all kinds of people on irc channels. One chap was hanging around on the #newlisp channel with the sole aim of trying to persuade people not to use newLISP. That’s a bit weird. Imagine finding someone loitering in a shop hoping to prevent you buying something you wanted. Of course, the antics of these ‘Lisp suprematists’ are familiar enough now for us not to take any notice of them – they’re usually quite harmless, and they go away eventually. In this respect, I found a good post on Slashdot, from a character called Melquiades, that summarizes the view that many people have of these oddballs (who are probably not very representative of most Lisp users, by the way):

Yes, you too can become a fanatical Lisp user! Just trawl for any online discussion of any programming langauge that is not Lisp, then post using the following handy form:

Derogatory or condescending salutation. Quasi-religious statement of love for Lisp.

Laundry list of several nifty Lisp features. (It doesn’t really matter which ones.)

Implication or outright statement that every feature in programming language in question has already been implemented in Lisp. Subsequent dismissal of language in question.

Remember, in writing your post, it is essential that you adhere to the following guidelines:

  • Never show any respect for a non-Lisp language.
  • Never admit the usefulness of new experiments, or of personal exploration.
  • Never contribute concrete, constructive suggestions to the designers or users of any other language.
  • Never, never think outside the Lisp box.

But back to irc and newLISP.

With some help from newLISP gurus (Norman, you know who you are!), I’ve been experimenting with some newLISP code to access irc in various ways. Here’s one attempt at an extremely simplistic irc client. Note in passing the lack of error-checking, a characteristic feature of these posts :-)

First we’ll open access to TCP port 6667 and connect to the irc server that hosts the #newlisp channel:

#!/usr/bin/newlisp
(set 'server (net-connect "irc.freenode.net" 6667))

Now we’ll log in to irc and join the #newlisp channel. Here I’ve used the username and nickname ‘newlithper’ – choose your own (and make sure it’s unique!):

(net-send server "USER newlithper 0 * :XXXXXXX\r\n")
(net-send server "NICK newlithper \r\n")
(net-send server "JOIN #newlisp\r\n")

Once we’re connected, we’ll get loads of text back from the server, consisting mainly of notices and also a biography of a leading figure in contemporary culture – cool. We’ll get this from the server via a buffer and print it, looking for a line containing 366, which apparently marks the end of the beginning, if you see what I mean:

(until (find "freenode.net 366" buffer)
  (net-receive server 'buffer 8192 "\n")
  (print buffer))

I don’t know why the maximum byte value is 8192, but the number looks plausible.

Now we’re connected and ready to ‘chat’. This is where I’ve been trying out a technique that allows me to do two sets of jobs at once. The first set consists of checking for new messages, responding to a periodic ‘keep alive’ exchange (called, reasonably enough, ‘ping-pong’), and handling a few errors. The second set consists of sending messages and commands.

So there are two while loops. They can share a connected flag; each loop can read and set this flag:

(set 'connected (share))
(share connected true)

This syntax is basically the equivalent of (set ‘connected true), used for symbols that are to be shared between threads.

The first set of jobs is done in a separate thread:

(fork
  (while (share connected)
    (cond
      ((net-select server "read" 1000) ; read the latest
          (net-receive server 'buffer 8192 "\n")
          ; output in green, then back to white
          (print "\n27[0;32m" buffer "27[0;0m"))
      ((regex {^PING :(.*)\r\n} buffer) ; play ping-pong
          (net-send server (append "PONG :" (string $1 ) "\r\n"))
          (sleep 5000))
      ((net-error) ; error
          (println "\n27[0;32m" "UH-OH: " (net-error) "27[0;0m")
          (share connected nil)))
   (sleep 1000)))

This runs happily in its own thread, regularly checking the shared ‘connected’ flag to see if it should continue. I’ve made output appear in green in my terminal.

The other while loop looks at the first character of any user input submitted via read-line. If it’s a “/”, it’s assumed to be an irc command. It’s definitely not a good idea to use commands that generate lots of output – since the other thread will work through the responses quite slowly (one line a second). So don’t try a “/list” command! Useful commands might be:

/names #newlisp
/whois cormullion
/time
/help

Here’s the loop:

(while (share connected)
   (sleep 1000)
   (set 'message (read-line))    ; get user input
   (cond
     ((starts-with message "/")  ; a command?
          (net-send server (append (rest message) "\r\n"))
          (if
            (net-select server "read" 1000)
            (begin
                (net-receive server 'buffer 8192 "\n")
                (print "\n27[0;32m" buffer "27[0;0m"))))
     ((starts-with message "quit") ; quit
            (share connected nil))
     (true  ; just send input as plain message
          (net-send server (append "PRIVMSG #newlisp :" message "\r\n")))))

With any luck, this code should allow us to send messages and give commands, while the other thread checks the channel for new messages. We quit by typing the command ‘quit’ at the start of a message. This sets the flag and thus terminates both while loops.

Finally, we should tidy up:

(println "finished; closing server")
(close server)
(exit)

So far this code seems to work fairly well – but I haven’t been testing it that much, mainly because I much prefer using something like Colloquy (MacOS X), which is an extremely well-designed and useful app. Perhaps I should be using semaphores to control access to shared memory, but I haven’t yet managed to understand the description of semaphore in the newLISP manual. :-)

But whatever irc client you use – if you have any interest in newLISP, please call in at the #newlisp channel occasionally. You don’t have to say anything if you don’t want to – just watch those speech balloons hang in the air…!

Advertisements

1 Comment »

  1. >;-)

    Comment by Anonymous — March 17, 2007 @ 20:16 | Reply


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: