HNHacker News
TopNewBestAskShowJobs

KrisJordan

1,721 karma · joined May 4, 2008

I teach computer science at UNC.

http://krisjordan.com

http://twitter.com/KrisJordan

submissionscomments
KrisJordan··on Dynamic Invocation in PHP Exposed
Didn't intend to cause harm in "straw-man"ing. I think it's valuable to know where people are coming from. You care enough about programming languages and verification to have a blog on it, that's awesome. It's perspective.

No where in the post is there an example advocating dynamic invocation based on computed strings. No where. In fact, the more I read your responses the less I believe what you're saying has anything to do with the contents and examples of the post. We're on the same page here: dynamic invocation with computed strings: bad. spaghetti code. evil like eval.

> What does "dynamic invocation" have to do with higher-order functions?

Everything? Whether you're rolling your own or making use of PHP's built-in higher order functions, like array_map http://us.php.net/array_map, you're dynamically invoking something: a lambda, a function, an instance method, or a static method. Unfortunately these are distinct things in PHP. So with array_map its first argument is a callback, or something that returns true to is_callable as described in the post. What you're arguing is that you should never send a string name of a function to array_map, but should instead wrap the invocation in a lambda. So..

  array_map(function($s) { return strtolowwer($s); }, $array);
Is preferable to:

  array_map('strtolowwer', $array);
Point blank, it's just not in PHP. It's more than twice as slow, it takes more than twice the memory, and, most importantly is every bit as unsafe. Notice I misspelled lower with an extra w? Let's imagine that's a bug, a programmer's typo. Neither case will error out until array_map is executed which means both parse and generate opcode just fine. Reconsider the function call wrapped with in a lambda. What must it mean deep down for PHP to be able to generate valid opcodes on a pure method call to a method that doesn't exist? It means the internal opcode must simply store the method name as a string waiting to be executed. So once we hit the op a table lookup based on a string in your code happens. Both ways. One string is wrapped in quotes, the other in a far more elaborate construct.

As for reflection, I'm all for it but in PHP a reflected function or method object is not a callable, thus cannot be passed to a function like array_map. Even if you could, I do not believe that, in PHP, the following is any less evil:

  array_map(new ReflectionFunction('strtolowwer'), $array);
Again, more memory, more code to execute, won't error out until runtime.

I really don't think you or I disagree on anything in terms of "best programming practices". The only thing we seem to disagree on is what this post was about and trying to demonstrate/advocate.

KrisJordan··on Dynamic Invocation in PHP Exposed
Having a blog about programming languages and formal methods I understand the basis of your disgust with PHP. In a perfect world all programming languages would use robust type systems and be capable of formal verification. PHP makes no attempt at either.

Out in user land there are all sorts of scenarios where dynamic invocation makes sense. Higher-order functions are the most obvious. Is mapping strtolower on an array of strings really spaghetti code?

Most uses for dynamic invocation are at the utility/framework level, not in application land. You're right, it's dangerous when used improperly, but you should consider coming down from the theory clouds if you believe dynamic invocation and goto are in the same boat on the river styx.

KrisJordan··on PHP as sexy as Scheme using lambdas and recursion
The point is not to argue some kind of replacement of scheme for PHP. Or one language's superiority to another. The point is to show its possible to write functional, good looking PHP. Letting the "neat things" of LISP influence the way you write in other languages. Internalizing concepts that are first class in other languages by trying to adapt them to a language where they aren't first class is a great way to learn. Learning and being influenced by other's great ideas is how all languages and communities make progress. This is why Scala is such an incredible language to experience. It was shameless in its influences and its desire to merge OO and FP. Making connections between disparate languages like the layman's PHP and the academian's Scheme is exercise for the mind.
KrisJordan··on PHP as sexy as Scheme using lambdas and recursion
Re "and probably won't understand code written thus".

Rather than giving up on the masses of "PHP coders" by labeling them incapable of functional style programming, recursion, etc, why not try to show them? If they're capable of wading through the inconsistencies of PHP they're pretty damn capable in my book. Sure they may lack the rigors of a computer science background but that doesn't mean they're uninterested.

Showing a "PHP coder" a different paradigm of programming in a different language is going to be less effective than trying to express it in the language they know. Personally, I'm really enjoying the challenge of taking the beautiful concepts taken for granted in many other programming language circles and teaching/expressing them in a language understood by the "masses".

KrisJordan··on Functional PHP 5.3 - What are Anonymous Functions and Closures?
The use syntax is a little weird at first but it turns out to be straightforward to understand. In fact, being explicit about what is being closed over makes the function itself easier to understand.

PHP, being the quirky language that it is, needs the use syntax to enable closures for cases where there are dynamic variable references. This is a bad example but illustrates the problem:

$foo = 'bar'; $fun = function() use ($foo) { $var = 'foo'; echo ${$var}; }; $fun(); // output 'bar'

$fun = function() { $var = 'foo'; echo ${$var}; }; $fun(); // fails

Sure, you could close over the entire local namespace but that's an efficiency nightmare and leads to unpredictable code.

KrisJordan··on Functional PHP 5.3 - What are Anonymous Functions and Closures?
Fixed. Thanks.
KrisJordan··on Convincing you to do it wrong (PHP and unsalted passwords)
The third conflated point is a rant of Perl over PHP.

"His language convinced him to do it wrong, and now he is pretty much stuck. And that's bad."

PHP doesn't convince you to roll-your-own over use-someone-else's. The author could have just as looked to use PEAR as you looked to use CPAN.

http://pear.php.net/packages.php?catpid=1&catname=Authen...

http://pear.php.net/manual/en/package.authentication.auth-ht...

KrisJordan··on On PHP 5.3's Namespace Backslash Backlash: The PHP Internals Team was Right?
"Half-ass Solution"

The PHP internals team could have pushed 5.3 out the door last November with :: as the separator. It was in the alpha. It worked. Except it didn't. If they had pushed it out then, knowing it broke down, that's a half-ass solution.

They changed it. They made it right. It pushed the release back by over half a year. That's hardly half-assed.

KrisJordan··on On PHP 5.3's Namespace Backslash Backlash: The PHP Internals Team was Right?
Here is an example of an ambiguous case:

// classes.php /////

namespace foo::bar;

function baz() {}

namespace foo;

class bar { static function baz() {} }

// someotherfile.php /////

include('classes.php');

foo::bar::baz(); // Ambiguity

/////

A proposed work around for the ambiguity was being explicit about ambiguous cases.

The internals team wanted to do ::, they did ::, and they convinced themselves otherwise (and suffered through a lot of pain in the process).

[17:00:05] <@CelloG> I am the strongest advocate for :: - every patch I have made up to this one was designed to preserve it, and I am convinced it just isn't technically possible to use it

http://wiki.php.net/rfc/backslashnamespaces#resolution_of_t_...

KrisJordan··on On PHP 5.3's Namespace Backslash Backlash: The PHP Internals Team was Right?
The lust has nothing to do with the syntax and everything to do with the functionality. Namespaces are long overdue in PHP (how has it taken so long)?

This is going to make developing larger scale projects (and projects that mix and match 3rd-party libraries) very different than pre-5.3

The initial uproar over the backslash failed to provide any commentary on the underlying implementation. I regret conflating the syntax with the implementation because the implementation is rock solid. The syntax, with a little practice, winds up feeling more natural than you'd think (or perhaps feel comfortable admitting :)

KrisJordan··on Windows 7 Ink Input and Math Handwriting Recognition
When I was a graduate student at Brown I was advised by Andy van Dam and was a member of the 'Microsoft Center for Research on Pen-Centric Computing' (http://pen.cs.brown.edu/)

The research group had developed an in-house math recognition engine that was very impressive but required some training and relied on some heuristics that worked for the group but likely wouldn't work for a general population. The math recognition engine was built out of necessity because Microsoft's previous math reco was terrible.

Gates, being a huge proponent of natural human interfaces and the pen in general, and the folks at Microsoft have put major efforts toward what's going into 7. They actually had two different teams working on math reco, one in China and one in a European center. The China team came out to visit us once and their engine was driven by a massive corpus of user-written input. From the sound of things their engine was further along so I wouldn't be surprised if this is what is in 7.

Microsoft has poured significant resources into handwriting recognition development, internal research, and external research. 7's support is going to be the best we've ever seen.

KrisJordan··on Scala is Not a Functional Programming Language
From reading Odersky's book Scala's notion of currying functions i.e. f(x:Int)(y:Int) is differentiated from partially applied functions. Here is his currying example using a partially applied x():

def x(a:Int, b:Int) = a + b

val y = x(1, _:Int) // y is a partially applied function

y(2)

==========

Much better looking than his snippet:

def x(a:Int, b:Int) = a + b

def y = Function.curried(x _)(1)

y(2)

KrisJordan··on Juno: A Lightweight and Simple Web Framework for Python
They're not used as executable code. They're used as meta data. Not much different than an XML file sitting beside of a script, except that

1) it's more DRY because for external files to say something about a construct in code there is repeated information, i.e. <route><to><class>Foo</class><method>bar</method></to><from><method>GET</method><url>some/url/here</url></to></route>,

2) because you're using the PHP language to specify metadata about a PHP construct refactoring is easier, i.e. change the name of a function and you don't have to go update your routing somewhere else,

3) having the metadata inline with code turns out to be mentally lightweight once you get over the initial shock of seeing metadata in a comment.

KrisJordan··on Juno: A Lightweight and Simple Web Framework for Python
PHP has its flaws, no doubt.

It's little known that doccomments are a PHP language construct that can be reflected over just as Python's doc strings can be introspected with __doc__.

http://us3.php.net/manual/en/language.oop5.reflection.php#la...

Thus !Route GET, a/good/$programmer is just as much a language construct in a PHP program as @route('a/good/:programmer') is in a Python program. The key difference is Python defines at the language level how that particular bit of script is expanded as a decorator. Recess does its expansion of annotations at the framework level.

Python is a much better and more thoughtfully designed programming language than PHP, for sure. PHP has loop holes, doccomments is one of them. PHP does not do anything, by default, with a doccomment, but it does give an opportunity to introduce meta-data on classes, methods, and properties and easily reflect over that meta-data and then it's up to the programmer to define a 'DSL'.

In this sense PHP offers something powerful and dangerous. Recess choose a simple data format, such that parsing can be expressed in a regexp that is then processed by essentially 'Constructing a class of type [FirstWord] and call init method with array of [Following words as a PHP array] - finally make these annotations available through reflection'. Not too much different than annotations in Java/C#. Simple enough that the danger is mostly negated and the utility makes the 'hack' justifiable.

For a better-written justification of why this design decision was made for Recess: http://www.recessframework.org/page/on-hiding-our-dick-tracy...

(Aside: This is why I'm a huge fan of Scala - extending a language with the language is awesome.)

KrisJordan··on Juno: A Lightweight and Simple Web Framework for Python
The idea of routing annotations is used extensively in the Recess PHP Framework, except that in Recess the annotation also takes the HTTP verb (GET, PUT, POST, etc.) to make beautiful, RESTful URLs even easier to work with.

http://www.recessframework.org/page/routing-in-recess-screen...

KrisJordan··on Ask HN: Why no love for PHP?
I abandoned PHP about two years back. 8 months ago, after going to a conference and hearing the folks at Flickr talk, specifically Cal Henderson (http://www.krisjordan.com/2008/09/16/cal-henderson-scalable-...) I got re-energized to take another stab at making PHP pleasant to work with.

The results of my last push evolved into a PHP framework: Recess. (http://www.recessframework.org) It's got annotations for a declarative, meta-programming style. It's inherently RESTful (and more fine-grained content negotiation is coming soon). The Models/ORM are lazy so that you can chain together queries that evaluate at the last minute. Recess deploys just fine to commodity $5/mo servers and was designed to be lightweight and fast without giving up object-oriented design (a la Code Igniter).

What I feel gets lost in the "PHP is terrible" literature is a distinction between PHP as a programming language and PHP as a technology / platform. As a programming language, from an academic perspective, PHP is embarrassing. As a technology/platform it's incredibly well suited for web applications because that's exactly its intention. PHP's shared-nothing execution model, simple deployment, efficiency & performance make it a great technology for authoring web applications. Tooling has gotten much better too with Eclipse's PDT & XDebug.

If you're growing tired of PHP and looking for a platform/framework to develop on that is more productive and enjoyable try taking Recess for a spin. For me, at least, it's made PHP fun again: http://www.recessframework.org/

KrisJordan··on How to be a program manager
Though the processes sound similar, the scope and details each is emphasizing are different.

Spolsky: "feature"

Fried: "app"

Suppose either is designing GreenfieldGloryApp - he might start with a one-page vision statement. He might then make some very high level mock-ups of scenarios. Maybe they would even be done in HTML. This is where they diverge: At this point 37signals would start building. Fog Creek would iterate 'specs' many times further by drilling down to feature or feature-set level functional specs. Each feature-level spec would start with a vision statement and then be fleshed out with mocks and "detailed descriptions".

KrisJordan··on Download the internet
Is their tracker working for anyone? Not so much here.
KrisJordan··on Don't Blame CSS For Your Incompetence
You're actually proving the point those articles are agreeing on. Your CSS changed to make that possible. The point is when you change the ordering of DIVs your CSS often also has to change. So they are not as loosely coupled as one would hope a Model-View relationship might be.
KrisJordan··on Don't Blame CSS For Your Incompetence
This article, while well intentioned, misses the point it was trying to prove. The article gives an example of a three column layout with two different orderings of the <div>'s in HTML to prove "ordering doesn't matter". The problem is the CSS in the examples changes along with the re-ordering of divs. This is exactly the point it was trying to disprove.

Though the coupling between CSS and HTML is loose it's not quite loose enough to allow HTML to be arbitrarily reordered and maintain the same presentation without also modifying the CSS.

KrisJordan··on Why CSS Should Be Used for Layout
The table tag's purpose is to host tabular data. Hence the <thead>, <tfoot>, and <tbody> tags for column headers, footers, and body data respectively.

Cite: http://www.w3.org/TR/html401/struct/tables.html

KrisJordan··on Why CSS Should Be Used for Layout
Saying "CSS is a better solution than Tables for reasons [X,Y,Z] but it is at the cost of a higher learning curve," is much different than saying "CSS is a better solution than Tables for reasons [X,Y,Z] but you're too incompetent to understand."

CSS layout problems are not why so many people use Flash. Flash has popularity because for pure designers working in a GUI on a canvas where you can pixel place every item with drag-and-drop is natural and taught in school.

As for examples, the article calls out the canonical CSS layout example site made specifically for this purpose years ago: http://csszengarden.com/

KrisJordan··on Why CSS should not be used for layout
An HN submission that tries to be more even handed:

http://news.ycombinator.com/item?id=464342

http://www.newmediacampaigns.com/page/why-css-should-be-used...

KrisJordan··on Why CSS Should Be Used for Layout
The jury is not still out on whether tables are suboptimal. They're easier, that's their only advantage.

The rule of getting something working quickly should not increase the cost of doing it right in the future.

KrisJordan··on Ask HN: What web framework(s) do you guys use?
I've been working on a PHP framework that is similar in the 'full-stack' approach of Cake but has performance characteristics of CodeIgniter. It's called Recess and can be found over at http://www.RecessFramework.org
KrisJordan··on Why I hate software patents: IBM patents trim()
The patent is for a database column setting which will 'auto-trim' all data. So instead of having to call the trim function every time you insert or update your database this patented setting does it automatically. Hard to believe these things get patents.
KrisJordan··on Why PHP won
Agree with your additions completely and would amend your #3 to say that PHP was big on re-use in the small, as well. I've known folks starting out with PHP who cobble a script together by copy-pasting snippets of code from here and there. Inelegant, yes, but when you are working on a small project it was usually effective.

This leads me to one point about PHP's documentation that I was surprised not to see. Their documentation has always (as long as I can remember, at least) had public comments. On many occasions questions I have had or example code I needed was crowdsourced by the public and located in-line below the function reference. I have been surprised other platforms don't make more extensive use of this.

Finally, in response to your "I guess I'm looking for something else." Understand your discontent - I've felt it myself over the past couple years and have found myself toying with Djagno, et. al. This fall I found myself returning to PHP with a mission to create a framework that I could use and not feel shamed to be in PHP. It's still early in development (4 months) but I believe it is looking good and getting exciting. It's called Recess, check it out sometime: http://www.recessframework.org/

KrisJordan··on Recess PHP Framework Public Preview
Will do, thanks.
KrisJordan··on Recess PHP Framework Public Preview
Thanks for the feedback. The belief is that though this practice may feel uncomfortable at first it should make things easier to mange in large applications. The premise is routes don't exist without a controller and method to route to - so why duplicate that information in another place? With routes stored somewhere else if you want to change a method name in a big app (especially one you're not the sole author of) there is an extra step of finding all the places that method name was potentially referenced. Routes in controllers is an attempt at being more DRY than routes.rb and less raw than Django's list of regexps.

For what its worth Rails actually generates code with comments that give examples of routes in its controllers: http://tinyurl.com/5jstgu

Regarding not having to register, here are links directly to the bits: http://news.ycombinator.com/item?id=410119

KrisJordan··on Recess PHP Framework Public Preview
This is towards the top of list of documents to produce. More screen casts demonstrating other features of the framework are also on the way.

The overarching mission of Recess is to provide a full-stack framework with functionality along the lines of Cake but designed for PHP (as opposed to attempting to clone Rails which leads to poor design decisions as PHP != Ruby). This way Recess will achieve the performance characteristics of CodeIgniter without sacrificing higher-order functionality of modern full-stack frameworks like Django and Rails.

For links to download without registration: http://news.ycombinator.com/item?id=410119

← PreviousPage 3 of 5Next →