I’m pretty sure most Railers don’t think about this kind of thing, but controllers.. they are state machines. Sure, most controllers don’t have much state. They implement CRUD, which means the only state you need is the state of validness of your model. The control flow is directed by #valid?, with maybe a confirm message for #delete.
But shopping carts are not that simple, and probably shouldn’t be. You want to collect the user’s purchased items, their address, credit card, and then confirmation of it all. In that order. Making them create/read/update/delete an address, create/read/update/delete a credit card. Then having them add the address, credit card, and items to a Basket object. That’s just too many steps and anyone can tell that would be really silly as a user flow.
Could you reduce 95% of controller actions to just CRUD? Yes, you probably could. But that’s now how we think. Sometimes you need more than one step to produce a good user flow. Even with Ajax, you still sometimes want to reload the entire page, or allow older browsers to use the functionality easily.
No.. Controllers ought to be modeled after the user flow, not what’s easy (or hard) about the development process. The reason that web apps tend to be so simple is not because of some intuitive understanding of what the user wants.. And I’m sure that simple apps win over complicated ones any day. No. While I would rather write simple code, sometimes the domain model expects more. But we don’t have any off-the-shelf abstractions with which to go above the request/response cycle.
We need a plugin that can do this. We need an acts_as_state_machine for controllers. I’m probably not going to write it, since I’m neck-deep in other projects, but if I had the time, I would. It would need to be a macro of some sort, something to maintain session variables as they go in and out of scope. With maybe even possibly a state chart to show what the user flow looks like to clients and less tech-oriented types. That would definitely help to get a mental snapshot of where things might screw up.
In the time of spirits thoughts grew till they over topped my head, whose offspring they yet were; they hovered about me and convulsed me like fever-phantasies — an awful power. The thoughts had become corporeal on their own account, were ghosts, e. g. God, Emperor, Pope, Fatherland, etc. If I destroy their corporeality, then I take them back into mine, and say: “I alone am corporeal.” And now I take the world as what it is to me, as mine, as my property; I refer all to myself.
– Max Stirner, The Ego and Its Own, p 15.
Freelancing seems to have no sensible pattern to it. It’s very chaotic in nature. Each prospect is another batch of spaghetti thrown at the wall. Sometimes none of it sticks.. and you’re left with nothing for 2-3 weeks. Sometimes it all sticks, and you have 5 clients expecting work done by the end of the day! The ups and downs are crazy, but I’d rather have that than a boring office job any day.
Is it just me, or do all these new software manifestos seem more like art manifestos then like serious critiques of the industry?
Like Design Driven Development.. Reading the Wikipedia of this philosophy, you get some very dynamic prose, but you’re let down because they’re not really saying anything new..! Just re-contextualizing existing problems. Next time I get the chance, I’ll start telling people I’m a futurist programmer or something.
Ionize now has a home. See if you can break it :)
Messing around with SexpProcessor
require 'rubygems'
require 'parse_tree'
require 'ruby2ruby'
Sexp.class_eval do
def unbox
if length == 1
self.first
else
self
end
end
end
class Lispify < SexpProcessor
def initialize
super
self.auto_shift_type = true
self.require_empty = false
end
def process_vcall(expr)
s(expr.first)
end
def process_call(expr)
expr = Sexp.from_array(expr)
first = process(expr[0]).unbox
second = process(expr[2]).unbox
s(expr[1], first, second)
end
def process_array(expr)
process(expr.first)
end
end
Which results in:
>> equation = %q{ x + x * x - x }
>> Lispify.new.process(ParseTree.translate(equation))
=> s(:-, s(:+, :x, s(:*, :x, :x)), :x)
>>
So now you’re in perfect shape to perform some kind of symbolic computation on the equation.
I’ve renamed Php::Parser to Ionize. Not as mystical as I would have liked, but it works for now. It’s got a new home at GitHub.
The TODO on Ionize is now:
- Create a basic demo site to show off it’s current capabilities
- Get Php::Environment up and running, even if that means I have to use libphp.so to handle top-level functions
- Replace the translate stuff with ParseTree’s SexpProcessor, which does 95% of what I’m already doing
Emacs find/replace across directories
M-x find-dired[Enter](make sure it’s in the right directory) [Enter]
-name '*.rb'[Enter]
% m rb$[Enter] (or just mark individual ones with ‘m’)
M-x dired-do-query-replace-regexp[Enter]
regexp-to-search-for[Enter]
string-to-replace-with[Enter]Then don’t forget to save.
Or there’sM-x tags-query-replaceif you have TAGS set up. If you use speedbar (I don’t), I think it provides a way to do it with more of a notion of a “project” than just a directory.
Restaurants with great food seem to prosper no matter what. A restaurant with great food can be expensive, crowded, noisy, dingy, out of the way, and even have bad service, and people will keep coming. It’s true that a restaurant with mediocre food can sometimes attract customers through gimmicks. But that approach is very risky. It’s more straightforward just to make the food good.
By my love and hope I beseech you: Do not throw away the hero in your soul! Hold holy your highest hope!
I’ve been using Dhaka to do PHP Parser for most of the project. I started out using RDParser. But I realized how much of a toy it was when I saw how fast Dhaka was by comparison, even though my Dhaka grammar was going to be almost twice as big. However, now that the project is maturing, I’m running into edge-cases where Dhaka isn’t as good of a fit for my purposes as I’d like. Specifically, Dhaka doesn’t support Unicode by default but I suppose this could be handled. Another issue I’ve had was with it’s lack of a splat operation, so you could get back a list of nodes that match instead of just pairs.
These are only minor at the moment, but the Unicode issue will have to be handled before it could be considered ‘production’. I’ll probably be on the lookout for something similar or maybe even add the functionality I need to Dhaka itself.. Who knows.
Worst. Syntax. Ever.
String access and modification by characterCharacters within strings may be accessed and modified by specifying the zero-based offset of the desired character after the string using square array brackets, as in
Note: Strings may also be accessed using braces, as in$str[42]. Think of a string as an array of characters for this purpose.$str{42}, for the same purpose. However, this syntax is deprecated as of PHP 6. Use square brackets instead.
Compiling Ruby to Php is a step in the wrong direction
So I managed to find someone who’s doing Ruby to Php compilation. It seems to be in active development. He has a demo available, and although the source is not available, you can glean from the results how he gets method_missing working on Php: implementing message sends through a single top level function. Ultimately, that route ends up being very similar to what one would expect from Ruby to C.
If you want to know what I think, and of course you do, I think his whole philosophy is wrong.. We shouldn’t have to succumb to antiquated technology like Apache just to deploy our web apps. Even when something like Passenger, I think it’s a step in the wrong direction. It’s too easy to ignore the OS when developing. My theory is that, if you’re forced to run your own VPS, just to even deploy Rails, you’re either a) going crawl back to a lesser language and therefore leave us alone or b) actual sit down and learn how Unix works. The whole Heroku thing seems cool until you realize how it coddles you from the realities of the environment. Sometimes software barriers that are created by platforms are useful for separating the wheat from the shaft even when they’re not intentional.
Some links on embedding PHP
PHP Parser 0.1.9
Transforms a class definition:
This wasn’t all that tricky. var needed to be converted to attr_accessor. $this-> needed to be converted to self., but otherwise, it was a very straight forward transform.
class ResultSet {
var $result;
var $total_rows;
var $fetched_rows;
function set_result( $res ) {
$this->result = $res;
}
function get_result() {
return $this->result;
}
function set_total_rows( $rows ) {
$this->total_rows = $rows;
}
function get_total_rows() {
return $this->total_rows;
}
function set_fetched_rows( $rows ) {
$this->fetched_rows = $rows;
}
function get_fetched_rows() {
return $this->fetched_rows;
}
function increment_fetched_rows() {
$this->fetched_rows = $this->fetched_rows + 1;
}
}
class ResultSet
attr_accessor(:result)
attr_accessor(:total_rows)
attr_accessor(:fetched_rows)
def set_result(res)
self.result = res
end
def get_result
return self.result
end
def set_total_rows(rows)
self.total_rows = rows
end
def get_total_rows
return self.total_rows
end
def set_fetched_rows(rows)
self.fetched_rows = rows
end
def get_fetched_rows
return self.fetched_rows
end
def increment_fetched_rows
self.fetched_rows = (self.fetched_rows + 1)
end
end
Transforms a switch case, and error guard
This one was slightly trickier. The global variable $dbtype need to be replaced throughout the AST, which ended up meaning saving a list of globals for the entire duration of the transform :(. I’d like to keep going for straight replacement transforms without keeping track of state, but some of the more complicated ASTs, along with the behavior of the Dhaka parser, kind of require it.
Specifically, the switch-case AST wasn’t all that complicated but it become a bit of a challenge with Dhaka, because there is no splat operator in it’s parser generator grammar, unlike normal BNF. So nodes would end up [:looking, [:like, [:this]] instead of [:looking, :like, :this]. This required a selective flattening operation that only applied to the statement nodes but not it’s children nodes.
Finally, to give myself an extra challenge, I added Php’s error guard, which ended up being equalvalent to Ruby’s rescue nil idiom. I prefer to use the :try idiom nowadays, but rescue nil does look pretty nice.
One flaw that I should point out is that Php’s switch-case semantics are exactly like C/C++, so the case without an statements will “fall through” to a case below it. This is not true of Ruby and will have to be finagled to produce the correct semantics, probably by joining the conditional expressions, separated by a comma.
function sql_logout($id)
{
global $dbtype;
switch ($dbtype) {
case "MySQL":
$dbi=@mysql_close($id);
return $dbi;
break;;
case "mSQL":
$dbi=@msql_close($id);
return $dbi;
break;;
case "postgres":
case "postgres_local":
$dbi=@pg_close($id);
return $dbi;
break;;
case "ODBC":
case "ODBC_Adabas":
$dbi=@odbc_close($id);
return $dbi;
break;;
case "Interbase":
$dbi=@ibase_close($id);
return $dbi;
break;;
case "Sybase":
$dbi=@sybase_close($id);
return $dbi;
break;;
default:
break;;
}
}
def sql_logout(id)
$dbtype
case $dbtype
when "MySQL" then
dbi = mysql_close(id) rescue nil
return dbi
break
when "mSQL" then
dbi = msql_close(id) rescue nil
return dbi
break
when "postgres" then
# do nothing
when "postgres_local" then
dbi = pg_close(id) rescue nil
return dbi
break
when "ODBC" then
# do nothing
when "ODBC_Adabas" then
dbi = odbc_close(id) rescue nil
return dbi
break
when "Interbase" then
dbi = ibase_close(id) rescue nil
return dbi
break
when "Sybase" then
dbi = sybase_close(id) rescue nil
return dbi
break
else
break
end
end
PHP Parser 0.1.6
- Foreach now transforms to an each loop
- Array lookup
- Single statement function
- If-else with nested if
I hate working for stupid companies. Most companies I’ve worked for aren’t really stupid, just ignorant of software.. Which is fine, because most people aren’t really supposed to know much about software. But a stupid company will make you do everything by hand, when automation is the most valuable aspect of software. They’ll make you conform to stupid standards because ‘they said so’, and not because it was a part of an over-arching philosophy. In general, stupid companies just flat-out make you less productive. Some companies don’t do this. Some of them make you more productive. But what’s even worse is when those anti-productive habits that they’ve ingrained upon you start spilling over into your solo projects. That’s the worst aspect about working for a stupid company.
DSP links
I’m giving this macros in Ruby thing some serious thought.. As it turns out, the def_macro gem isn’t really all that complete and was just an experiment. There’s a slightly better possibility that I might use Raganwald’s rewrite.. But not 100% sure on that either. I might even come up with some kind of interface so end users can rewrite things like PHP’s for loops on their own, but with a decent default config.. Common cases, such as for ($i=0;$i<6;$i++) { ... } could get recognized as just iteration.. Hmm.. but that could get a bit complicated.. Like I said, it requires some thought, but it’s definitely a piece of this puzzle.
And Eliezer Yudkowsky merely confirms what we were all thinking
So you came here. Maybe you don’t understand what the equation says. Maybe you understand it in theory, but every time you try to apply it in practice you get mixed up trying to remember the difference between p(a|x) and p(x|a), and whether p(a)*p(x|a) belongs in the numerator or the denominator. Maybe you see the theorem, and you understand the theorem, and you can use the theorem, but you can’t understand why your friends and/or research colleagues seem to think it’s the secret of the universe. Maybe your friends are all wearing Bayes’ Theorem T-shirts, and you’re feeling left out. Maybe you’re a girl looking for a boyfriend, but the boy you’re interested in refuses to date anyone who “isn’t Bayesian”. What matters is that Bayes is cool, and if you don’t know Bayes, you aren’t cool.
Well.. he asked for it...