Live data from Hacker News

Imperative vs. Declarative

latentflip.com

41–50 of 53 posts

Re: Imperative vs. Declarative

#41

I really like SQL. Sure, the language has warts but the ability to concisely represent WHAT you want, not HOW you want it, makes it very readable once you understand the simple constructs and how to properly design tables and indexes (not very hard). For example, consider the problem of finding the second largest value in a set. In SQL, I'd do something like: SELECT MAX( col ) FROM table WHERE col It's pretty readabl…

    maximum $ filter (
or like the Ruby one, but with better error semantics

    (`atMay` 1) . reverse . sort
since we don't know that there exists such a column.

Re: Imperative vs. Declarative

#42
post #6

Prolog is declarative programming take to the maximum (excluding things like Answer Set Programming/clingo etc). In Prolog you ask questions. For example: subset([1,2],[2]). then it goes away and says "yes". Or you want to know if any subsets exist: subset([1,2],B). B = [] B = [1] B = [2] This makes it really really nice for some surprising tasks (Windows NT used to ship with a prolog interpreter for setting up the n…

If you're familiar with or interested in Prolog, I would definitely recommend checking out Mercury. The language home page was just migrated and they're having broken link issues, but here's a link: http://www.mercurylang.org/ Also, you can check out the wikipedia page for a quick summary: http://en.wikipedia.org/wiki/Mercury_programming_language

The language has a lot of functionality that Prolog doesn't have and (thanks to a strong typing system) performs much better. It just needs a bigger community to support it.

Re: Imperative vs. Declarative

#43
post #36

Earlier quoted context omitted.

And, see, I would actually invert further. The declaration should be: elements = [1,2,3,4]; doubledElements = doubleElements(elements) Basically, if you see the words map, fold, reduce in your code, you are probably not as easy to understand as you'd like to think. Of course, in the cooking methaphor, I'm ok with mutating elements and just doing: elements = [1,2,3,4]; doubleElements(elements); This clearly has issues…

> And, see, I would actually invert further. The declaration should be: But then you lose pureness, right? The whole point of using high-order functions is allowing you to be as declarative as mathematics, so you can just operate functions together. Consider that in the first example, I only need to write the implementation for doubling a number n, while the `doubleElements` implementation is too specific, would thro…

Only in my example that relied on mutations. The first can all be implemented with pure functions just fine. Indeed, I was assuming it would be, hence the assignment to a new variable.

I suppose I should have said that the doubleElements implementation would likely be that map one liner. (Though, it needn't be. One could exploit custom knowledge of the domain there to do crazy crap like memoize the calls.)

That make sense?

Re: Imperative vs. Declarative

#44
post #12

I'm not sure I agree with some of the examples in the article. The examples used paint declarative programming as basically abstractions over details. The problem is that there is no line where an abstraction crosses the boundary into declarative programming. It's not really about abstractions but about control flow. If your code has a specific order it has to run in, then its imperative as you're still describing th…

so what would be declarative programming ? does it even exist? i mean, at some point you need to write some logic , and logic is imperative. Let's take a html file. It is declarative. but the underlying logic is written somewhere else. so you cant really have pure declarative programming? if it is possible how ?

Yes. Read up on Prolog.

Re: Imperative vs. Declarative

#45

I really like SQL. Sure, the language has warts but the ability to concisely represent WHAT you want, not HOW you want it, makes it very readable once you understand the simple constructs and how to properly design tables and indexes (not very hard). For example, consider the problem of finding the second largest value in a set. In SQL, I'd do something like: SELECT MAX( col ) FROM table WHERE col It's pretty readabl…

The important part is that abstracting the implementation from the declaration, the DBMS is free to compute this using whatever index, sorts and memory allocation is has too. So I think the way you do this in other languages doesn't even compare, because it's not really the same thing.

The effect is you end up with a declaration that is highly intelligible, exactly because you don't have to write the implementation.

Re: Imperative vs. Declarative

#46
post #43

Earlier quoted context omitted.

> And, see, I would actually invert further. The declaration should be: But then you lose pureness, right? The whole point of using high-order functions is allowing you to be as declarative as mathematics, so you can just operate functions together. Consider that in the first example, I only need to write the implementation for doubling a number n, while the `doubleElements` implementation is too specific, would thro…

Only in my example that relied on mutations. The first can all be implemented with pure functions just fine. Indeed, I was assuming it would be, hence the assignment to a new variable. I suppose I should have said that the doubleElements implementation would likely be that map one liner. (Though, it needn't be. One could exploit custom knowledge of the domain there to do crazy crap like memoize the calls.) That make…

> Only in my example that relied on mutations. The first can all be implemented with pure functions just fine. Indeed, I was assuming it would be, hence the assignment to a new variable.

Yes, the first example uses pure functions, but I guess you're confusing pure functions with HOFs [1]. The point is only having to write the implementation to double one number, and extrapolating it by composition. Consider that in your example, for instance, you would need a `doubleHash` function for hashes, and so on.

http://en.wikipedia.org/wiki/Higher-order_function

Re: Imperative vs. Declarative

#47
OP could definitely have used more examples, but I think he's on the right track. Where declarative or functional programming comes in really handy is composition. Underscore has a lot of utilities that make it easy.

  var genericFilter = function(type, value) {
    return function(items) {
      return _.filter(items, function(i) {
        return i[type] === value;
      });
    }
  };

  var sizeFilter = genericFilter('size', selectedSize);
  var brandFilter = genericFilter('brand', selectedBrand);

  var appliedFilters = _.compose(sizeFilter, brandFilter);

  var filteredItems = appliedFilters(items);
  // which ends up doing  sizeFilter(brandFilter(items));
// edit for sloppy code;

Re: Imperative vs. Declarative

#48

I really like SQL. Sure, the language has warts but the ability to concisely represent WHAT you want, not HOW you want it, makes it very readable once you understand the simple constructs and how to properly design tables and indexes (not very hard). For example, consider the problem of finding the second largest value in a set. In SQL, I'd do something like: SELECT MAX( col ) FROM table WHERE col It's pretty readabl…

The important part is that abstracting the implementation from the declaration, the DBMS is free to compute this using whatever index, sorts and memory allocation is has too. So I think the way you do this in other languages doesn't even compare, because it's not really the same thing. The effect is you end up with a declaration that is highly intelligible, exactly because you don't have to write the implementation.

> The important part is that abstracting the implementation from the declaration, the DBMS is free to compute this using whatever index, sorts and memory allocation is has too. So I think the way you do this in other languages doesn't even compare, because it's not really the same thing.

The ruby method-based form really is the same thing, because the semantics of teh result are constant across different enumerable objects (conventionally, of course, nothing about the language enforces this), but different enumerables may well implement the behavior differently under the hood -- including using internal indexes -- and may, in fact, apply the same type of adaptive techniques used by an SQL-based RDBMS (or, in extreme cases, actually defer all the work to an SQL-based RDBMS where the data presented with an enumerable interface in Ruby actually lives.)

This is less true, perhaps, of some of the other examples in that the implementation will be the same for all objects in the same system (but you still get some of the conceptual clarity advantages of declarative programming, even if the its not leveraged as effectively behind the scenes by the runtime adapting the actual methods used to the data it is working on.)

Re: Imperative vs. Declarative

#49
post #43

Earlier quoted context omitted.

Only in my example that relied on mutations. The first can all be implemented with pure functions just fine. Indeed, I was assuming it would be, hence the assignment to a new variable. I suppose I should have said that the doubleElements implementation would likely be that map one liner. (Though, it needn't be. One could exploit custom knowledge of the domain there to do crazy crap like memoize the calls.) That make…

> Only in my example that relied on mutations. The first can all be implemented with pure functions just fine. Indeed, I was assuming it would be, hence the assignment to a new variable. Yes, the first example uses pure functions, but I guess you're confusing pure functions with HOFs [1]. The point is only having to write the implementation to double one number, and extrapolating it by composition. Consider that in y…

I did not realize we were debating HOF versus pure functions.

That is, I'm fine with using both the pure and HO functions. I just think hiding the HOF ones behind a normal function call is usually a big win for readability.

So, to do the full example:

    elements = [1,2,3,4]
    doubledElements = doubleElements(elements)
    function doubleElements(e) {
        function double(n) { return n*2; }
        return e.map(double);
    }
Where I would assume the "reader" code would only have the first two lines. The rest would be behind the implementation layer. If the double function would be used elsewhere, no need to scope it to doubleElements.

Re: Imperative vs. Declarative

#50

Lately, when I code in C#, I write the code I wish was possible with the goal of trying to code to the problem as stated in the requirements. This way the code that solves the problem looks almost exactly like the description of the problem. That is step #1. Step #2 is doing whatever is necessary to make that code work. Sometimes this means using the more interesting stuff like reflection, dynamic objects, expression…

This is what I love about C#, it really provides all the necessary components to do this style of "wishful development". I've started doing this everywhere and the results are great. Like you said, the code itself literally reads like a specification. It's allowed me to turn what is otherwise would have been an extremely tedious web application into something I enjoy working on.

As an example, I turned what otherwise would have been an extremely tedious exercise in writing tons of obscure SQL (creating reports from a very non-standard database layout) into an API for creating reports that is literally like reading the specification for the report. And all of it was done in about 250 lines of C#. And to top it off we still have complete static type checking! I really cannot sing the praises of C# enough.

Post reply on HN