I enjoy PHP like I enjoy going home to see my family for the holidays. It's fun for a bit, the nostalgia makes me feel warm and fuzzy, and the familiarity of everything is very comforting. You quickly realize though that the grass really is a lot greener on the other side. You remember why you moved out of your parent's place and went out on your own.
It's hilarious looking at how cryptic these one-liners are, particularly when I consider that with languages like Ruby and Python you can do a LOT with a tiny little line if code.
As a side-note, one of my favorites is summing an array in Ruby:
These "one-liners" are cryptic because they are complex, it's a what can you do in the smallest form possible. It doesn't require code readability. Obviously you wouldn't use a 120 character dependency injector. That's just silly. But you can make one in 120 characters.
I disagree. I think they're simpler because they're built of smaller numbers of orthogonal concepts. I think code like this is certainly more dense, but I find the consequence of that density is that I spend less time pattern matching and skipping over "things that look like common idioms" and more time thinking about how there large, powerful abstractions wire together to achieve the intended end.
The GP's point is that Ruby doesn't require a built-in method that specifically sums an array to still get a clean, terse operation. You can use #inject to apply an arbitrary operation to (operator, last result, current element) and arrive at a result.
For example, given a list of numbers, you can generate a bitwise OR mask easily:
[1,2,3,4,5].inject(:|)
What this does is iterate over the list and apply ($last_result | $current_element) and return the result, which is passed on as $last_result to the next iteration. $last_result is 0 by default. This is equivalent to (as of PHP 5.4):
In case this was a serious entry... which I honestly can't tell.
The problem with array_sum is not that it's too long but instead that it's combined two rather specific bits of functionality into a fixed (if common) form, while the Ruby code separates the ideas of "folding" and "addition" allowing for many orthogonal creations.
To pick another favorite, in Haskell you could write
Foldable.foldl1 (+)
which sums any foldable thing—anything which has elements which can be combined together one-by-one. So it'll apply to Trees or Sets or Dictionaries (well, Maps) just as easily while also allowing things like (+) to be replaced by other binary operators.
It works (superficially) similarly to how Haskell does things and treats (+) as a partial function call by recognizing that + isn't getting at least 2 arguments. You could also do stuff like:
((+ 1) 2) ; => 3
(map (* 2) [1 2 3]) ; => [2 4 6]
If a function f takes any arguments and Pharen knows this, it'll convert (f) into a partial function call as well. Unfortunately I haven't figured out a way to check if a function has any side effects. Otherwise in this case at least operators are treated like functions.
It does track the arity of functions, but remember that this happens at compile time. Regular addition in Pharen is still just regular addition in PHP:
(def a (+ 1 2 3 4)) ; => $a = (1 + 2 + 3 + 4);
Of course, there are situations where partial application won't always happen because the compiler is unable to detect it:
(fn add (x y)
(+ x y))
(map #add [1 2 3])
Pharen won't be able to realize that `add` here is being partially applied inside `map`. It's not smart enough for that yet. If you try to run this you'll end up with 'Missing argument 2' and 'Undefined variable: y' all over the place.
However, I'm not putting a whole lot of emphasis on partials. They're there as a convenience, but they're not really a core part of the language.
But yes, back to the original point, all the tracking is done at compile time so that for addition with two or more arguments the resulting PHP will look like regular addition in PHP.
{-# OPTIONS -fglasgow-exts #-}
class BuildList a r | r-> a where
build' :: [a] -> a -> r
instance BuildList a [a] where
build' l x = reverse$ x:l
instance BuildList a r => BuildList a (a->r) where
build' l x y = build'(x:l) y
varargs x = build' [] x
main = print $ ( sum $ varargs 1 2 3 4 5 6 100)
$ ./Test
121
My hypothesis was that the compiler was tracking the arities of each function in order to open up opportunities for partial application. That means there's some ambiguity when you write something like (+ 1) which, in Scheme is a complete application equal to 1 but may also be interpreted as a partial application equal to (lambda (x) (+ 1 x)).
There are many ways to mitigate that ambiguity statically and dynamically, but I feel there's always going to be a tradeoff between favoring partial application, favoring variadic functions, and the complexity/sophistication of your static checking or runtime environment.
I just made a stab at where the solution might lie in that design space. Turns out I was wrong.
The array_reduce answers get closer to what I was looking for. This might be a "one line" answer, but it requires two special forms, assignment, sequencing operators (;), and two fresh variables.
Orthogonality and composability dramatically increase abstraction, code reuse, testability, and likelihood of writing correct code, both for library maintainers and library users.
That's not funny. Horrifying, maybe, but not funny.
Edit: Strike 'maybe'. I looked at it again and it's definitely horrifying. I saved it anyway, though; Halloween's only a few weeks off, and I think I shall print it out and stick it on the wall of my cube next to the PHP hammer and the "periodic" table of Perl 6 operators.
kudos. almost as cool as the cpp template hack to compute area based on part of the source code 'ascii art' size. (which I can't find anymore. googlefu--)
Yeah, but remember to pass the 0 to it; otherwise the sum of an empty array would be nil:
x.inject(0, &:+)
That's one of the disadvantages of not having a powerful type system to infer what's the "zero" of some type.
Still, the Ruby code is pretty readable and a good example of orthogonal concepts that compose well. E.g., getting the product of the numbers instead: x.inject(1, &:*). Or the least common multiple: x.inject(&:lcm).
It's a good fix and no bad thing to point out, and I'm not just saying that because I was about to point out the same thing before I noticed you'd beat me to it.
people have been creating 140 character music pieces in the supercollider music language for a while. its very tricky to make something that lasts and evolves and has structure and keeps your interest.
"this tweet is also totally deterministic and without any randomness. here a lot of nested square wave oscillators creates the complexity. basically there are 4 channels/voices mixed down to one and then duplicated in left and right channel. there are three levels deep nesting of frequency modulation with another set of square waves mixed and added."
Yeah I remember those ! In fact I did some bit shift melody stuff myself in supercollider based on those and some other code.
One of the sc people released an iPhone app that let's you write bitshift based melodies.
The early stuff that supercolliders creator James McCartney did really set the style for short, mathematically elegant music. It's really a great language for it. You can do operations on arrays, and do interesting multichannel expansion.
At the risk of arousing some people's ire, I really like these tidbits that try to squeeze maximum functionality (albeit a bit dangerous) into a minimum span of characters. It feels a bit like the underhanded C contest in a way since there are so many magnificent ways to self-destruct doing this, but at the same time it's a fun challenge.
Here's a fun(!) presentation of Rebmu given by Dr. Rebmuthalamonious Golfstanipetrovitch (!!) given at the recent Rebol/Red conference - http://www.youtube.com/watch?v=iDKaz1iB9wQ
About ID obfuscation: i like to use a small-width block cipher (e.g. 32-bit skipjack). A reversible int->int transform means you don't need an extra DB column, you're never prone to CRC32 collisions, you can still use base36 (why not case-sensitive base62?) for URLs, and with an application secret key there's no chance of reversal.
Well, maybe someone could aim to get many sequential keys and then reverse-engineer the state of the cipher, but that's also possible with your method.
Wow, Perl's seen better days but I think they're a good match for each other. Perl's fascinated by JavaScript's objectivity and popularity, and JavaScript's wearing Perl for retro effect like some kind of fashion item. The two of them are like darkness and light. No prize for guessing who brought the drugs...
I'm really conflicted on what opinion to have of this. On the one hand, these PHP constructs are even worse than most of what you see in that language, but on the other hand, constraining PHP sources to a maximum length of 140 characters should help reduce the scope of the contagion.
It's hilarious looking at how cryptic these one-liners are, particularly when I consider that with languages like Ruby and Python you can do a LOT with a tiny little line if code.
As a side-note, one of my favorites is summing an array in Ruby: