"PHP is overly verbose and terribly inconsistent and lacks powerful methods of abstraction and proper closures and easy-to-use meta-programming goodness"
Sometimes I wonder how much closures and meta-programming is just code for coding sake. I've seen lots of examples of 5 line LISP code that does something totally amazing but you don't really know what it means but it's so abstract. If you have a quick job to do, I don't see that it's a limitation in using a language that requires to build the most straight forward solution.
PHP is ugly, but for the most part it isn't horrible -- these days you can easily avoid some of the worst parts and concentrate on making code that would be very equivalent to the same code in, say, Java. PHP is very straight forward -- it means what it says.
"Your web framework in PHP probably isn't continuation-based, it probably doesn't compile your s-expression HTML tree into assembler code before rendering it."
This just sounds like over-engineering the problem.
Sometimes I wonder how much closures and meta-programming is just code
for coding sake. I've seen lots of examples of 5 line LISP code that does
something totally amazing but you don't really know what it means but it's
so abstract
You could the same for so many PHP frameworks. Why are there so many classes? Why do I have to inherit from a class I don't understand? Why am I forced to define classes at all? Why are my custom classes 50% getters/setters? Why are my objects mutable? etc. etc. etc.
(map :last-name people)
The point is if the language provides the proper level of abstraction, you end writing less of your own hand rolled abstractions.
Again the only thing I'm hearing here is arguments from people who are too lazy to actually see how things are done from a functional perspective. Get off your ass and find out. Then tell me you have a problem with it.
You don't even have to include the word "PHP" in there. A lot of frameworks include a massive amount of functionality that you're almost never going to use. And for the few times you might need to use it, it'll probably take less and less learning and less dependency on code you don't control just to code up something by hand.
But my complaint isn't about frameworks or their relative complexity. It's about how most people touting some of these solutions pride themselves on how terse the end result is. This goes well beyond DRY. A good abstraction is great for providing a clean view of the logic, but some abstractions and meta-programming take it so far that now the logic is no longer obvious.
> Again the only thing I'm hearing here is arguments from people who are too lazy to actually see how things are done from a functional perspective.
I've done functional programming work in the past (ML) but the fact is, it's just much harder to just get things done in functional languages. When you find the perfect domain mapping for functional work, it's great, but most of the time you don't have that. It's like arguing the Esperanto is a nicer and cleaner language than English -- that's probably true -- but if you want to get work done you use English.
> I've done functional programming work in the past (ML) but the fact is, it's just much harder to just get things done in functional languages.
This is 2010, we're not living in a FP vs. OO world anymore. Clojure (and I've heard Scala) preserves the greats parts about OO programming. I'm sure this is the just the beginning.
"I've done functional programming work in the past (ML) but the fact is, it's just much harder FOR ME to just get things done in functional languages."
With my addition above I agree with you 100%. Generalizing from personal experience? Let's try to raise the bar on discourse a little higher.
Fair enough. I hope you'll also complain about the original poster presuming that anyone who doesn't agree with him must be lazy and ignorant. It's a very common argument tactic whenever someone defends Lisp or Scheme: "everyone else simply don't get it."
There was a recent article posted here about people assuming, by default, that they are smarter than everyone else. Lisp has had over 50 years to prove that it can be used to develop software better than all the alternatives and it's still less successful attracting developers than languages just a few years old. It appears the previous commenter is just assuming he knows something that 99.9999% of other developers don't.
I don't advocate any particular language or platform for all possible solutions. Sometimes Java is right choice, sometimes PHP, sometimes C#, Python, etc. And whether or not a developer knows the language is a large factor but it's not the overriding factor. Trying to shoe-horn in a language of choice into every situation is a recipe for disaster. Sometimes it's necessary to learn a platform/language to effectively tackle certain tasks. So far, I've personally been unable to find a situation where Lisp seems to work. To generalize it: there is lots evidence that a vast majority of other developers haven't either. You can either assume they're all morons or not.
Come on man. We're all ignorant. I just called you out on a particular thing you seem ignorant about on which you wanted to make an absurd claim about based on your own limited experience. You should expect to get called out.
In my own ridiculously limited experience (which happens to include one new FP lang) I found your claim to be simply, irrefutably (in my mind) untrue.
The whole point of karma on HN is to keep things in balance. And I saw the need to keep the balance here. If you can't roll with that what's the point of discussion?
> I just called you out on a particular thing you seem ignorant about on which you wanted to make an absurd claim about based on your own limited experience.
Honestly, I'm not even sure what claim you're talking about. I think I even agreed with you. The whole line about lazy and ignorant seems entirely tacked on without referring to anything in particular.
> And I saw the need to keep the balance here.
You made a valid point but then you went into essentially personal attacks. That's not the kind of thing that Hacker News is about.
I can't forget to fetch the next row from the database. I can't forget to check that I'm at the end of the result set. Grouping the results is easy and straightforward. The statement and connection objects are automatically closed when the request is done. Compare that to PHP.
I'm getting better, but even today I feel a little irritated when someone says PHP was designed for simple web/database apps. I know what a language designed for simple web/db apps looks like, and PHP is not it.
Have you even used PHP? There is nothing in your above statement (or linked code sample) that isn't done just as easily in PHP. Iterate over records using foreach, check. Closing database connections automatically (or out of scope), check. I could do grouping with about the same amount of code, too. PHP has it's ugly bits but it's not significantly different in capability from most other procedural/OO languages.
This uses my company's PHP templating engine (which is open source and available at http://tierratemplates.com) and our internal CMS framework:
// controller function
public getcolors($request) {
$db = CMS::GetDB();
$request->favcolor = $db->transform($db->getRows("select * from favcolor order by color, name"), "collect", "color");
}
// and the template
{@ favcolor ?
"<ul>"
`<li><strong>{$key}</strong>: {$:implode(", ")}</li>`
"</ul>" @}
the template uses a control structure called a conditerator (more info at the site). The controller uses a data transform to convert the set of rows into a hash of rows keyed on color.
I think that is more concise and reads better than the BRL example.
Here's some possible PHP code to do what that Scheme code sample does (I've excluded the HTML for brevity):
$result = $conn->execute('select * from favcolor order by color, name');
while($row = $result->next()) {
if ($result->groupBeginning('color')) {
echo $row['color'].': '.$row['name'];
} else {
echo ', '.$row['name'];
}
if ($result->groupEnding('color')) echo "\n";
}
echo 'Count:'.$result->count();
I just came up that off the top of my head, but there's nothing impossible in there. Also, instead of field name for groupBeginning(), passing a closure would also be possible.
Nice. I've done something similar myself but I didn't take it exactly in the same direction. I leave much of grouping, wrapping, appending work to my own template engine layer. Is the source to your DSL available?
Yeah I would normally never mix the templating/html w/ the data processing but I was trying to stick to the example but w/ one line hah. Right now it is part of my new web framework which is very much a work in progress but available on http://voltron.googlecode.com the relevant code for the Array dsl is under Model/Type/Array.php and FluentLambda.php and the constant declarations are in bootstrap.php - again total work in progress so things are not as clean as they should be just yet.
sql_apply("select id,somefield from sometable","applicator_function");
PHP is a programming language, it was not designed for 'simple web/database apps' any more than any other language, you can use the building blocks provided to create access at the level you require. But you can customize it so that it does become usable for 'simple web/database apps'.
The above is a short sample of how I'd do the thing you describe and I don't have to remember to fetch the next row from the table and I don't have to check that I'm at the end of the result set, grouping is as easy as SQL will make it and all cleanup is automatic.
PHP is a programming language, it was not designed for 'simple web/database apps' any more than any other language...
Um, yes it was. See http://en.wikipedia.org/wiki/PHP#History to verify that PHP started as a bunch of CGI binaries to serve some simple dynamic web pages. The database bit came later, but at the start it was explicitly designed for quick and dirty web pages.
I never compared the state of PHP today with the first released version. I merely used the origins of PHP to argue that PHP was, indeed, more designed for simple web applications than most other general purpose programming languages.
And yes, you can make such statements about every other mainstream language. For instance Perl was more designed for text manipulation than most other general purpose programming languages. Java was more designed for multi-threading than most other general purpose languages. C was more designed for close to the machine programming than most other general purpose languages.
All of these things are true. All of these things still show in various ways. Yet every one of those is a general purpose language that can be used for anything you want.
At least the Lisp guys have figured out how to write parsers and lexers by now. (They even grok lexical scoping.)
I guess we can't blame PHP for preserving the $ in front of variable-names with all the legacy code lying around. But the following should parse in a sane language:
$width = getimagesize($filename)[0];
Adding support for this would not break legacy code. Nobody can tell me that naming all intermediate results like
$sizes = getimagesize($img);
$width = $sizes[0];
is such a preferable style, that the parser should enforce it.
By the way, this is how PHP pretends to support higher order functions:
I want to abstract away the ways my app is like every other web app. I don't want to abstract away what's unique about it. If you abstract away everything, all languages are the same.
The DSL snippet is every bit as verbose as the PHP code sample, yet somebody had to write the DSL in the first place. Not sure mission was accomplished. I think a better solution is offered by Mustache logic-less templates.
This just looks like a massive step back from a MVC setup to me. How do proponents of using Lisp for web development handle interaction with designers?
Regarding interaction with designers, I believe the answer is 'It Depends'.
As an example, in the Clojure space there are two libraries that are good exemplars of the ends of the spectrum: Hiccup and Enlive.
Hiccup (http://github.com/weavejester/hiccup) uses sexpressions to define the (ht|x)ml output. Effectively either the developer and designer roles are fused or the developer gets a design from the designer and encodes it into hiccup manually.
Enlive (http://github.com/cgrand/enlive) is (in overly simplistic terms) a selector driven substitution engine. You give it an HTML file for a template and some CSS selectors describing what to modify, alternatively you define a snippet in terms of some elements within the page. In this model the designers work is first class resource, and not modified by the developer.
This is exactly the same breadth of options as I've seen in just about any real language being used for development tools.
This is just one style, not representative of all Lisp web development. You can have any style you want. With continuations you can even use a procedural style where your program describes a workflow of multiple pages.
(Whether MVC is the right style is a topic for another discussion.)
Good too know. I would like to give Lisp a try, but I've only just being able to sell a php shop on migrating to python/django. Lisp is a near-impossible sell to every web dev shop I've worked in.
I find e.g. closures in Lisp overly verbose. The ML family of languages has a much lighter weight syntax for functions. This makes amazing stuff look less like code for code's sake.
(Though I do admit that I immensely like Lisp's macros.)
In e.g. Haskell abstractions are the straightforward way to solve a problem. Abstractions are cheap.
Closures in most Lisps are a bit verbose, but it's easy to create an alternate syntax using a macro. Arc and Clojure provide built-in shorthand for function literals that makes them much more convenient to use.
Indeed. Though with variable arity (which can be a good thing!), currying will always be at least slightly more cumbersome than in languages with fixed arity of the ML type syntax for function application.
Currying and combinators are my preferred ways of creating new functions. Having infix symbols can help a bit, but I don't see it as crucial.
Incidentally I only really began to use reduce/fold in Clean and Haskell, though I had been exposed to the concept in Scheme before, and used it a few times. But perhaps that was just a learning effect of prolonged exposure and would have happened while staying with Scheme, too.
I still like Scheme. Matthias Felleisen is doing great work using it for education.
Here are two combinators that I have actually used in my code (the first one is fairly common):
dot :: (b -> c) -> (a1 -> a2 -> b) -> a1 -> a2 -> c
dot = ((.).(.))
swing :: (((a -> b) -> b) -> c -> d) -> c -> a -> d
swing = flip . (. flip id)
Imagine (or better: provide!) Scheme versions or their idiomatic equivalents.
Of course the point-free definitions makes them a bit hard to understand, but I wanted to demonstrate terseness. `dot' also has a nice point-full definition:
dot f g a b = f (g a b)
The use case for `dot' should be obvious from the latter definition. I leave the point-full definition (and a use case) for `swing' as an exercise. Let me just note that Lisp would carry some more syntactic baggage for the definition and use of both of these combinators.
However, you can't beat Lisp, when it comes to Quines:
((lambda (x) `(,x ',x)) '(lambda (x) `(,x ',x)))
Haskell's facilities for talking about Haskell code are more verbose.
P.S. for completeness sake, to make the exercise above easier without doing a search:
The problem is most people building meaningful programs are not people with "just a quick job to do". For those people, having abstractions available allows them to focus on the harder problems that actually matter, instead of constantly reinventing the wheel.
The mental energy is probably not worth it if you are just building a blog for yourself, but in that case, the mental energy of learning PHP is not worth it either. If the job is really that quick, why are you using dynamically generated content in the first place? HTML one-off's are the most straight forward solution.
On the other hand, if you want to build a bulletproof web application, you should probably use powerful tools, figure them out once, and then actually solve your problem.
> the mental energy of learning PHP is not worth it either
You probably already know PHP. It's so much like many other languages and it doesn't require much knowledge to get started. Many of the "gotchas" about PHP are more academic than practical and if you are ignorant about these things then you are more likely to do it right. Some of the horrible stuff, like huge body of non-namespaced functions, is pretty easy to search though and then use without a lot of knowledge overhead.
I actually write very large business web applications in PHP. Crazy? Maybe. There is a bit of a sunk cost here, when the app was started most other solutions were pretty immature. However even with potentially "better" options now, PHP isn't going to burn down the house.
"This just sounds like over-engineering the problem."
Except the problem was never defined. Of the five commercial Lisp applications I've worked on, two are addressing domains (large-scale financial calculations, and a web platform/OS) where using PHP makes absolutely no sense, and the current one (ERP) where PHP was previously attempted and found not to make any sense. All three use basic techniques like closures, markup generation and metaprogramming, and one of them is continuation-based (which I think is a mistake, but opinions differ).
Sometimes I wonder how much closures and meta-programming is just code for coding sake. I've seen lots of examples of 5 line LISP code that does something totally amazing but you don't really know what it means but it's so abstract. If you have a quick job to do, I don't see that it's a limitation in using a language that requires to build the most straight forward solution.
PHP is ugly, but for the most part it isn't horrible -- these days you can easily avoid some of the worst parts and concentrate on making code that would be very equivalent to the same code in, say, Java. PHP is very straight forward -- it means what it says.
"Your web framework in PHP probably isn't continuation-based, it probably doesn't compile your s-expression HTML tree into assembler code before rendering it."
This just sounds like over-engineering the problem.