The interesting thing is that there is so many options to port that when I get stuck on one, I usually shift sideways mentally and solve another before I come back.
Example, I'm stuck on the reverse of the list-join function which would be (in Ruby) a split function usually used as thus:
"1,2,3".split(',') => [1 2 3]
I haven't found an elegant way inside my head to solve that issue however while working on it I was able to "improve" on Ruby somewhat by addressing what I have always griped about with regards to the index function.
Example, in Ruby one can use the index function to return the index (string or array) of what you are searching for by using the index method on that object.
The problem (for me) has always been that the index function only returns the first instance of the item in the set. Which is (again for me) kind of silly because it precludes being able to do more interesting manipulations.
Ruby Way (ugh)
[1,1,2,3,4,5].index(1) => 0
Now, if I'm interested in all of the locations of the value "1" in the set I'm going to have to do something annoying like build a separate array and store in it the location of the item as I iterate over the set.
I think by now you can see why this annoys me because my thinking along the lines of the Object.split function requires knowing not only what the delimiter is but also the location of each instance of the delimiter within the set.
So, when I created the index function, I made my Ruby port drift a little (some amateur language designing if you will) with the following:
;index
(define (index lst val)
(let* ((blah (list 'head)))
(let bump ((i 0))
(if (= (length lst) i)
(cdr blah)
(if (equal? (list-ref lst i) val)
(begin
(set! blah
(append blah (list i)))
(bump (+ 1 i)))
(bump (+ 1 i)))))))
Which can be shown like this:
> (define l-ist (list 0 1 1 2 3 4 4 5 6))
> (index l-ist 1)
(1 2)
Now, I can convert my string to a list (string->list) and find out the locations of all the delimiters as follows:
> (define commas "1,2345,789,0")
> (index (string->list commas) #\,)
(1 6 10)
Which will allow me to use my slice function to carve up the interior bits of the string.
At the moment, the index function only works on lists so it should be called list-index but, duck-typing is an easy mimic as well so I would write something along the lines of:
(define (index object val)
(if (list? object) (list-index val)
(if (string? object) (string-index val)
(if (vector? object) (vector-index val)))))
Elegant it ain't but, it works. What I hope to do is look at some of the clojure source code and see if I can grok what Rich Hickey did by abstracting the seq function over every object in clojure.
The more I look at clojure, the more I find myself disappointed somewhat that Groovy looks so freakin' ugly. It's as if the language designers want to slowly wean the Java-istas off the curly braces without creating culture shock.
From someone who's spent enough time mucking about with Lispy languages the curly braces only mean one thing to me: hash-table.
Clojure is brilliant for a number of reasons but, my two favourites are:
1. It removes the ugly java syntax and replaces it with something beautiful
2. It does #1 while preserving the power of the Virtual Machine, which is second to none.
Clojure for Lisp Programmers is a presentation Rich gave for the Boston Lisp meetup.
There is one for Java programmers being introduced to Lisp but, if you take the time to go through either SICP or "Teach Yourself Scheme in Fixnum Days" you can probably ignore it and go right to the meat of the matter. He explains more about Clojure to the Lisp programmers because he doesn't have to explain Lisp first.
Unless
I love unabashedly the "unless" conditional much in the same way that I prefer to invert my sentence structures. But, mostly it's because any language that has the "unless" allows me to write a conditional the way English speakers normally write - that is to say "Give me that bucket, unless it has paint in it".
Well, PocketScheme doesn't have "unless". Only if, cond, equal?, eqv?, =, case are part of the language.
But, no fear - some googling around and I found a procedural definition of the Unless statement on Google Books that goes like this:
(unless test expression1 expression2)
Well, that makes tonnes of sense to me. So, here it is in Scheme:
(define (unless test expr1 expr2)
(if (eqv? test #t) expr2 expr1))
usage:
> (unless (= 2 3) 't 'f)
t
I hope to have the first fifty or so functions up on a github location by the end of the month and when I do, I'll provide the link.
No comments:
Post a Comment