Live data from Hacker News

In Lisp, should lists be replaced with trees?

hxa.name

31–40 of 43 posts

Re: In Lisp, should lists be replaced with trees?

#31
By "replacing" lists with trees, am I supposed to understand that working with trees will be natural and easy, and lists will feel like second-class citizens? I thought we were beyond thinking like that. Building languages around a favorite data structure was never the right thing to do; it was always tunnel vision and bad design. Different data structures have different features and different performance characteristics. There's no reason for a language designer to pick a favorite data structure and force anyone who has to use a different one to deal with warts and second-class library and language support.

Re: In Lisp, should lists be replaced with trees?

#32
post #30
post #29

Earlier quoted context omitted.

I think the answer is we should have it, but it's just a library.

OK. Then I suppose the question is: why should it be library not built-in? The main thing not addressed in the article is: what are the language implementation implications? What are the pros and cons there?

In my way of thinking, the distinction between "library" and "built-in" is very fluid. That is, if you run an executable which automatically loads a library for you, then voila it is now built-in. If nothing else, you can set up your own local environment that you favor. I realize this has portability implications, but keep in mind that not everyone will want "bignums" or "socket operations" or "openssl" available all the time in every program.

For me, the language implications are nil. I would not change a single thing in Fexl to support name-value "trees" versus lists. It's all programmable using the system as it is. The S, C, Y, I, L, R combinators are what they are, forever and ever, world without end. :) And I'm quite sure the same thing is true of Lisp (i.e. just use defun or maybe defmacro). You'll notice that even in the original article the author didn't propose any new syntax. It's all just more functions.

I mean, even in Perl for goodness sake all you have to do is this:

    # A map is a list of branches.  Each branch is pair(key,data).  The data is
    # pair(val,map).  No two keys in a map have any prefix in common.  A key cannot
    # be null.  If you put a null val at a key, it deletes that key from the map.

    sub map_put
        {
        my $map = shift;
        my $key = shift;
        my $val = shift;

        die if !defined $key || ref($key) ne "" || $key eq "";
        die if !defined $val;

        if (is_atom($map))
            {
            return $map if is_null($val);
            return pair(pair(atom($key),pair($val,null())), $map);
            }

        my $branch = left($map);
        my $old_key = name(left($branch));

        my $cmp = $key cmp $old_key;

        if ($cmp == 0)
            {
            my $sub_map = right(right($branch));

            if (is_null($val))
                {
                return right($map) if is_atom($sub_map);

                if (is_atom(right($sub_map)))
                    {
                    # Combine singleton map upstairs.

                    my $top_key = name(left($branch));
                    my $next_key = name(left(left($sub_map)));

                    my $new_branch = pair(atom($top_key.$next_key),
                        right(left($sub_map)));
                    return pair($new_branch,right($map));
                    }
                }

            my $new_branch = pair(left($branch), pair($val,$sub_map));
            return pair($new_branch,right($map));
            }

        if (substr($key,0,1) eq substr($old_key,0,1))
            {
            my $len_common = len_common_prefix($key,$old_key);

            my $key_suffix = substr($key,$len_common);
            my $old_key_suffix = substr($old_key,$len_common);
            my $common_prefix = substr($key,0,$len_common);

            if ($key_suffix eq "")
                {
                return $map if is_null($val);

                my $sub_map =
                    pair(pair(atom($old_key_suffix),right($branch)),null());
                my $new_branch = pair(atom($common_prefix),pair($val,$sub_map));
                return pair($new_branch,right($map));
                }

            if ($old_key_suffix eq "")
                {
                my $old_sub_map = right(right($branch));
                my $new_sub_map = map_put($old_sub_map,$key_suffix,$val);
                my $old_val_atom = left(right($branch));

                if (name($old_val_atom) eq "")
                    {
                    return right($map) if is_atom($new_sub_map);

                    if (is_atom(right($new_sub_map)))
                        {
                        # Combine singleton map upstairs.
                        # TODO hey wait!  This is the same code as above.  Unify this.

                        my $top_key = name(left($branch));
                        my $next_key = name(left(left($new_sub_map)));

                        my $new_branch = pair(atom($top_key.$next_key),
                            right(left($new_sub_map)));
                        return pair($new_branch,right($map));
                        }
                    }

                my $new_branch = pair(left($branch),
                    pair($old_val_atom,$new_sub_map));
                return pair($new_branch,right($map));
                }

            return $map if is_null($val);

            my $old_branch = pair(atom($old_key_suffix),right($branch));
            my $sub_map = map_put(pair($old_branch,null()),$key_suffix,$val);

            my $new_branch = pair(atom($common_prefix),pair(null(),$sub_map));
            return pair($new_branch,right($map));
            }

        if ($cmp 
That would be a lot cleaner in Fexl or Lisp, but it's totally do-able in any language.

Re: In Lisp, should lists be replaced with trees?

#33

"Branchs/trees are a superset of pairs/lists" No, they aren't. A tree is acyclic by definition. Cons cells allow circular structures.

The structure he calls a 'tree' allows cycles and is a generalization of a list. Whether he uses the correct word isn't really interesting: it doesn't detract anything from the post.

Re: In Lisp, should lists be replaced with trees?

#34
post #23

A list structure is already a 'dictionary tree', except it has lousy performance in access. (only really visible on large data sets). * (second (assoc 5 '((1 2) (3 4) (5 6)))) > 6 The lousy performance doesn't matter, most of the time, because you have other data-structures for data, and your compiler generally is only interested in sequential access (constructing a parse tree out of it). The lisp code already being…

Exactly. Rose by any name smells just as good.

Re: In Lisp, should lists be replaced with trees?

#35
post #3

not directly lisp related, but the team working on Fortress has some interesting work on using "conc lists" (pairs, and trees as a combination of pairs) as a basic unit of work for parallel processing[1], the analysis quite naturally considers its relation with lisp ad cons lists in other languages. [1] http://labs.oracle.com/projects/plrg/Publications/ICFPAugust...

I think that's directly related. The answer to the question "Why should we replace our lists?" is that you can avoid known failure cases with lists at a relatively small price in complexity and memory in the worst case, and sometimes get big gains. Singly-linked lists are not suitable for a concurrent world and functional programming really needs to stop putting lists on a pedestal and writing them into their very syntax. There's actually other problems they cause, too, but the concurrent problem is a real killer, because you can not just program your way around it, you need a fundamentally different data structure.

Re: In Lisp, should lists be replaced with trees?

#37
post #3

not directly lisp related, but the team working on Fortress has some interesting work on using "conc lists" (pairs, and trees as a combination of pairs) as a basic unit of work for parallel processing[1], the analysis quite naturally considers its relation with lisp ad cons lists in other languages. [1] http://labs.oracle.com/projects/plrg/Publications/ICFPAugust...

http://vimeo.com/6624203 Conc lists as video. Titled Organizing Functional Code for Parallel Execution; or, foldl and foldr Considered Slightly Harmful (Guy Steele)

Re: In Lisp, should lists be replaced with trees?

#38
post #13

Earlier quoted context omitted.

To take a familiar example, the Web is not a tree. While you might argue that each page has unique children (outlinks), there is no unique parent -- a page can have an arbitrarily large number of incoming links, and the page can link back to those pages in turn, producing cyclic structures of immense complexity. For some interesting discussion on the limits of tree structures with respect to urban planning see A City…

All good, just a nitpick: You don't need a unique parent to have a tree. You don't even need directed edges. :) The purest definition of a tree graph is "a graph with no cycles".

We use different definitions. My trees are acyclic connected graphs with one root.

Re: In Lisp, should lists be replaced with trees?

#39
I wouldn't say lists should be replaced with trees, but adding a rich set of tree-based data structures to Lisp improves it substantially, in my view. To see what I mean, have a look at my FSet functional collections package, which does exactly that:

  http://common-lisp.net/project/fset/
Unlike what the OP is suggesting, FSet doesn't expose the internal structure of its trees. Instead it wraps them in a rich set-theoretic interface.

Re: In Lisp, should lists be replaced with trees?

#40

Lists are trees.

Wait, I thought trees are lists.

No, trees are multidimensional lists. Lists are one-dimensional lists, which are degenerate trees and a simple primitive for the more general (always a loaded term) structure.
Post reply on HN