i'd rather say: "programs (in L) should be readable by people (who know L)." i have no idea how to determine absolute readability (except to require that the font-size be within a certain range.)
> Lisp 150 LOC ................ Peter Norvig > Qi (slightly revised) 63 LOC .................Mark Tarver > Ruby 53 LOC .................William James > Q 10 LOC ..................Steven Apter > K 3 LOC ...................Steven Apter > Ruby (again) 17 LOC ...................William James > Mathematica 20 LOC .................. Szabolcs
> Mark
So K wins the competition in brevity, but does the ability to squeeze code into illegible character blobs say anything about the suitability of a programming language for writing readable and understandable programs? I'd rather follow the principle that "Programs must be written for people to read, and only incidentally for machines to execute."...
-- Dimitre Liotev (format t "~{~a~}" (reverse '("et" "n" "in." "a" "zn" "@" "l" "d")))
>> e"hi. i'm going to be your worst nightmare" >> e"i think you're full of it." >> e"my mother told me so." >> e"no. you tell me about yours." >> e"you're obviously retarded." >> e"damn your eyes!" >> e"understand a kick in the pants?" >> e"i always ignore idiots." >> e"i am afraid of dinosaurs"
>> responses:
>> "have you always been going to be my worst nightmare? >> "why do you think i am full of it?" >> "tell me about your mother." >> "please don't be so personal." >> "can you elaborate on that?" >> "can you elaborate on that?" >> "that's very interesting. do go on." >> "why do you always ignore idiots?" >> "have you always been afraid of dinosaurs?"
> I don't see "you", "your", "my", "myself", "yourself", etc. > So how can it change "your" to "my"? > I was talking about the K program; you're talking about the Q program.
both the k and the q program use P. did mark have this feature in his Qi version?
>> a few observations:
>> the 'i' function gives you prompt-and-respond in the console by >> call 'e' until the user gives no prompt:
>> i:{while[count r:read0 0;-1"? ",e r;]}
> I was talking about the K program; you're talking about the Q program.
activate the k script with: while[#r:0:0;-1"? ",e r]
>> the 'P' function maps first- and second-person:
>> >> Lisp 150 LOC ................ Peter Norvig >> >> Qi (slightly revised) 63 LOC .................Mark Tarver >> >> Ruby 53 LOC .................William James >> >> Q 10 LOC ..................Steven Apter >> >> K 3 LOC ...................Steven Apter >> >> Ruby (again) 17 LOC ...................William James >> >> Mathematica 20 LOC .................. Szabolcs
>> >> Mark
>> > The K version doesn't do everything that the Ruby >> > versions do. It doesn't change "I" in the user's >> > response to "you" when throwing it back at the user, >> > for example.
>> > When there are multiple possible replies to a user's >> > input, the Ruby program rotates those replies so that >> > not one will be repeated until all have been used.
William James <w_a_x_...@yahoo.com> writes: > This does so little that it should be no more than 2 lines. > In Ruby:
> S = > [ /father|mother|brother|sister/i, "Tell me about your 0."], > [ /\b(am|i'm) (.*)/i, ["Why are you 2?","Have you always been 2?"]], > [ /\bI was (.*)/i, ["Why were you 1?","I can't believe you were
[...]
He, Ruby is so verbose, both K an Q beat it to death when it comes to brevity. Witness the power, a sudoku solver in K:
f:{$[&/x;,x;,/f'@[x;i;:;]'&27=x[,/p i:x?0]?!10]}
Not that I understand what this eyesore means, but according to this blog it is supposed to be a sudoku solver:
Stevan Apter wrote: > i'd rather say: "programs (in L) should be readable by people (who know > L)." i have no idea how to determine absolute readability (except to > require that the font-size be within a certain range.)
> Wow, looks like APL - also famous for inscrutable 1 liners.
> Nothing from the big players Haskell, O'Caml & ML so far.
> So far I've got
> Lisp 150 LOC ................ Peter Norvig > Qi (slightly revised) 63 LOC .................Mark Tarver > Ruby 53 LOC .................William James > Q 10 LOC ..................Steven Apter > K 3 LOC ...................Steven Apter
> Mark
Below is the Common Lisp version from Norvig.
I have removed the duplicated definitions from his code. He is developing the code in his book (especially the pattern matcher), so he has more than one version of several functions. The code is also written in a very readable style, to support the educational purpose of his book.
When the comments and the rules are removed, the code is about 110 lines.
;;; ==============================
;;; -*- Mode: Lisp; Syntax: Common-Lisp; -*- ;;; Code from Paradigms of Artificial Intelligence Programming ;;; Copyright (c) 1991 Peter Norvig
(defun starts-with (list x) "Is x a list whose first element is x?" (and (consp list) (eql (first list) x)))
(defun flatten (the-list) "Append together elements (or lists) in the list." (mappend #'mklist the-list))
(defun mklist (x) "Return x if it is a list, otherwise (x)." (if (listp x) x (list x)))
(defun mappend (fn the-list) "Apply fn to each element of list and append the results." (apply #'append (mapcar fn the-list)))
(defun random-elt (choices) "Choose an element from a list at random." (elt choices (random (length choices))))
(defun variable-p (x) "Is x a variable (a symbol beginning with `?')?" (and (symbolp x) (equal (char (symbol-name x) 0) #\?)))
(defconstant no-bindings '((t . t)) "Indicates pat-match success, with no variables.")
(defun get-binding (var bindings) "Find a (variable . value) pair in a binding list." (assoc var bindings))
(defun binding-val (binding) "Get the value part of a single binding." (cdr binding))
(defun lookup (var bindings) "Get the value part (for var) from a binding list." (binding-val (get-binding var bindings)))
(defun match-variable (var input bindings) "Does VAR match input? Uses (or updates) and returns bindings." (let ((binding (get-binding var bindings))) (cond ((not binding) (extend-bindings var input bindings)) ((equal input (binding-val binding)) bindings) (t fail))))
(defun extend-bindings (var val bindings) "Add a (var . value) pair to a binding list." (cons (cons var val) ;; Once we add a "real" binding, ;; we can get rid of the dummy no-bindings (if (and (eq bindings no-bindings)) nil bindings)))
(defun print-with-spaces (list) (format t "~{~a ~}" list))
(defun eliza () "Respond to user input using pattern matching rules." (loop (print 'eliza>) (let* ((input (read-line-no-punct)) (response (flatten (use-eliza-rules input)))) (print-with-spaces response) (if (equal response '(good bye)) (RETURN)))))
(defparameter *eliza-rules* '((((?* ?x) hello (?* ?y)) (How do you do. Please state your problem.)) (((?* ?x) I want (?* ?y)) (What would it mean if you got ?y) (Why do you want ?y) (Suppose you got ?y soon)) (((?* ?x) if (?* ?y)) (Do you really think its likely that ?y) (Do you wish that ?y) (What do you think about ?y) (Really-- if ?y)) (((?* ?x) no (?* ?y)) (Why not?) (You are being a bit negative) (Are you saying "NO" just to be negative?)) (((?* ?x) I was (?* ?y)) (Were you really?) (Perhaps I already knew you were ?y) (Why do you tell me you were ?y now?)) (((?* ?x) I feel (?* ?y)) (Do you often feel ?y ?)) (((?* ?x) I felt (?* ?y)) (What other feelings do you have?))))
>> i'd rather say: "programs (in L) should be readable by people (who know >> L)." i have no idea how to determine absolute readability (except to >> require that the font-size be within a certain range.)
languages make different trade-offs. i was once asked to write a style-manual for programmers new to k. this is the result: www.nsl.com/papers/style.pdf.
eliza.q mostly follows the rules. eliza.k breaks them all!
>>> i'd rather say: "programs (in L) should be readable by people (who know >>> L)." i have no idea how to determine absolute readability (except to >>> require that the font-size be within a certain range.)
> languages make different trade-offs. i was once asked to write a > style-manual > for programmers new to k. this is the result: > www.nsl.com/papers/style.pdf.
Looks familiar. We may have met briefly if you were in that office on the 30th floor at UBS with the Special K carton outside. I wandered in one day, ended up talking about GC with the K crew, got a free style guide and K manual for my trouble. Might still have it somewhere.
I was a per diem guy so did not get the K training. :(
> >> e"hi. i'm going to be your worst nightmare" > >> e"i think you're full of it." > >> e"my mother told me so." > >> e"no. you tell me about yours." > >> e"you're obviously retarded." > >> e"damn your eyes!" > >> e"understand a kick in the pants?" > >> e"i always ignore idiots." > >> e"i am afraid of dinosaurs"
> >> responses:
> >> "have you always been going to be my worst nightmare? > >> "why do you think i am full of it?" > >> "tell me about your mother." > >> "please don't be so personal." > >> "can you elaborate on that?" > >> "can you elaborate on that?" > >> "that's very interesting. do go on." > >> "why do you always ignore idiots?" > >> "have you always been afraid of dinosaurs?"
> > I don't see "you", "your", "my", "myself", "yourself", etc. > > So how can it change "your" to "my"? > > I was talking about the K program; you're talking about the Q program.
> both the k and the q program use P.
So what you posted as the k program was not the complete k program.
> did mark have this feature in his > Qi version?
No.
> >> a few observations:
> >> the 'i' function gives you prompt-and-respond in the console by > >> call 'e' until the user gives no prompt:
> >> i:{while[count r:read0 0;-1"? ",e r;]}
So what you posted as the k program was not the complete k program.
Mark Tarver was led to believe that the complete program was 3 lines.
Perhaps the complete k program would be something like
> Having got 3936 LOC through a 4000 LOC implementation, I thought I'd > do some recreational > hacking and do an old old program I've not looked at for some time - > Eliza. You all know Eliza well enough for me not to have to spell it > out. The challenge is to implement or dig up an Eliza program (you > don't have to write it yourself) in your favourite FPL. Note that the > script that drives Eliza's responses should not be counted towards the > LOC count. Some constraints.
> 1. The script itself should be changeable by any novice. That is to > say that it should not > be a pile of hard-wired code written in the native language of > the program or require > deep programming skills.
> 2. The program should receive keyboard input from the user - > including the usual punctuation > and any characters he wants to enter without crashing.
> During the Harrop Wars on comp.lang.lisp a lot of stuff was thrown > around about the desirability of pattern matching. The challenge is > interesting because it involves a style of pattern-matching called > 'segment pattern matching' that is not hard-wired into most FPLs and > I'd like to see how well different FPLs cope with something outside > the standard.
> Oh last thing; don't get too uptight about this. It's only a bit of > fun.
> Mark
Unlike my 2-line Ruby version, this one changes first-person pronouns to second-person, and vice versa.
S = [ /father|mother|brother|sister/i, "Tell me about your 0."], [ /\b(am|i'm) (.*)/i, ["Why are you 2?","Have you always been 2?"]], [ /\bI was (.*)/i, ["Why were you 1?","I can't believe you were 1."]], [ /\bI will (.*)/i, "Do you think it's wise to 1?"], [ /\bI (.*)/i, "Why do you 1?" ], [ /\b(you|your|yours)\b/i, ["We're talking about you, not me.", "Please don't be so personal."]], [ /.*/, ["That's very interesting. Do go on.", "Tell me more.", "I'm not sure that I understand you fully.", "Can you elaborate on that?" ]]
On Feb 24, 9:00 am, Dimitre Liotev <no...@email.com> wrote:
> Mark Tarver <dr.mtar...@ukonline.co.uk> writes: > > Sorry I missed a couple of later attempts
> > Lisp 150 LOC ................ Peter Norvig > > Qi (slightly revised) 63 LOC .................Mark Tarver > > Ruby 53 LOC .................William James > > Q 10 LOC ..................Steven Apter > > K 3 LOC ...................Steven Apter > > Ruby (again) 17 LOC ...................William James > > Mathematica 20 LOC .................. Szabolcs
> > Mark
> So K wins the competition in brevity,
I'm not so sure. The three lines of K were not a complete program. I just posted a 4-line Ruby program that does everything the Q program does.
> but does the ability to squeeze > code into illegible character blobs say anything about the suitability > of a programming language for writing readable and understandable > programs? I'd rather follow the principle that "Programs must be written > for people to read, and only incidentally for machines to execute."...
If you really believe that, then you must agree that the language used in your signature was designed to be easy for a computer, not a human, to parse.
> -- > Dimitre Liotev > (format t "~{~a~}" (reverse '("et" "n" "in." "a" "zn" "@" "l" "d")))
Ruby:
%w(et n in. a zn @ l d).reverse.join
Now that's easier for a human to read! Of course, Lisp makes it easy to have macros that generate code, which is a powerful feature.
William James wrote: > On Feb 22, 5:49 am, Mark Tarver <dr.mtar...@ukonline.co.uk> wrote: > > Having got 3936 LOC through a 4000 LOC implementation, I thought I'd > > do some recreational > > hacking and do an old old program I've not looked at for some time - > > Eliza. You all know Eliza well enough for me not to have to spell it > > out. The challenge is to implement or dig up an Eliza program (you > > don't have to write it yourself) in your favourite FPL. Note that the > > script that drives Eliza's responses should not be counted towards the > > LOC count. Some constraints.
> > 1. The script itself should be changeable by any novice. That is to > > say that it should not > > be a pile of hard-wired code written in the native language of > > the program or require > > deep programming skills.
> > 2. The program should receive keyboard input from the user - > > including the usual punctuation > > and any characters he wants to enter without crashing.
> > During the Harrop Wars on comp.lang.lisp a lot of stuff was thrown > > around about the desirability of pattern matching. The challenge is > > interesting because it involves a style of pattern-matching called > > 'segment pattern matching' that is not hard-wired into most FPLs and > > I'd like to see how well different FPLs cope with something outside > > the standard.
> > Oh last thing; don't get too uptight about this. It's only a bit of > > fun.
> > Mark
> Unlike my 2-line Ruby version, this one changes first-person > pronouns to second-person, and vice versa.
> S = > [ /father|mother|brother|sister/i, "Tell me about your 0."], > [ /\b(am|i'm) (.*)/i, ["Why are you 2?","Have you always been 2?"]], > [ /\bI was (.*)/i, ["Why were you 1?","I can't believe you were > 1."]], > [ /\bI will (.*)/i, "Do you think it's wise to 1?"], > [ /\bI (.*)/i, "Why do you 1?" ], > [ /\b(you|your|yours)\b/i, ["We're talking about you, not me.", > "Please don't be so personal."]], > [ /.*/, ["That's very interesting. Do go on.", > "Tell me more.", > "I'm not sure that I understand you fully.", > "Can you elaborate on that?" ]]
g**gle split some of the lines in my 4-line code above. Let's make it 6 lines.
S = [ /father|mother|brother|sister/i, "Tell me about your 0."], [ /\b(am|i'm) (.*)/i, ["Why are you 2?","Have you always been 2?"]], [ /\bI was (.*)/i, ["Why were you 1?","I can't believe you were 1."]], [ /\bI will (.*)/i, "Do you think it's wise to 1?"], [ /\bI (.*)/i, "Why do you 1?" ], [ /\b(you|your|yours)\b/i, ["We're talking about you, not me.", "Please don't be so personal."]], [ /.*/, ["That's very interesting. Do go on.", "Tell me more.", "I'm not sure that I understand you fully.", "Can you elaborate on that?" ]]
P = Hash[ *"I|you|my|your|myself|yourself|you are|I am|you're|I am". split('|')] ( gets;sub(/[.!?,; ]+$/,"");x=Array(S.find{|a|$m=$_.match(a[0])}[1]) puts x[rand(x.size)].gsub(/\d/){$m.to_a[$&.to_i].scan( /you are|you're|\w+|\W+/).map{|s|P[s]||P.invert[s]||s}.join} ) while 9
William James wrote: > On Feb 24, 9:00 am, Dimitre Liotev <no...@email.com> wrote: [ SNIP ] >> Dimitre Liotev >> (format t "~{~a~}" (reverse '("et" "n" "in." "a" "zn" "@" "l" "d")))
> Ruby:
> %w(et n in. a zn @ l d).reverse.join
> Now that's easier for a human to read! Of course, Lisp makes > it easy to have macros that generate code, which is a powerful > feature.
And a succinct but not-quite-so-easy-to-read J version :-) -
> William James <w_a_x_...@yahoo.com> writes: > > This does so little that it should be no more than 2 lines. > > In Ruby:
> > S = > > [ /father|mother|brother|sister/i, "Tell me about your 0."], > > [ /\b(am|i'm) (.*)/i, ["Why are you 2?","Have you always been 2?"]], > > [ /\bI was (.*)/i, ["Why were you 1?","I can't believe you were
> [...]
> He, Ruby is so verbose, both K an Q beat it to death when it comes to > brevity. Witness the power, a sudoku solver in K:
> Not that I understand what this eyesore means, but according to this > blog it is supposed to be a sudoku solver:
Boy, I have mixed emotions when reading that. On the one hand, I see what at first glance appears to be a collection of random characters. On the other hand, I recognize I have zero knowledge of K, so I'm slightly curious about a language that seems to take conciseness to an obscene level.
Here's a question. Would it be easier to add some verbosity and formatting to make the above K program more readable to those who don't know K, or to take a readable program in another language and make it that short? :)
>> Not that I understand what this eyesore means, but according to this >> blog it is supposed to be a sudoku solver:
> Boy, I have mixed emotions when reading that. On the one hand, I see > what at first glance appears to be a collection of random characters. > On the other hand, I recognize I have zero knowledge of K, so I'm > slightly curious about a language that seems to take conciseness to an > obscene level.
> Here's a question. Would it be easier to add some verbosity and > formatting to make the above K program more readable to those who > don't know K, or to take a readable program in another language and > make it that short? :)
in k symbols like + are ambivalent: x+y is addition, +x is transposition. q is k with keywords for the unary case: x+y is addition, flip x is transposition.
in f we have one instance of a primitive with four arguments: @[x;y;:;w]. so we can define:
amend:{@[x;y;:;z]}
x?y finds y in x. let's cover that as well, and give it infix syntax:
.q.find:?
$[x;y;z;...] is the conditional.
now rewrite f in q like this:
f:{$[all x;enlist x;raze f each amend[x;i]each where 27=x[raze p i:x find 0]find til 10]}