Twelve Saturn Vs were used on the Apollo moon exploration program, and the 13th, in 1973, placed the McDonnell Douglas Skylab into Earth orbit. Two were placed in storage.So we still have two Saturn Vs? Cool. We should get one out of storage and launch it just to see if we can. Given the plan of going back to the moon, this would sure inspire a lot more confidence in NASA.
References:
Looking up at the Saturn V
The web site does the standard request a quote which is lame, but a few more lines down on the google search turned up this posting which gave me a ballpark figure:
Pro-Fusion Dual-Arc 80 Micro-TIG/Plasma System. Our R&D project has been completed. Used less than 50 hours. Available for $10,500 (shipping & insurance additional).Guess I better stick with the low-budget stuff from Lincoln and Miller.
Besides the old a,b=1,2
, you can also say a,b=getpair()
where getpair()
returns more than one value. This is kind of strange, because you would expect that Lua would try and leverage on its built in dictionary type, not the sub-set of lists. But its in there, though it works kind of strange. For instance, if you try to cascade return values (lists) together, it doesn't really work:
function a(x) return x,x*2,x*4 end function b(x) return x,x*3,x*9 end =a(10) 10 20 30 =b(10) 10 30 90 =a(10),b(10) 10 10 30 90So if you're making a list, the only thing that can return a list is the last item in the list. This of course has not yet been mentioned in the documentation (they don't want to show things coming apart at the seems yet), but I did run across somebody discussing this in my original foray looking into Lua.
You can hack things up by making one function take the other function:
function a(x,fn) return x,x*2,x*4,fn(x) end =a(10,b) 10 20 40 10 30 90which will even let you use anonymous functions
=a(10,function(x) return x,x*x,x*x*x end) 10 20 40 10 100 1000Of course if you forget the function, its not very happy, so I attempted to make it more robust:
a=function(x,fn) return x,x*2,x*4,fn and fn(x) end -- you can use asignment interchangably with named definitions =a(10) 10 20 40 nil =a(10,b) 10 20 40 10Hmmm, not so good. Making a table didn't work any better because then you get a table reference back, not a set. You get into similar trouble in Perl right around now, but perl has the dereference operator and slice functions, and I don't know what the equivilent is Lua is yet. Oh well, enough fun for one night.
Thanks to Brand Mantra for the amusement. And if Alaska Air ever decides to extend service to Flagstaff, I'll think about flying with them.
.c.o: $(CC) $(CFLAGS) -c -o $@ $< .cpp.o: $(CXX) $(CXFLAGS) -c -o $@ $<I now had:
$(OBJ)/%.o: %.cpp $(CXX) $(CXXFLAGS) -c -o $@ $< $(OBJ)%.o: %.c $(CC) $(CFLAGS) -c -o $@ $<But I really hated putting together a list of the object files with the sub-directory in front. I tried using a really short variable name, but it was still ugly:
OD= obj OBJ= $(OD)/hm_core.o $(OD)/hconf_core.o $(OD)/hconf_module.o $(OD)/hm_config.o ...Ugly, but isn't there a better way? I asked around originally, but not widely enough, turns out there is a way:
OD= obj OBJ= hm_core.o hconf_core.o hconf_module.o hm_config.o ... BUILD_OBJ= $(addprefix $(OD)/,$(OBJ))That's just sooo cool. Almost makes me want to read the man page for GNU make(1). Oh, wait a minute, the useful information isn't in the man page. It's in this help system called info which uses emacs key bindings for navigation. So first I would have to go read the man page for info so I could use it, oh wait, the useful information isn't in the man page ...
Oh, forget it.
This is the new Schwinn StingRay, designed together with orange county choppers. Looking at the bike in the stores, I could only think to myself that it wasn't a bicycle, but rather a motorcycle with pedals. The rear tire is like five or six inches wide. It looks really cool, but can a 14 year old really pedal it around town? Maybe if you added a motor ...
Oh well, maybe I'm just getting old.
I'm sure they went through the same thing when the printing press came out. That was a radical change (where web logs are not). The printing press allowed people other than the government and church to distribute ideas beyond their direct social group, and more importantly, led to a worldwide drive for literacy of the common people. Before that you only learned to read if your parents were rich enough for a tutor, or if you were high enough in the church. There was a lot of control over information (since it was not practical to copy most things). Books were extremely rare and precious. Predictably the church was against the printing press. Putting the bible into regular people's hands where they could read it themselves. That's just dangerous.
Web logs pale in comparison. Printed media has already had to deal with the web for nearly a decade, and they're still standing, though not without some holes punched in the status quo here and there. The major difference blogs bring is that they legitimize far more niches. I can now read about the trials and tribulations of other programmers, assistant directors of technology in the governments of foreign countries, venture capitalists, protocol hackers in india, and homeless machinists in LA. In the same way, if they can find me, others can read about my adventures TIG welding, my quest for good aluminum ingot molds, various technical difficulties with the electronics that surround me, my neverending battles to pound C++ into something useful, random forays into science, and things I'm learning from my kids.
Whats it all going to amount to? I have no idea, but I keep putting my ideas down, because I think they're interesting. If nothing else, my kids can look back in ten years and shake their heads at my strange ideas. Other than them, I'm not writing to any particular audience, nor am I expecting one to show up. That's the secret down side of publishing--just because you wrote something, doesn't mean anybody will read it.
The most popular thing I've written so far was about messing with Fluorine in a college lab, and how the stuff can kill you easily. Somehow that article got picked up by 0xdecafbad which has a lot of readers, and suddenly I had tons of traffic, and was ranked number five on Google for technical difficulties. That's all long since faded, and life seems to be back to normal around here, though according to the logs I have a few regulars and I get interesting contacts from time to time from other people about various things I've written about.
That's probably the killer app for weblogs (sorry, weblogs are not a killer app themselves): helping create critical mass around ideas. Don Park digs up SQLite or LUA, and then after digging around in it I put up more information about what its all about, or go yell at him for wasting my time (but in a good way). Or Brad Feld and Fred Wilson start ruminating about what these logs are for and I can wade in with my take on writing, publishing and audiences. Or I can put some crazy ideas out there about future energy solutions and get some feedback as to where my science has gone wrong.
I guess the reason I really keep at it, is that I can keep in touch with the bigger world this way. Being isolated out here in Flagstaff, the local scene doesn't provide much in the way of stimulating conversation. With the blogsphere, and the internet in general, I feel like I'm still part of what's going on, and can make my small contribution to the bigger picture. Oh, and maybe get venture funding for my startup after we've got a couple more customers.
At the pilot for the Masters of Fine Arts in Software, I was once again motivated to get off my duff and get back into the trenches with a new language, and several others were very heavily into Ruby, so I thought I might go that way until Richard made a pitch for Lisp (which I wasn't that interested in) and CLOS. CLOS is Common Lisp Object System, and it sounded really powerful, so I went away thinking that maybe I should find out more about CLOS.
After searching far and wide, what I found was a bunch of different LISP dialects, and notes about each one like: "A really good implementation, but not very stable." or "looks promising, but couldn't get it to install." which led me to realize that there was almost no way I was going to be able to find a usable Lisp and get started with it without some help (which I didn't have). I also found a great series of articles by Paul Graham, describing what Lisp was and wasn't supposed to be, where its power was, and how the Lisp community had shot itself in the foot and destined itself for obscurity.
While Lisp has a number of great features (like memory management and runtime binding), what everyone was enthralled with was the fact that it has no syntax, and instead is written as expressions, which are parsed into lists, and then can be manipulated at runtime. Lisp's most powerful feature is its macro system (and the fact that the macros can act on themselves), so its really easy to create your own language--in fact the Lisp community is continually re-fracturing itself into thousands of splinter groups, so that its almost impossible to share any progress. This is a disease the smalltalk community seems to have as well, only they're not continually redefining the language, its just their environment that diverges and the fact that they don't have source files.
I've plowed into C++ templates enough to realize how having a separate limited language for macros is a shortcoming, but I was going to wait on the Lisp side of things to see if someone could cook up something resembling a syntax, and the ability to do useful things (like make system calls and communicate with other programs).
Then, Don Park dropped another one of this techno gadget bombs: Lua. Lua is a scripting language designed to be light, fast, and easily bound to great things like C & C++.
I did a quick background check on it and found this one article which described a set of speed tests between MzScheme (a lisp like thing), Ruby, Python on Lua. The author was hoping that MzScheme was the fastest, but it wasn't, though it made a respectable showing. The results were: Lua was always the fastest by quite a bit, MzScheme and Python switched for second and third, and Ruby was always last by a mile.
That pretty much sold it.
So I downloaded some Lua stuff and got started. So far I haven't scratched the surface very far. Tables are a builtin in Lua, though it does some weird stuff and lets you use them as lists too (basically using ints as keys from 1..n). One thing that is interesting, is that you can do multiple assignments, sort of like in perl:
And also like perl, they tried to be clever witha,b=1,2 ; val1, val2 = val2, val1 ; -- swap two vars without a temp
AND
and OR
. Now in perl you can do cool stuff like indx1= getindex() || 1 ;
so that if getindex()
came back with 0, you could assign it a different value. Unfortunately if 0
was a valid number you had to write out the test for undef
the long way. Perl 6 adds indx1= getindex() |& 1 ;
which will only return 1
if getindex()
returns undef
. Perl of course also lets you do things to existing variables, so in perl 6 you'll be able to say: indx1 |&= 1;
which is amazing compact and somewhat oblique to novices. But trust me, its cool, and I'd have used it all over the place if it was in perl 5.
Unfortunately Lua does not have increment, or the common C shortcut: a += 1 ;
which I am really scratching my head about, but it does have some pass through on OR
and AND
. OR
is of course supposed to be like ||
, but I had never seen anyone try and do a passthrough in perl with &&
, so I was kind of scratching my head about what it was for till I got to the end of the section on expressions where they explained that they tried to implement the a= expr ? val1 : val2
syntax from C. Basically, its supposed to work like this:
Unfortunately, if val1 isfinalval= expr AND val1 OR val2.
false
or nil
then it doesn't actually work, so you can say the ternary C operator is partially supported; which is to say if you use this in your code and you know what you're doing it might work.
So far my impression is that the syntax could use some cleanup, the tables are neat (though perl has tables too), and I'm still waiting to find the silver bullet. But I'll keep plugging away at it for now.
I have a massive collection of laser disks (they were these large platters, like records, only they were movies) and so far our kids are now old enough to watch two of them. The first one Max could watch is The Brave Little Toaster, which actually involves a number of advanced issues (like nightmares, jealousy, and a junk shop owner that guts appliances for their parts), but most of that seems to fly right over Max's head and he's into the car crusher at the end. "It maaashed them into little BITS."
This week the new favorate is Wallace and Grommit's Grand Day Out. This is a pretty good film for kids, though some of the jokes are going to be over their heads, but its good clean fun. Of course after that movie played, the disk flipped over and started The Wrong Trousers, which includes such issues as deception, psychological warfare, slavery, theivery and attempted murder. But in the end, after a spectacular model train chase, the good guys win, and all is well--I guess. Now to explain what's going on to Max...
Actually, the most interesting outcome was on day two (of repeated viewings), Max declared that he need some parts because he was going to build a rocket. To JonMarie's credit, she took him down into the basement (I'm still working upstairs where its warm), robbed my cardboard box collection for a rocket body, robbed my egg carton collection and borrowed my dry erase markers to create buttons for the control panel, robbed my cardboard tube collection for the rocket engines, and rummaged through my scrap wood collection for some 45s for fins. See, I've been planning ahead for having kids a LONG time. The results were satisfactory for Max, and he set out in his space ship (after making an emergency dash for crackers) to the moon.
Sure enough, its Friday and I'm working down in the basement (which is still a cool 64F) and I'm suddenly hit by a case of the chills. In fact, after coming upstairs, it still takes three layers of clothing and a heavy comforter for me to feel warm upstairs where its 79F. Check my temperature: 105.6F. Dang that's hot. Take some ibuprofen and crash for the evening. The next day I'm death warmed over, but I have enough sense to avoid trying any heavy mental lifting. My brain is so bunged that there's no way I could do anything useful like code. I imagine its a little like Charlie (in Flowers for Algernon), knowing that once before there was more capacity there...a brighter spark, but only being able to remember it like a dim memory. In my case I'm hopeful that at least some of my brain will return (baking your brain is not good for it) as well as my strength, energy, and ability to tolerate a room temperature lower than 95F.
On the other hand, I have to really recommend forehead thermometers. We ended up with this one after our kids decided the ear one was a hammer:
They're just as cheap these days ($35), and work just by pressing to the forehead (or behind an ear), and dragging it around an inch or so so that it runs over a blood vessel or two. Quick, the kids don't mind it, very easy to clean, and supposedly more accurate than taking a reading in the ear.
Now that they're on the web, you can browse their inventory there, but there's something cool about having their entire inventory laid out in front of you where you can check it out. This picture of wrenches just doesn't convey the massiveness of a TWO FOOT adjustable wrench.
Max spent equal time playing with a trike and a pair of welding goggles which he wore and pretended to weld (like his papa does). This is how we ended up spending two hours at the show.
,
I probably bought more stuff than I need (like a 10 pack of grinding wheels for my 4 1/2 angle grinder which I've never ever used), but thanks to a little strategy meeting with my metal shop teacher, I avoided buying some things that would have been crap. So, just out of curiosity I browsed around last night looking for random items like tap & die sets. In the process, I ended up finding H & H industrial products which offers "quality industrial supplies" if your definition of quality is "imported from taiwan". What's impressive is that for the tools that overlap with cummins, their prices are actually better. They also have a bunch of higher end milling machine accessories that alternately had me drooling or scratching my head.
If anyone knows what a Radius and Angle Dresser is actually used for, let me know, I have no idea.
First of all, I'm working on multi-threaded code, which is always prone to strange behaviors and is very difficult to debug, but I wasn't really thinking that was of significance until I totally unwound the problem. There was unfortunately this delicate race condition which could make code which shouldn't work, suddenly work properly. Thus allowing me several hours of self indulgence as I mistakenly searched for the error in the compiler.
So I had a base class which needed to launch a thread and run its own handler:
class target { public: target() ; virtual ~ target() ; void launch() ; private: virtual void run(void) ; static void * entry(void *) ; } ; void target::launch() { pthread_t tmpthr ; pthread_create(& tmpthr, NULL, target::entry, this) ; } void * target::entry(void * atarget) { target * ref= (target *) atarget ; ref-> run() ; return ref ; }and then I had a sub-class which overrode the run() method.
class monitor_class : public target { public: monitor_class() ; protected: virtual void run(void) ; ... } ;Now in the debugger, monitor_class::run() would run, but from the command line target::run() would run instead (as demonstrated through the judicial placement of printf's--knowing how to debug without a debugger is a necessary skill, for there are many circumstances in which a debugger is not available or not helpful in assessing the problem.) So clearly, there was some bug in the compiler and I had to figure out what it was, or at least work around it for the time being.
First I took a look at the typecast in target::entry() but except for switching to dynamic_cast<target*>(atarget) which didn't work in the debugger either, that wasn't helping me. I then tried making target::run() a pure virtual (by defining it virtual void run() = 0, but that just got me an exception at runtime: "pure virtual being called". I then worked backward and did a test call to run() in target::launch(), before doing all the casting. This was also calling the wrong function, and after staring at this for a minute or two I thought to myself to look at where I was calling launch().
Turns out I had decided to be clever and called launch() here:
target::target() { launch() ; }
Ouch. Never call a virtual function from a constructor, you don't get the answer you want. At best you get the methods that belong to the constructor class, at worst the results is undefined. Of course launch() wasn't virtual when I put it there. I must have decided to get clever later and wasn't watching for this side effect (and somehow the debugger pandered to my bad habits and kept me happy right up until I tried to run it stand-alone). Well, I'm certainly not going to do that again.
Good enough for sheet metal work, that's for sure.
Feb '04
Oops I dropped by satellite.
New Jets create excitement in the air.
The audience is not listening.
Mar '04
Neat chemicals you don't want to mess with.
The Lack of Practise Effect
Apr '04
Scramjets take to the air
Doing dangerous things in the fire.
The Real Way to get a job
May '04
Checking out cool tools (with the kids)
A master geek (Ink Tank flashback)
How to play with your kids