HNHacker News
TopNewBestAskShowJobs

pyrtsa

93 karma · joined September 23, 2009

Pyry Jahkola

My thoughts: http://pyrtsa.posterous.com

My tweets: http://twitter.com/pyrtsa

I write software for http://futurice.com in Helsinki, Finland, and study Engineering Physics and Computational Science at http://aalto.fi.

submissionscomments
pyrtsa··on Transducers are coming to Clojure
Nope, that's the funny feature of transducers. Like lenses in Haskell, transducers compose in reversed order.

    (sequence (comp (map inc) (filter even?)) (range 10))
    ;;=> (2 4 6 8 10)
    (->> (range 10) (map inc) (filter even?))
    ;;=> (2 4 6 8 10)
Both test functions in transduce-bench return 250000500000.
pyrtsa··on Bjarne Stroustrup – The Essence of C++ [video]
But you'll need to document it very visibly that "Thou shalt call resource.close() whatever happened."

C++ makes it possible for the library writer to take care of freeing the resources automatically.

pyrtsa··on Bjarne Stroustrup – The Essence of C++ [video]
Nitpick:

    if (x < 100) throw new Exception("Weird!); // LEAK!
You shouldn't use `new` either when throwing exceptions. Just:

    if (x < 100) throw Exception("Weird!); // no leak.
pyrtsa··on Bjarne Stroustrup – The Essence of C++ [video]
Bjarne's advice also applies to pointers wrapped as class members. There are just too many ways you can mess things up inside the class when dealing with raw pointers, examples including:

- partial construction: having to deal with already allocated pointers in case of errors during the construction - copy construction: who owns the resources? (Alternatively, you'll need to remember to disable the copy constructor explicitly.) - copy assignment: likewise

Doing the Right Thing is just so much easier when you wrap those member objects into e.g. `std::unique_ptr<T>`. That'll disable copy construction and assignment, which means that you'll need to think of that separately if it's needed.

pyrtsa··on Scroll This
> This is neat, but really disappointing that there is no feedback when…

Here's how you can say the same in a more positive manner:

> This is neat, and it would be even better if there was feedback when…

To keep up the hacker spirit, I find it amusing that the words "but" and "and" are logically equivalent (i.e. they both are representations of the logical ∧ operator), just with different connotations. :)

(Edit: It's actually a social hack to say your negatively toned "but" phrase with a positive "and" instead.)

pyrtsa··on Callbacks are imperative, promises are functional
I asked the same question in Twitter. Turns out James was actually augmenting (i.e. modifying) the array object `promises` to behave as a promise itself. I don't think this was a particularly beautiful way of doing it but it seems to work now that I think of it.

Promise libraries, like RSVP.js [1] he referred to, typically implement a way to construct a promise with a depends-on-many relationship, as a function possibly called `all([p1, p2, ...])` (with the same type signature as for `list`), `and(p1, p2, ...)` or something similar.

IMO, defining the `list` function that way would've been clearer to the reader and more FP'ish, treating the `promises` argument in as a value and not a mutable object.

[1]: https://github.com/tildeio/rsvp.js/blob/master/lib/rsvp/all....

pyrtsa··on A nice, little known C feature: Static array indices in parameter declarations
Correct. The key difference is that the enable_if version can be overloaded with mutually exclusive requirements:

    template <size_t N>
    typename enable_if<(1 < N && N < 10), void>::type
    foo(int (&bar)[N])
    {
        // called when 1 < N && N < 10
    }

    template <size_t N>
    typename enable_if<(N >= 10), void>::type
    foo(int (&bar)[N])
    {
        // called when N >= 10
    }
OTOH, the key advantage in static_assert is the meaningful error message.
pyrtsa··on A nice, little known C feature: Static array indices in parameter declarations
And, by extending your second example, we can enforce the minimum array size with std::enable_if (C++11; boost::enable_if_c with C++03):

    template <size_t N>
    typename enable_if<(N >= 10), void>::type
    foo(int (&bar)[N]) { ... }
EDIT: Changed condition from N >= 0 into a more meaningful one. X-)
pyrtsa··on Clojure 1.5.0 RC 1 released
In my view it's exactly the opposite:

    (-> (california) bay-in city-on) ; "The Californian bay's city"
vs.

    (city-on (bay-in (california))) ; "The city on the bay in California"
The former ("->") starts with what's fed into the pipeline, the latter starts with what you get out of it. In addition, "->" avoids the nesting of expressions regardless of the number of steps, which might be useful in some cases. But both styles have their place.
pyrtsa··on Aligning your Git logs
It might have been those UTF-8 ellipses: "…"

Good to hear that you got it resolved, but are you sure that your character encoding settings are alright?

pyrtsa··on Aligning your Git logs
Oh, good to hear. It's how Posterous implements the embedding of Github Gists that probably is to blame here.

I'm still thinking whether to switch my blog to another platform, maybe even an own server, as that's not the only problem I've had trying to embed source code examples to my posts.

Much of it boils down to the use of the Tiny MCE editor, that I'm a bit surprised Posterous is enforcing everybody to use!

pyrtsa··on Elements of Modern C++ Style
I think the lambdas are the more useful the more complicated the function is. Simple asynchronous tasks might be one such example. This one, however, still is a pretty common use case, so introducing a function object type for it wouldn't hurt readability. Something like:

    template <typename A, typename B>
    struct between_ {
        A a; B b;
        between_(A const & a, B const & b) : a(a), b(b) {}
        template <typename T>
        bool operator()(T const & t) const { return a < t && t < b; }
    };
    template <typename A, typename B>
    between_<A, B> between(A const & a, B const & b) {
        return between_<A, B>(a, b);
    }
    // ...
    auto i = find_if(begin(v), end(v), between(x, y));
Verbose? Admittedly. Except maybe for the point of use, i.e. the last line. Which, I think, helps a lot anyway.
pyrtsa··on Elements of Modern C++ Style
I don't think introducing more syntax to the language for a feature that ultimately is a library solution, is a sustainable way to go.

But if you really need a compact notation for smart pointers, you'll get pretty close by using template aliases, e.g.

    template <typename T> using up = std::unique_ptr<T>;
    template <typename T> using sp = std::shared_ptr<T>;
    // ...
    up<int> foo(sp<int> bar) {
        return bar ? up<int>(new int(*bar)) : nullptr;
    }
pyrtsa··on Apple acquired mind-blowing 3D mapping company C3 Technologies
Interesting. Previously, the same company has been behind the 3D view of Nokia's map service http://maps.nokia.com/3D/ — more info e.g. here http://www.ubergizmo.com/2011/04/c3-technologies-behind-noki...
pyrtsa··on IOS 4 vs. 5, Pixel by Pixel (jp)
Oh true, missed that. Finally pulled out the phone to realize this. And then the other option 16+20+20+20+16 / 32+40+40+40+32 already has too big a difference between the margins on the edges compared to the ones between the icons. Makes perfect sense now.
pyrtsa··on IOS 4 vs. 5, Pixel by Pixel (jp)
It's not impossible to make it symmetric for both, though. With consistent spacings. E.g.

    19+18+18+18+19 (iPhone 3GS)
    38+36+36+36+38 (iPhone 4)
pyrtsa··on Gerald Sussman: "We Really Don't Know How To Compute"
Anybody noticed how closely this, being from the programmer's point of view, is related to what Bret Victor [1] has been talking about from the UI perspective? Take http://worrydream.com/#!/ScrubbingCalculator, or any of the "Kill Math" or "Explorable Xplanations" articles, for an example.

Combining a good UI to the propagators as explained by Sussman in this video, would make a disruptive product on any field where decision making is needed. (Not like such tools didn't exist already in the hands of some, of course.)

[edit] fix typo

pyrtsa··on Show HN: Create a beautiful timeline with TimeKiwi
Hmm, I think the months menu [1] that opens when you take the mouse to the bottom right corner should have months listed in the opposite order. It feels more logical to get the most recent months down, closest to the mouse cursor, and the least recent furthest up.

[1]: http://timekiwi.com/timeline.html#posterous=garry.posterous....

Edit: Ok, it might not feel that natural anymore with the scrolling behavior, since the timeline itself has time pointing upwards. How about moving the menu to the top?

pyrtsa··on Show HN: Final Touch
Also, the Updates link on the bottom of the home page is broken, points to /update.php, not /updates.php like it should. ;)
pyrtsa··on Fastest sort of fixed length 6 int array
Seven years ago, maybe. But today's GPUs do it easily in their programmable pipeline (shaders).

And where conditionals are costly, you can use tricks like:

    float temp = min(x, y);
    x = max(x, y);
    y = temp;
instead of the conditional swapping operations, to make the whole network sorting algorithm deterministic. (Edit: notice that min() and max() here are hardware operations.)
pyrtsa··on Q: Why can I access an out-of-scope C++ var? A: So you rent a hotel room...
Yeah, the hotel room analogy breaks as soon as you realize that visiting some completely other hotel room will already overwrite that variable in the first one.

But it was a fun story, though.

pyrtsa··on Lytro Lightfield Gallery
Reminds me of that multi-lens camera Adobe was playing with some years ago.

http://visualnary.com/2008/04/13/lens-that-takes-multiple-pi... http://visualnary.com/2008/04/13/nab-predictions.html

pyrtsa··on Nokia Plan B
It was originally many things, but before going into the rubber goods business it started out as a paper mill. http://www.nokia.com/about-nokia/company/story-of-nokia/noki...
pyrtsa··on No, really, pi is wrong: The Tau Manifesto (Tau Day, 2010)
I actually disagree with that logic as well. If you just knew that e^(i * pi) = -1, then how would you know, whether halving that exponent would yield +i or -i?

Considering that, we'd need to state Euler's identity as: e^(i * pi/2) = i, but again we'd know nothing about fractions of that exponent. And there we go!

The point is, Euler's identity is a nice property of the definition of complex numbers, but in itself, not too generic. That's why OP's form, e^(i*tau) = 1, would do just fine.

Edit: fixed asterisks.

pyrtsa··on No, really, pi is wrong: The Tau Manifesto (Tau Day, 2010)
Only there is no year zero, by (that) definition. http://en.wikipedia.org/wiki/0_(year)