Arc Forumnew | comments | leaders | submit | kennytilton's commentslogin
14 points by kennytilton 6704 days ago | link | parent | on: Docstrings: a contrarian view

The problem with comments is that no one ever changes them when the code changes even tho the comment is right there! don't you see it! change that,too!!!

Moving docstrings away from the code would make things worse, creating multiple copies would make it even worser.

-----

6 points by marvin 6703 days ago | link

I love contrarian views. I disagree with this one, though.

I'd like to hear good arguments for not having docstrings. CatDancer has one instance above, but that particular case could be solved by instructing the editor to hide them until we want them. Source-level documentation solves so many other problems.

Documentation is essential if multiple programmers are going to touch something, which will be the case in the vast majority of projects. "The vast majority" likely even includes most peripheral work on the language itself, such as writing libraries. Keeping the documentation right next to the function/macro definition makes it that much easier to check the documentation and a lot easier to write the documentation in the first place. Even looking up automatically generated documentation on a web site is too much hassle when it could be checked interactively from your terminal.

I think the principal argument for docstrings is that they actually make most programmers document their code, as long as the framework (help-query systems, automatic HTML generation etc.) is in place. And this in turn makes libraries that much more valuable, because it won't any longer take two hours to understand a simple, peripheral but necessary support system.

-----

3 points by kennytilton 6703 days ago | link

* Documentation is essential if multiple programmers are going to touch something, which will be the case in the vast majority of projects.*

I don't know. (a) This is Lisp, we need one tenth the programmers of other languages meaning it is one tenth likely anyone will ever look at my code. (b) Even in tall buildings on projects with twenty people when I was on a trekking vacation in the Andes and my program broke, guess whose yak-phone rang?

-----

3 points by almkglor 6703 days ago | link

(a) This is Lisp, so the same-sized team of Lisp programmers can build a project ten times larger. (b) You.

-----

2 points by shiro 6703 days ago | link

Although this is not a very general example, I tend to oppose in-code docstrings for a couple of reasons.

One of the primary reasons is that we have developers in multiple countries with different primary languges; forcing everyone to write English docs would actually discourages some from writing docs. And mixing multiple languages in the source was a source of troubles (although it's getting better now for most tools and editors can cope with utf-8.)

Another is that I see sometimes documentation and code need different structures; tying one doc for each global entry skews documents away from the better structure. (This doesn't exclude having a small 'remainder' entry per each code, which is useful as you said that you can check in the editor. )

-----

4 points by kennytilton 6703 days ago | link

btw:

"I love contrarian views. I disagree with this one, though."

A sig is born. :)

-----

1 point by akkartik 6703 days ago | link

Here's how I handle that: explicitly connect comments to a specific point of time. Use (version control) tools to regain the advantages of having comments next to code.

http://akkartik.name/codelog.html

That said, the idea of different people maintaining their own documentation is pretty interesting. Anybody have pointers to projects where this has happened?

-----


You made me look again at defset, looks promising:

  (mac defset (name parms . body)
    (w/uniq gexpr
      `(sref setter 
           (fn (,gexpr)
             (let ,parms (cdr ,gexpr)
               ,@body))
           ',name)))
An example being:

  (defset car (x)
    (w/uniq g
      (list (list g x)
          `(car ,g)
          `(fn (val) (scar ,g val)))))
I'll try it when I wake up. :)

-----

3 points by kennytilton 6704 days ago | link

Done and committed to CVS. Thx for the push!

-----

3 points by kennytilton 6704 days ago | link | parent | on: symbol macros, please?

The weird thing is that loop seems Arcy-er than iterate cuz it like Arc goes out of its way to minimize parentheses. Worth the learning curve, I assure you.

-----

2 points by vsingh 6704 days ago | link

Didn't Paul call Loop one of the worst mistakes in Common Lisp? I doubt the man is going to change his mind on this one.

Loop may minimize parentheses (i.e. nesting), but then again, so does BASIC. I'd say the main reason it isn't "Arcy" is that it fails the simplicity-of-implementation test.

-----

2 points by kennytilton 6703 days ago | link

I think you misunderstand. The "weird" to which I refer is precisely pg's anti-(cl)-loopism. He should love loop not just for the brevity, but also because it is a triumph of DSL. ie, CL loop is a DSL for iteration, and I know because I use it for everything. But! pg seems closer to being a schemer at heart so maybe he prefers recursion for things I handle by iteration.

ps. Are you saying BASIC eliminates parentheses the same way LOOP does? :)

-----

1 point by vsingh 6703 days ago | link

It's hard for me to see Loop as a triumph of DSL. I see it more as a failure of Common Lisp to provide simple flexible iteration constructs.

Arc already seems to provide simple operators for many of the cases in which Loop is commonly used. For example: 'accum', 'for', and 'repeat'. It doesn't seem like we need Loop.

Re BASIC: In a way, yes. Both BASIC and Loop use keywords to replace the indication of structure by parentheses. For example, we could eliminate a pair of brackets in 'with' by doing this:

    (with x 2 y 3 z 4 endvars
        (+ x y z))
but that wouldn't be very Lispy.

-----

2 points by kennytilton 6703 days ago | link

Well I resisted Loop for almost ten years then broke down and learned it when PCL came out cuz it had a good chapter on it, so having made the transition I can assure you it is a powerful little iteration language, not just a simple iterator of which CL has many so it is not clear what you do not like about those. I'll ignore your continued insistence that BASIC has anything to do with this discussion. :)

Btw, loop offers a little-known second syntax that is Lispy, one just never sees examples in the wild.

-----

2 points by vsingh 6703 days ago | link

If you have found through long experience that Loop truly offers something unique that can't be offered as well (or as intelligibly) by a combination of simpler operators, then I'll have to take your opinion seriously.

I've made a thread to collect exemplary examples of Loop in action (http://arclanguage.org/item?id=2938) and it'd be great if you could contribute your favorites, e.g. from Cells or other code you've written.

Personally, I don't have the same experience as you. I've found Loop to be useful as a replacement for iteration constructs that should have been in CL to begin with, e.g. dovector, when I'm too lazy to code the requisite macro. I haven't ever had to use Loop in its full complexity.

-----

4 points by kennytilton 6703 days ago | link

Sorry, it just sounds from what you have posted so far that you do not know CL's loop, by which I mean make an effort to use all of its capabilities such that you would know what's there so well that you had it at your fingertips. I am having the same problem with CL idiots denouncing Arc who probably have not even installed it.

You want me to code (dotimes (x 10) (foo))?! No way!

  (loop repeat 10 do (foo)). 
And that is not even a good example!!

  (let (x)
     (dolist (y whatever (nreverse x))
        (let ((py (pfft y)))
           (when py
               (push (yo-mama (cons y py)) x)))
Egad! How about:

   (loop for y in whatever
         for py = (pfft y)
         when py collect (yo-mama (cons y py)))
Is the first version starting to look like a disassembly? Bingo!!! :)

btw, the thing that got me to break down and give loop a chance was learning that the expansion was highly optimized code, meaning (for example) it would not first map across whatever and then delete the nils.

but these examples still do not get to the point of LOOP being a DSL. That property emerges only in the next level of application, as even the loop form expands to ten lines. But once you have loop under your belt (I kill myself) you do not even want to code a simple dotimes, that bogus unused count variable just pisses you off no end, never mind all the extra (wait for it) parentheses!

pg, phone home, all is forgiven! :)

-----

2 points by vsingh 6703 days ago | link

That looks interesting. I've submitted that example to my thread.

-----

1 point by almkglor 6704 days ago | link

/me loves 'loop

-----

2 points by kennytilton 6705 days ago | link | parent | on: Local variables

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.

-----

7 points by kennytilton 6705 days ago | link | parent | on: Infix Math

Old-time lispers rather enjoy our punctuated names and get great mileage out of (especially) using it to flag special variables thus: foo.

Meanwhile, this is all fun, but exactly how often does one put formulas into code, especially formulas one is forever revising meaning we need the editing to be a breeze?

I doubt I code one formula a year, and I write a lot of code. Maybe the engineers out there should just toss off a w/infix macro within which the highly optimized language of math is understood. A starting point might be a Common Lisp infix package, ask on comp.lang.lisp for recommendations.

-----

4 points by eds 6705 days ago | link

Personally I don't think the whitespace is that much of a problem. Certainly I don't think whitespace makes infix less readable; it probably makes it more readable if anything. And it don't think there is a terribly appreciable difference in typing or reading time because of the extra characters. (Arguably the space bar is the easiest key to hit on the entire keyboard.)

While I wouldn't necessarily miss punctuation characters that much, I don't really think it is worth it just to remove the whitespace from infix expressions. You could interpret +-/* as separate in infix expressions only, but I think that creates unnecessary uniformities in the language.

And I do think that math matters. Maybe there are a lot of areas in which you wouldn't really gain much with the infix notation, but exactly the opposite can be said for other fields. I've been working on simple 2D game in CL, and all the math expressions were getting a bit annoying. I would love to try rewriting it in Arc if Arc ever got bindings to any good game libraries.

-----

3 points by kennytilton 6704 days ago | link

Sorry for my repetitiveness (said the same elsewhere) but The Lisp Way when you need a domain-specific syntax is to implement that with a macro and then use the syntax wrapped by the macro. Then Peter does not need to rob Paul (in this case by impoverishing the Arc naming syntax to get math syntax).

Has anyone looked at the CL infix packages?

-----

2 points by eds 6704 days ago | link

If you will simply go without not having whitespace between operators, then you doesn't need to disallow cool characters in symbols or add macro calls in front of all the infix expressions in your code. Honestly, all you save in whitespace you probably spend immediately in having to make the call explicit. I like that the current system integrates infix math seamlessly with s-expressions, that's why I spent my time writing that code. (Admittedly, the infix parts aren't perfect, but the integration itself is fairly seamless.)

I did look at some of the CL infix packages. And if I didn't have programming assignments to work on I might consider porting one.

-----

2 points by dreeves 6705 days ago | link

(Note your foo surrounded by asterisks got interpreted as italics here.)

Could you get most of the same mileage out of capitalization conventions? foo vs Foo vs FOO...

I tried to argue elsewhere that math matters more than you're suggesting: http://arclanguage.org/item?id=2412

I guess this is kind of a religious thing though. :)

-----

2 points by kennytilton 6704 days ago | link

Yeah, I saw that about the foo getting italicized. I guess I'll use octothorpes for asterisks from now one. :)

The coolest hackery has beautiful mathematical gems at the core or in the cleverest bits.

I guess I am not emitting the coolest hackery. :) I know I never put math formulas in my code because it is such a PITA when I do. :) I thought about challenging math infix proponents to post one or two examples from their code, no cheating and contest closed to scientists and engineers.

I do not see it as religious, just a simple question: how often does this come up? And I tried to make another point: this is a Lisp with an intelligible macro mechanism, do what at least one CL project did: write an infix-eating macro! Then you do not need whitespace either, you can have any syntax you want inside the macro. If the task sounds daunting, well that is why I suggested asking on c.l.lisp for the recommended infix package -- just port it to Arc.

-----

2 points by cadaver 6704 days ago | link

There are two concepts under discussion:

First, disallowing arithmetic operators in symbol names, so that (a+b/c) is interpreted like (a + b / c). All the replies to that, up till now, can be summed up like this:

  eds: *I don't really think it is worth it*
  kennytilton: *impoverishing the Arc naming syntax*
  cadaver: *seems not such a good idea after all*
Secondly, whether or not to have some language support for infix. As can be seen in previous discussion, with eds's system, you only need swapped positions where a literal-in-functional-position is encountered for infix support. Paul Graham said that literals in functional position are valuable real estate, nevertheless a comment regarding such an idea can be found in the arc1 source.

One good point of having support is brevity for math-infix users. The only bad point that I see is that we use up the valuable number-in-functional-position real estate, which could have been used for something else.

Supporting infix may not only be good for math. Consider the following:

  (sort (fn (sm gr) (sm < gr)) somelist)
I'm sorry that I can't supply any good examples of heavy maths in real world programs, though I don't doubt that such exist (ciphers?). On the other side, if in a program there isn't any heavy use of maths at all, except for a single mathematical formula that the programmer would like to write in infix, then using a separate macro package would introduce a dependency, and that might make the programmer grudgingly write out the formula in prefix. Another good case for lisp-infix is that when, like me, you tend to copy other's non-lisp formulae then, in eds's infix system, it would look more like its original form.

-----

2 points by kennytilton 6704 days ago | link

Supporting infix may not only be good for math. Consider the following: (sort (fn (sm gr) (sm < gr)) somelist)

Consider: (sort < somelist)

And if (sort (fn (x y) (< x y)) somelist) looks awkward then maybe the issue is prefix altogether? I think anyone trying Arc who is new to Lisp might try Just Lisping (in Arc, of course) for a few weeks before even thinking about changing the language. These things take time and until one has done enough coding to get fluent (or throw up ones hands and say it has been three weeks and I still hate this!) one cannot even form an opinion about the whatever that thing might be. It is like an editor or IDE -- I hated the IDE I love now but made myself wait a month before ripping the vendor a new one. Now people accuse me of being on their sales team.

Case in point: Arc. It is hard judging the brevity/parens stuff because I am in pain anyway without a decent IDE, without a debugger, without a standard library... but I slogged my way thru a port of Cells from Lisp to Arc and some of the brevity is growing on me (I deliberately stopped doing a transliteration and reinvented over the keyboard so I could feel the language better) and at this point I think I can say I would not kick Arc out of bed. Something like that.

btw, if we are just talking about one math formula in a blue moon, why bother? I mean, it would be fun if it had no cost, sure, but apparently pg has plans for numbers in the functional position. Anyway...

-----

2 points by cadaver 6704 days ago | link

cadaver wrote:

  (sort (fn (sm gr) (sm < gr)) somelist)
Yes, a stupid example, sorry.

What are those plans for numbers in the functional position? pg's comments in the arc1 source are completely compatible with eds's system:

Comment 1 is about literal numbers as functions: (1) evaluates to 1

But that is not incompatible with comment two, which is about swapping first and second positions: (1 + 1) evaluates to 2

In fact, math-infix can only benefit if both were added to the language.

-----

1 point by eds 6704 days ago | link

Although literals in functional position may be valuable real estate, I think that infix math is valuable enough to justify using it (at least until we think of something more important).

The only other thing that was suggested in the comment in ar-apply was that literals in functional position might be constant functions. I think infix syntax gives the programmer far more expressive power than being able to denote constant functions.

-----


"you'll either need to use smart editor commands that let you navigate and edit your code based on s-expressions rather than rows/columns, or you'll have to sort out closing parens by hand."

The beauty of parentheses is precisely being able to edit code in meaningful chunks because the parentheses naturally organize our code that way, which is part of why I think Arc's philosophy of "First, we kill all the parentheses" is away from goodness.

When I do edit code as if it were just so many lines and characters (about half the time -- after a dozen years I still have not mastered more than a few keychords) a simple "reformat" keychord automatically puts everything where it should be. And I am rarely disappointed by mistakes because the editor is still giving me cues by auto-indenting when I hit TAB and by blinking matching parens as I type.

I would suggest folks spend a few weeks writing Lisp before they try to change it, they might be surprised how they end up feeling about the parens. Unfortunately pg himself has it in for parens, so I cannot blame you all for the syntax massacre I am witnessing. :) A non-problem is being solved.

-----

4 points by kennytilton 6705 days ago | link | parent | on: Syntax for optional/keyword args

CL keywords are a plist which must be parsed? Yeah, but (loosely speaking) by the compiler, not by me.* For example, in CL I can write your cut thus:

  (defun cut (seq &key (start 0) (end (length seq)))
     ;no parsing here
     (subseq seq start end))
...and then call it like this:

  (cut "Hello World" :start 2 :end 8)
(I made the seq parameter mandatory because I cannot understand why else I would be calling cut.)

keyword args make code more readable and as bogo said are extremely handy for those occasional functions with a kazillion parameters.

* One /can/ combine &rest all-args &key key1 key2 &allow-other-initargs and then parse the all-args as a plist if in a black-belt kinda mood, but it is exceedingly rare to find in normal code.

-----

2 points by are 6704 days ago | link

Arc currently supports optional parameters.

A CL-style keyword argument is like an optional argument in that you need to give it a default value for when it's omitted. But in addition, with a keyword argument at function-call-time, you can switch argument order if you specify the key.

This means that Arc could treat keyword arguments as a special case of optional arguments.

This is the optional-arg example from the Arc tutorial:

arc> (def greet (name (o punc (case name who #\? #\!)))

       (string "hello " name punc)) 
* redefining greet

#<procedure: greet>

arc> (greet 'who)

"hello who?"

But let's say you allow both "o" and "k" for optional arguments, and when there is a "k", you allow the argument symbol to be used as a key when calling the function, like this:

arc> (def greet (name (k punc (case name who #\? #\!)))

       (string "hello " name punc)) 
* redefining greet

#<procedure: greet>

arc> (greet 'who)

"hello who?"

arc> (greet 'john)

"hello john!"

arc> (greet :punc "?!?" 'jane)

"hello jane?!?"

Of course, once you allow an argument symbol to be used as an argument key when calling, you could actually extend this opportunity to every single argument, optional or not. Then you would no longer need the "k" syntax, since every argument is "keyable":

arc> (def greet (name (o punc (case name who #\? #\!)))

       (string "hello " name punc))
* redefining greet

#<procedure: greet>

arc> (greet 'who)

"hello who?"

arc> (greet :punc "?!?" :name 'jane)

"hello jane?!?"

-----

1 point by are 6704 days ago | link

And BTW, the :arg syntax for argument keys is only a CL convention. In Arc, it would be much more natural/readable to use arg: (colon appended rather than prepended to the symbol).

-----

1 point by AF 6703 days ago | link

Is that even a possibility? Doesn't : currently do function composition in Arc?

-----

1 point by are 6703 days ago | link

Wouldn't there be whitespace after an argument keyword, distinguishing it from function composition (no whitespace)?

-----

2 points by kennytilton 6706 days ago | link | parent | on: Question on '() and nil in ac.scm

I do not know (literally! I do CL, not Scheme) if that would work, but it is a bit of a religious issue dividing the Lisp communities. Indeed, this is one of the reasons I am even looking at Arc, that and that mac works like CL defmacro. And fwiw, those two issues were highlighted by pg as things differentiating Arc and Scheme. Not sure if I am adding anything to the debate, but I get the feeling it either would not work or it would freak out any Schemer finding it in ac.scm. :) I guess another thought might be not to get too caught up in ac.scm since it is implementation and might disappear and become <gasp> an Arc/C or Arc/CL compiler or something.

-----


Looks like how common lisp works. And agreed: mixing optional with keyword args would be a nasty thing to do to users. Probably they saw that it was /possible/ and said sure, why not?

-----


I benchmarked your benchmark against all the other benchmarks I could think of including the idea that maybe it did not make sense to time something sitting on top of something else and it came in last.

-----

More