Baby's first <canvas>: Brownian tree
Saturday, May 1st, 2010 10:43I just wrote my first use of that <canvas> thing that everyone's talking about. (If you don't know, this is part of the WHATWG/HTML5 general vicinity of features: an element which creates a bitmap pixmap image that can be drawn on by JavaScript.)
Since LJ doesn't let me embed JavaScript or iframes (a restriction which I'm only just noticing...) I'll have to provide only a link (but your CPU meters will thank me for that):
(This is also part of a personal goal to learn more about Modern Web Applications technologies: “Ajax”, jQuery, web frameworks, etc. I used to (a) not have a personal server, and (b) tend to “All web content must be accessible to non-JS and pure-text users” — but I’ve come to realize that while one should still avoid unnecessary dependence on fancy stuff, there is value in using these systems to create what are not so much “web pages” as cross-platform, zero-install applications — they may not be usable by $NON-MAINSTREAM-BROWSER-TYPE but nothing else would be more compatible and still provide the same benefits.)
Weird thing: Once upon a time I did a lot of work with MOO-code. Ever since then, if I’m writing something and my typing gets ahead of my thinking, I often type “#-1
”. It’s not meaningful in the context, it’s not a joke to myself — I have no idea what’s going on there.
(In MOO #-1
is the canonical value which is an-object-reference-but-not-a-valid-object, like null
in Java.)
The three ways to compare floating-point numbers
Thursday, April 1st, 2010 09:29One bit of advice sometimes given to the novice programmer is don't ever compare floating-point numbers for equality, the reason being that floating-point calculations are inexact, and one should use a small epsilon, allowable error, instead, e.g. if (abs(value - 1.0) < 0.0001)
.
This advice is actually wrong, or rather, overly strong. There is a situation in which it is 100% valid to compare floats, and that is an cache or anything else which is comparing a float with, not a specific constant (in which case the epsilon notion is appropriate), but rather a previous value from the same source; floating-point numbers may be approximations of exact arithmetic, but that doesn't mean you won't get the same result from the same inputs.
So, don't get any bright ideas about outlawing aFloat == anotherFloat
.
Unfortunately, there's a case in which the common equality on floats isn't what you want for previous-value comparison anyway: for most definitions of ==
, NaN ≠≠ NaN
. This definition makes sense for numerics (and is conformant to IEEE floating point specifications), because NaN
is “not a number”; it's an error marker, provided as an alternative to exceptions (or rather, floating point error signals/traps/whateveryoucallit) which propagates to the end of your calculation rather than aborting it and requiring immediate error handling, which can be advantageous in both code simplicity and efficiency. So if you think about calculating within the space of “numbers”, then NaN is outside of that. But if you're working in the space of “results of calculations”, then you probably want to see NaN == NaN
, but that may not be what you get.
Mathematically, the floating-point comparison is not an equivalence relation, because it is not reflexive on NaN
.
(It's also typically the case that 0 == -0
, even though positive and negative zero are distinct values. Oh, and NaNs carry data, but I'm not talking about that.)
What to do about it, in a few languages:
- JavaScript
Even the
===
operator does not compare identities rather than numeric values, so if you want to compareNaN
you have to do it as a special case. Google Caja handles it this way:/** * Are x and y not observably distinguishable? */ function identical(x, y) { if (x === y) { // 0 === -0, but they are not identical return x !== 0 || 1/x === 1/y; } else { // NaN !== NaN, but they are identical. // NaNs are the only non-reflexive value, i.e., if x !== x, // then x is a NaN. return x !== x && y !== y; } }
- Common Lisp
The
=
operator generally follows the IEEE comparison (if the implementation has NaN at all) and theeql
operator does the identical-object comparison.- E
-
The
==
operator is guaranteed to be reflexive, and return false for distinguishable objects, so it is appropriate for the “cache-like” use cases, and the<=>
operator does conventional!(NaN <=> NaN), 0.0 <=> -0.0
floating-point comparison.
(no subject)
Sunday, March 14th, 2010 14:28“Extended subset” makes perfect sense as long as you don’t think about it with set theory.
Those that leave one Googly-eyed
Thursday, March 11th, 2010 22:48One of the things I’ve been procrastinatingah, not had the time to do, being busy with school and other projects, is announcing and working on a job search for this summer. I have posted my resume, but I didn’t even get around to mentioning that. The process really doesn’t excite me that much — it’s essentially research, comparison shopping, which I have never been very fond of.
But, last October, I was contacted out of the blue by a recruiter asking if I was interested in opportunities at — Google. After checking that it wasn’t a spoof I naturally said yes, and after a number of rounds of information exchange and interviews,
This summer, I will be (well, subject to my completing the process of accepting the offer) working as a Software Engineering Intern at Google, with the Caja team, in Mountain View, CA.
So — whoa and yay and other such cheerful words. And thanks to my friends at Google who referred me and nudged the process along.*
The most uncertain remaining step is finding housing in or near Mountain View (could be as far as San Francisco or San Jose; Google runs a shuttle bus and is convenient to public transportation). Google has provided some general advice-for-interns, but I’d like to hear input from my readers and friends who already live in in the area.
Some parameters:
- I would consider living with other people, but I wouldn’t want to take a chance on a complete unknown. (So if you are someone or know someone with a room...)
- Speaking of taking chances, make the chance of being mugged on the way home in the evening very small, please.
- I am traveling from the east coast, probably by train, so I don’t want to have to transport a lot of stuff, or buy items that I’ll use for only three months — so a furnished space is better.
- I do not own a car, but I know how to drive one.
- I do not own a bicycle, but I used to know how to ride one.
- This will be the first time I have lived outside of my home city for longer than a week’s visit/vacation.
*Y’know how job search advice is big on saying you should be “networking”? If you’ve thought you’re too much of the non-face-to-face-social non-polite-small-talk would-rather-talk-to-people-through-the-computer sort for that — take me as an example. This opportunity came to me because of other people who knew me entirely through my work on open source projects (E, and thus Caja-CapTP) — I didn’t do anything that I wouldn’t have done for other reasons anyway. I’m not saying you shouldn't do any of the other stuff you might be thinking of — I’m saying this stuff counts.
Things I had not done before entering college
Saturday, February 27th, 2010 21:31Normal People Things:
- Gone to a party unrelated to my family.
Never thought I'd do:
- Worn a t-shirt with text on it.
- Written an essay structured using a gratuitous extended metaphor.
Extra nerd points:
- Programmed a number type which carries units and error values, to reduce the tedium of lab reports.
- Learned to write all my assignments in LATEX.
Hvm.hs: an exercise in Haskell golf
Tuesday, February 23rd, 2010 21:21import Char import Debug.Trace import System.Environment import Control.Monad.Fix {- Hvm.hs By Kevin Reid, 2008-06-15 This is an implementation of the virtual machine described at <http://www.hacker.org/hvm/>. It was designed to fit into a single IRC line so that its definition could be put into lambdabot <http://www.haskell.org/haskellwiki/Lambdabot>, and its inspiration and creation was documented at <http://swhack.com/logs/2008-06-15>. Haskell source not in HTML: <http://switchb.org/kpreid/2008/Hvm.hs> Non-blog location: <http://switchb.org/kpreid/2008/Hvm.html> Explanation of variables: r = VM execution function of call stack, memory, instruction pointer, and operand stack c = call stack m = memory i = instruction pointer j = instruction pointer plus one o = operand stack a = arithmetic handler h = proceed with instruction pointer and operation stack modification g = proceed with operand stack modification z:x = one value popped from operand stack z:w:e = two values popped from operand stack k:l = one value popped from call stack d, t: slice lists using z as length To make it fit in IRC, discard comments, imports, and "main", replace all line breaks with semicolons as appropriate, and discard the ' ' and _ cases (i.e. the interpreter will not support whitespace or report invalid characters). perl -0777 -pe 's/\A.*(?=^s)//ms; s/\s*main .*//; s/--.*$//mg; s/\n */;/g; s/[;\s]*(where|let)[;\s]*/$1 /g; s/;'\'' '\''->g o;_->error\$show\(p!!i\)//;' -} s p=r[](fix(0:))0[] where r c m i o=--trace (show (m,i,(if length p<=i then '!' else p !! i),(reverse o),c)) $ let a(&)=g$w&z:e j=1+i h=r c m g=h j z:x=o w:e=x k:l=c d=drop(1+z) t=take z in case(p++"!")!!i of 'p'->show z++g x 'P'->chr(mod z 128):g x d|isDigit d->g$ord d-48:o '+'->a(+) '-'->a(-) '*'->a(*) '/'->a div ':'->g$signum(w-z):e 'g'->h(z+j)x '?'->h(i+case w of 0->z;_->1)e 'c'->r(j:c)m z x '$'->r l m k o '<'->g$m!!z:x '>'->r c(t m++w:d m)j e '^'->g$x!!z:x 'v'->g$x!!z:t x++d x 'd'->g x '!'->"" ' '->g o _->error$show(p!!i) main = do [p] <- getArgs; putStrLn $ s p
Where's my new PDA?
Tuesday, February 16th, 2010 13:48My Palm TX is noticeably wearing out (power button dead and worked around, cover hinge fraying, direction pad starting to go) and doesn't have a decent modern web browser. I might have gotten a Palm Pre by now if it weren't for the lack of full-size external (Bluetooth) keyboard support (notetaking is one of the major use cases) — though I hear there might be an SDK coming out which would let third parties build one. (Lesser issues are the cost of a phone contract (though Internet-anywhere makes that have a good bit of value) and the battery life.) I get the impression that I should be looking at the Nokia N900 or one of its relatives, but I haven't gotten around to investigating that.
My additional requirements for a New PDA are that it sync calendars/todos with iCal, sync the abovementioned notes to my Mac (I don't care what software), fit in my shirt pocket, and have mostly-not-locked-down-and-expensive software development/installation (so that customized/open-source/the-obscure-niche-I-happen-to-need software can happen).
(Apple mobile products fail on the openness criterion and either Bluetooth keyboard (iPhone/iPod touch) or fitting in the shirt pocket (iPad).)
A machine I used to use to host some web services, bots, and repositories became no longer accessible from the Internet, as a result of which I've had to move what I was serving from it; some to switchb.org, some to personal machines.
I took the opportunity to clean things up a bit, as a result of which I now have better backups, more polished services, and know a little bit more about configuring Apache — though not as much as I perhaps should.
My Subversion repositories are now served over HTTP, and therefore browsable; and they are now backed up daily (using svnsync triggered by a cron job) to my laptop, and thence to all its backups.
(I wasted several minutes on remembering that cron will ignore the last line of a crontab file if it doesn't end with a newline; after listening to me grumbling about this, someone made a suggestion to end the file with a comment, so that the last line is harmless whether ignored or not, and also reminds one of the issue.)
If you have a working copy of one of my repositories (E-on-CL, E-on-JavaScript, MudWalker, Den, etc.), here's a guide to the changed URLs.
My other Tahoe-LAFS volunteer grid storage node is now residing on a machine on my home LAN.
Finally, some simple data-querying web services I wrote for Waterpoint's word games have now been moved to switchb.org; I also took the time to prettify their URLs (no cgi-bin or .cgi) and write documentation.
I haven't yet gotten to working on the bots, darcs repositories, or miscellaneous other stuff I had there.
(Pondering moving my blog over to switchb.org as well so as to not have ads, especially now that I found I can still have LJ-friends by way of OpenID. (Hm, but reading friends-locked posts over RSS might not work since there's no username+password for LJ to accept. Anyone have experience with that situation?))
Apache configuration questions:
- If I have multiple variants of a document (e.g. foo.html foo.pdf foo.txt) handled by MultiViews, so the canonical URL of the document is extensionless (“foo”), how do I properly control the default variant to serve in the event that the client does not express a preference via the Accept header? (Without doing so, I found that it would serve the .txt version, whereas I would prefer the HTML.) All that I found that worked was to create a type map file named “foo” with quality values, and force it to be interpreted as a type map using <FilesMatch>. This seems kludgy to me.
- What is the right way to serve CGIs, not in a designated cgi-bin directory, and without any .cgi extension in the URL? I initially tried to apply mod_rewrite, but I couldn't get it to work such that /foo internally contacted foo.cgi whereas /foo.cgi redirected to /foo. I resorted to another <FilesMatch> explicitly listing the name of each CGI and doing
SetHandler cgi-script
. - What is the right way to handle “testing” vs. “deployment” configurations, where the relevant Directory, Location, etc may be different depending on which server or subdirectory the site is set up on? I see that one may use environment variables — should I just set up variables containing the path prefixes for the particular host before including the generic configuration file?
ASDF PSA: defpackage in .asd is not obligatory
Wednesday, November 25th, 2009 17:06There seems to be a recurring misconception about writing .asd
files. It is not necessary to start your asd with (defpackage :foo.system ...) (in-package :foo.system)
to “avoid polluting the package asdf loads your system in”.
Every time an .asd file is loaded, ASDF creates a fresh package to load it in. The relevant code from ASDF is:
(defun make-temporary-package () (flet ((try (counter) (ignore-errors (make-package (format nil "ASDF~D" counter) :use '(:cl :asdf))))) (do* ((counter 0 (+ counter 1)) (package (try counter) (try counter))) (package package)))) (defun find-system (...) ... (let ((package (make-temporary-package))) (unwind-protect (let ((*package* package)) ... (load on-disk)) (delete-package package))) ...)
So, whenever you load an asd file, the package is fresh and :use
s CL and ASDF.
There are reasons to define a package for your asdf system definition.
- If you are creating any classes, such as custom ASDF component types, then, since classes are not garbage collected (MOP specifies that the list of a class's subclasses can be retrieved, and no implementation I know of uses weak references for the purpose), naming them with symbols in a consistent package (rather than the asdf temporary package) ensures that reloading the system definition does not create useless additional copies of the classes.
- If you are defining functions or other named entities in your system definition (which should of course only be done if they are also necessary to load the system) and want to be able to refer to them, such as for debugging, with nice interned symbol names.
- If you want to be able to
(load "foo.asd")
rather than going through asdf:find-system.
The disadvantages I can think of for defining a package for your system definitions are that the package list becomes more cluttered (only noticeably if for some strange reason you're loading many system definitions and not loading the defined systems), you're using more of the global package namespace (probably not a significant concern if you use a naming scheme like foo
and foo.system
), and your code is marginally more complex.
So there are good reasons for (and maybe some against) defpackage
in your asd, but package hygiene is not one of them.
[Edited 2009-11-26 to be less worded against defpackage after consideration and feedback.]
Avoiding repeating myself (on the command line)
Tuesday, October 27th, 2009 21:37I was working on some automated document generation, building the process, revising the input document, and checking the results, and got tired enough of typing "make output/foo.txt && open output/foo.txt" and then going back and editing that line when I wanted to check the PDF version etc. that I wrote a tool which I hope will have more general application as well. I called it “maken”:
#!/bin/sh # Make files and view the results. make "$@" && open "$@"
Or it could be generalized into being a combinator, running any two commands, rather than just make
and open
, specified as the first two arguments:
#!/bin/sh ca="$1" shift cb="$1" shift "$ca" "$@" && "$cb" "$@"
(Which, for the Haskell folks, should be called &&&
, except that that would be annoying to enter in the shell.)
(no subject)
Monday, September 21st, 2009 23:18Every time you write “ |
” in shell, that's concurrent programming.
This is not a LaTeX quine
Monday, September 21st, 2009 21:42\documentclass{article} \usepackage{verbatim} \begin{document} \verbatiminput{\jobname.tex} \end{document}
What do you call a method, er, header in Java?
Thursday, September 17th, 2009 23:46What do practicing Java programmers call the part of a method definition that isn't the { body }?
__________/ this bit here \___________ public static void main(String[] args) { // not this part }
A quick search turned up the Java Language Specification, Second Edition calling it a MethodHeader in the grammar, but it doesn't use that term in the text and I want to know what term(s) are used in practice, not solely by language lawyers.
(“Signature” is not correct, as that includes only the method name and parameter types, not modifiers and result type.)
It's that time of day again...
Thursday, September 17th, 2009 22:56Both of the non-internet-based computer-related classes I'm taking this semester are (only offered as) once-per-week night classes, nominally ending at 9:30. So I'm talking with someone after class — — gee, it's bedtime already.
GSoC conclusion.
Thursday, September 10th, 2009 20:57Late update on Caja-CapTP:
Google Summer of Code is over. I passed based on revised goals, but I'm not happy with the state of the code and I did not complete any significant part of the original plan.
Regarding the items mentioned in my last update:
- Write more documentation/comments.
- Commit as much of the work-in-progress as I can.
- ...including the incomplete CapTPConnection, even though its tests don't pass yet, so that the partial work can be counted.
I committed CapTPConnection, and found and fixed enough infrastructure (whenResolved, CommTable, SwissTable, deSubgraphKit, etc.) bugs that it starts up and can do a basic operation or two. It's not useful for anything, but it's a lot closer to running than it was at the time of my last update.
Also, I removed dependencies on 'window' so in principle it will operate on a non-browser (server) JavaScript implementation. This has not been exercised because there is no browserless driver for the test scripts yet.
I stated that I would continue working on Caja-CapTP past the GSoC work period; however, with the time occupied by schoolwork, I have not had time or brain space to do so yet. I am not going to abandon the project.
Java programming class (yes, I know Java already) today, introducing loops. Task: write a factorial program. I wrote mine to use int
arithmetic if possible, floating-point if not. Test the edge cases, of course. It says:
500! ≈ Infinity
I'm glad I used the “approximately equals” sign.
GSoC update: Stuff done, more to do.
Wednesday, August 12th, 2009 11:50Stuff done:
- Implemented generic literals.
- Implemented cyclic references in Data-E.
- Various cleanup, debugging support, and committing of stuff previously written.
- Wrote a wiki page documenting Caja-CapTP's major components and files.
Stuff to do:
- Write more documentation/comments.
- Commit as much of the work-in-progress as I can.
- ...including the incomplete CapTPConnection, even though its tests don't pass yet, so that the partial work can be counted.
Brain-dump for the beginning JavaScript programmer
Wednesday, August 12th, 2009 10:44A while ago I got the idea to write a “my experiences with JavaScript” post; unfortunately, I’ve forgotten what I was going to put in it. However, yesterday someone said approximately “I need to learn JavaScript in 3 hours, what should I know?”, and I thought of quite a few not-immediately-obvious things to point out.
( Brain-dump for the beginning JavaScript programmer )