42 comments

[ 5.3 ms ] story [ 132 ms ] thread
Hi everyone, I'm the creator of Pharen. Feel free to ask me questions or remind me why this is a terrible idea. :)

Yes there are a lot of issues with cross-language compilers. That said, Coffeescript: http://coffeescript.org, which compiles its own language to Javascript has had a lot of success and is being used in production. So it's at least possible to use languages like this.

The extra layer of abstraction is a big hurdle. When debugging you have to find the source of the problem in the PHP, though ideally after that you can just find the matching Pharen code and go from there. One of the things on my todo list is to have at least a rough line-to-line tracker built, so that it could at least tell you the general location a problem happened, if not the exact line.

Translating docs and example code for existing libraries into Pharen is a bigger issue, I think. Mainly because Pharen emphasizes a functional style of coding while most PHP code assumes you are doing things imperatively. This is something Clojure has to deal with in terms of Java interop so again it shouldn't be too hard to get around.

In terms of efficiency there is tail recursion optimization (converts a recursive function to having a while loop at the end) and a persistent sequence library in the works that would make functional looping through a list about as fast as imperative iteration. More aggressive optimizations might come in the future.

If you're interested, feel free to contribute: http://scriptor.github.com/pharen/contribute.html. If you use IRC you can come hang out (or berate me personally) on #pharen on Freenode. Any suggestions or ideas are welcome.

What is it for?
Originally, for fun!

It gives you a chance to use Lisp's syntax and mentality if you're stuck with PHP on the backend. Moreover, you have features like macros and lexical scope, which can be useful.

Fun is good.

I just wondered if it had been built for a specific project and if so what problems it was trying to solve.

It's funny - I've spent the past few years thinking about high-level languages that would compile down to lisp. Recently I've seen a number that go the other way.

Is this is a problem you face personally?
Does this only work on the newest version of PHP? Compilation of closures, I presume, requires that PHP support closures, right?
Nope, it should work for PHP 5.2 as well. Closures are implemented using a static member on a class that handles all the lexically scoped variables, not PHP 5.3's native closures.
ok, that is killer. awesome work!
This makes me curious, why reimplement features that would've been built-in in PHP 5.3? After all, 5.3 is now available in most major platforms including a Ubuntu LTS release and the latest RHEL.

Other than that, Pharen looks very interesting. A minor detail is that I didn't yet figure out how to call static methods of external PHP classes.

I was curious to know the same thing. I do however like the code being side by side. It helps people who know PHP learn a little Lisp.
I guess I wasn't exactly sure just how widespread PHP 5.3 was and wanted to play it safe. Also, even if new servers nowadays come with 5.3, a lot of existing code is still running on 5.2.
Then again, you could argue that people interested in such projects like Pharen are likely to have modern PHP versions ;-)
> When debugging you have to find the source of the problem in the PHP, though ideally after that you can just find the matching Pharen code and go from there.

You could always just add the S-Expression that became the php code as a comment. From there it should be trivial to find it in the Pharen code.

This is really cool and for the most part the syntax seems to make sense.

One thing I don't understand is why there is special unnatural-looking syntax for dictionaries. It is inconsistent that comma=whitespace everywhere else. Perhaps something like:

(array "a"=>1 "b"=>2)

Note that this currently compiles to array("a", =>1, "b", =>2)

The current dictionary syntax is actually typical for lisps, particularly this is exactly what Clojure does. It's just a series of elements except in this case it's designed to look at every two elements as a pair.

What do you mean by it's inconsistent? Commas are the same both in dictionaries and anywhere else, they're completely optional.

I take that back. I had no idea that {"a" 1 "b" 2} works when I made that comment.
Is the intended user a Lisp programmer forced to work on a php code base...or a Lisp programmer looking to take advantage of some of php's native server scripting features?
HAH!

I think, strictly, the former.

(I actually laughed out loud at this :_)

Fair enough. I've never programmed in lisp. I just assumed that lisp didn't have native server abstractions like $_REQUEST - and that Pharen may expose those.
While no or few lisps have that sort of thing baked in natively, they mostly have libraries that expose it, which is arguably better in any case.
Both really, since interop with PHP is pretty easy so you can use those native features in a lispy way.
Do you believe there are or will be good reasons to choose Pharen over Scheme, Common Lisp or Clojure in a situation where one isn't forced in to using a PHP backend? With Clojure, for example, I consider the baked-in concurrency models and data structures very valuable, but haven't had much cause to care that it runs on the JVM.
That's a really good question. The main case I can see is if someone is already familiar with PHP and its deployment and doesn't want to learn another language/platform. It might also be useable for basic scripting tasks (the compiler has an --executable flag that adds a PHP hashbang to the top of a script).

Other than that Pharen is still pretty new and nowhere near the same level as mature lisps. Making debugging and interop with 3rd party libraries easier are the main long-term goals, so maybe after that it'll be at least a little viable.

This actually doesn't suck. I was expecting something much much worse, but I was pleasantly surprised. If the author just focuses on a few primitives and how to make them as efficient as possible (i.e. closure efficiency, tail-calls, macros, efficient list representation, etc), if he just gets those right, others can always use it as a target and develop more comfortable lisp substrates on top of it.

Cheers!

Thanks Mahmud :)

Efficient sequences are what I'm working on right now, particularly trying to make persistent versions of the major data structures in PHP.

Tail calls are another thing, though with PHP 5.3's gotos they could be done (who'd have thought that feature would ever be useful?) Could you elaborate on how I could improve efficiency for macros?

Macros don't need to be efficient, only accurate :-) Don't sweat hygiene too much, just implement GENSYM and you should be fine.
Hey Scriptor, neat project!

What are the major differences between Pharen and Lisphp?

(covered here:)

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

The big one is that Lisphp is an interpreter while Pharen is a compiler. Lisphp takes source code and just runs it, which means that it's lisp code running on Lisphp, which in turn is running on the PHP interpreter.

Pharen generates regular PHP source files that you can then throw wherever PHP works.

How do they compare performance wise? I've tried some 'toy' lisp programs in Lisphp and was pretty disappointed at the speed, does Pharen fare better in this respect?
I haven't done any real benchmarks, but theoretically Pharen would have at least the same order of magnitude performance as regular PHP. The main things slowing it down is the memory overhead needed for using lexical scope.
Don't forget to run it through HipHop to compile the PHP down to C++. :)
Is this modeled after any particular Lisp? It looks a little bit like Clojure.
I'd say it's closer to Clojure than others lisps, but there are still some differences. For example, no keywords (:foo, :bar, etc.) and lists are not functions of their members. This can get a little confusing with Pharen's array access syntax:

    (:some-list 1)
Here, some-list is just a variable while the : prefix tells Pharen that you are trying to index into it.
From reading the examples this looks awesome, I'll give it a try tomorrow at the office. Is there a way to expand macros only and not do the compile-to-php step?

My current project involves generating php from a declarative definition and this could be just the right tool for the job! Maybe it will make switching to common lisp a lot easier once I learned enough of it :D

>Is there a way to expand macros only and not do the compile-to-php step?

So that it would just generate the Pharen code resulting from the expansion? Unfortunately, not yet. As soon as a macro is done executing it returns the node tree itself, which is then compiled. There might be a way to hack macro-expand in though.

Let me know how trying to work it into your project goes! I'll be glad to help with any problems that come up.

Perhaps the title should reflect that is a translator from Lisp code to php code.
(comment deleted)
I pretty much like the partial such as (map (* 2) [1 2 3]). Do you plan on adding something like (map (/ _ 2) [1 2 3]) like Arc or a #(.. % ..) clojure equivalent?
Possibly, it might have a use in some web framework ideas I have (such as designate a series of actions to perform on something like input data).