Arc Forumnew | comments | leaders | submit | raymyers's commentslogin
1 point by raymyers 6329 days ago | link | parent | on: Bug in pushing with nested lists?

Right. Of course, backtick'd lists with at least one comma are still born anew each time; i.e. `((,a)) is safe.

-----

2 points by raymyers 6329 days ago | link | parent | on: Local variables

If you are using so many local variables that it is becoming a problem, you might need to reorganize. However, I would suggest declaring them all at the beginning and only losing one indentation level.

    arc> (with (a 1 b nil) (= b a) b)
    1
    arc> b
    Error: "reference to undefined identifier: _b"

-----

2 points by kennytilton 6329 days ago | link

you might need to reorganize

Amen. Try to think more functionally. "On Lisp" is available on-line, see chapter 3. The funny thing is that one can achieve good functional style by making one's code look a certain way.

-----

10 points by raymyers 6329 days ago | link | parent | on: The Factor Language

I have this friend, really sharp guy.

When we were sophmores he was learning Lisp, which was greek to me. ("What the heck is a lambda?!") Two years later, Lisp was my favorite language.

By then, he was learning Haskell, which I could barely stand to look at. ("What the heck is a comprehension?!") Today, I love Haskell too.

Why am I telling you all this? Because that guy is into Factor now, though it's still total gibberish to me.

-----

1 point by raymyers 6329 days ago | link | parent | on: More generic if macro

True, though that only works for function calls -- not variables: (if (no li) ...)

-----

2 points by raymyers 6330 days ago | link | parent | on: Favicon?

Nice icon. Mind if I swipe it?

-----

4 points by raymyers 6330 days ago | link | parent | on: Anarki Conventions

That's a great requirement, but it might easier to obey if there was a test suite.

-----

4 points by nex3 6329 days ago | link

Please, feel free to make one (or rather, contribute... offby1 has the beginnings there already).

-----

3 points by raymyers 6330 days ago | link | parent | on: lazy lists in arc

If these had good performance and were interchangable with the native lists of the language, this would be really cool. Sadly, I don't think lazy lists as a library can approach the usefulness of lazy lists as a language feature.

There have been some pretty good library attempts over the years though, like CL Heresy.

-----

4 points by raymyers 6332 days ago | link | parent | on: Another, older wannabe neo-Lisp

I also enjoy currying and "pointfree" style. However, wouldn't it require giving up functions that take an arbitrary number of arguments? (In fact Scala has both, but it required introducing a special syntax.)

I find that Arc's shortcut closure [] notation is a surprisingly good curry-substitute. For example:

    (map (act w) locs-to-check) ; currying
    (map [act w _] locs-to-check) ; only one token longer

-----

2 points by cooldude127 6331 days ago | link

there's something to that. i didn't really think about it, but that might just be fine. that's actually exactly what scala's explicit partial application looks like, with the underscore.

i honestly haven't been doing a whole lot of practical arc programming. CL and Slime have spoiled me to the point where I find it difficult to use a language that doesn't have that convenience

-----

7 points by raymyers 6333 days ago | link | parent | on: Binary Search Trees in Arc

Ask and ye shall receive. http://ray.codezen.org/wiki/doku.php?id=binary-search-tree

-----

4 points by lojic 6333 days ago | link

Very nice - thanks!

  Haskel:
  36 total lines; 1,167 chars
  Arc:
  53 total lines; 1,215 chars
I don't know the formula for a "code tree".

-----

4 points by gregwebs 6333 days ago | link

This doesn't tell the whole story. The haskell version is doing some balancing. For an AVL tree with rotations implemented through pattern matching see here. http://www.nabble.com/Re%3A-Why-functional-programming-matte...

The line deriving(Eq,Show) means that you can now do this:

  Prelude BST> Tree 'a' Empty Empty
  Tree 'a' Empty Empty
  Prelude BST> let a = Tree 'a' Empty Empty
  Prelude BST> a
  Tree 'a' Empty Empty
  Prelude BST> let b = Tree 'b' Empty Empty
  Prelude BST> b
  Tree 'b' Empty Empty
  Prelude BST> a == b
  False
  Prelude BST> let c = Tree 'c' a b
  Prelude BST> let d = Tree 'c' a b
  Prelude BST> c == d
  True
All this is guaranteed at compile time. Moreover, the haskell version is much more readable. The use of modules removes unnecessary function prefixing, and there is no doubt about what the arguments to functions are when they are pattern matched.

Curiously, though, the arc version actually has less tokens by my measurement

  ruby -e 'p File.read(ARGV[0]).split(/\s|\.|!/).reject{|s| s==""}.map{|tok| tok.gsub(/\(|\)/,"")}.flatten.uniq.size'

  bst.arc 205
  bst.hs  253
but here is the interesting thing- now lets count just the unique tokens

  bst.arc 41
  bst.hs   47
This is in part due to haskell's pattern matching semantics where the same function definition is repeated multiple times, and the '|' character is repeatedly used. Also, there are more functions in the arc version, and in both pieces of code, variable names are usually one character and function names have multiple characters.

-----

2 points by rkts 6333 days ago | link

> The haskell version is doing some balancing.

Balancing that causes remove to be O(n). Probably not a good idea.

-----

2 points by raymyers 6333 days ago | link

A more balanced tree will speed up 'find' and 'insert'. If those actions are performed far more often than 'remove', it would indeed be a good idea. Without knowing the use case, I cannot say which I would prefer.

-----

3 points by pg 6333 days ago | link

It's fairly easy to do by hand. Just count the number of tokens-- in the sense of things whose first character a parser would not treat as merely another character in the name it was previously reading-- that are not closing delimiters of a pair.

-----

2 points by vrk 6333 days ago | link

If by that you mean counting the nodes, you need to parse the source first. You can either do it by hand (if you know the grammar) or tweak the compiler/interpreter, if it doesn't have any statistics option.

-----

4 points by lojic 6333 days ago | link

Is there a bug in bstMin ? Shouldn't it reference bstMin on the rhs?

-----

2 points by raymyers 6333 days ago | link

Fixed. Thanks!

-----

1 point by pg 6333 days ago | link

It's missing bst-trav. (The functions that are supposed to be part of the external interface are the ones that begin bst-...)

Also, is numerical < hard-wired as the comparison function?

-----

2 points by gregwebs 6333 days ago | link

no need for bst-trav since there is an elements function. You can just map over the elements.

in the data declaration 'a' is a generic type, but Haskell will infer that the type must be an instance or class Ord (i.e. implement <,<=,>=,>,max,min,==). (If the type is not an instance of Ord it will tell you so at compile time)

-----

2 points by pg 6332 days ago | link

no need for bst-trav since there is an elements function. You can just map over the elements

Mapping over elements is not the same if you're looking for the 4th element of a huge tree; which is probably what you have if you're using a bst.

-----

7 points by raymyers 6332 days ago | link

Actually yes, in Haskell it is the same. Lazy evaluation means you could take the 4th element of a map over an infinite list. For example: "map (*2) [1..] !! 4"

-----

2 points by rkts 6333 days ago | link

I would argue that relying on overloaded comparison functions is a bad idea. Not all things have a 'natural ordering,' and even for those that do you might want to override it at some point.

-----

2 points by raymyers 6332 days ago | link

I think reasonable people can differ on this. Passing comparators as arguments is an approach more typical of dynamically-typed languages (e.g. CL and Scheme 'sort'). In a statically-typed language, it is more common to use a comparison operator that specializes on type (e.g. Haskell Prelude 'sort'). If a set of objects don't have a 'natural ordering', they might not belong in a Binary Search Tree in the first place.

-----

3 points by pg 6332 days ago | link

What do you do if you want to maintain a list of strings sorted according to their length?

-----

4 points by raymyers 6332 days ago | link

If I wanted to keep using the Ord type-class for comparison, I might use a container type, like this:

    data Elem = Elem String deriving (Show, Eq)
    instance Ord Elem where
        Elem x < Elem y = length x < length y
    
    tree1 = insert (Elem "Some string") Empty
    tree2 = remove (Elem "Some string") tree1
If I really wanted to pass in the comparison function, I would have to change my code slightly. See: "A More Faithful Translation" (http://ray.codezen.org/wiki/doku.php?id=binary-search-tree).

-----

0 points by gregwebs 6333 days ago | link

You have just seen a bunch of code that gets the job done, whereas there is still an argument about whether the lisp code should be passed a comparison function. If you are going to make this argument you should show some actual code, because it is obvious from looking at this example which way is better.

-----

2 points by pg 6332 days ago | link

You have just seen a bunch of code that gets the job done,

It seems to me more that you have redefined the job to be what the code does.

-----

3 points by raymyers 6332 days ago | link

Or maybe we just interpreted the job as "a non-destructive binary search tree". Sorry if we misread the syllabus :)

-----

3 points by gregwebs 6332 days ago | link

Sorry, that comment doesn't sound nice and is dumb because I didn't realize what the previous commenter was getting at.

-----