Arc Forumnew | comments | leaders | submit | conanite's commentslogin
2 points by conanite 5937 days ago | link | parent | on: Dotted lists.

There's a comment at the end of arc.arc that might be relevant:

  ; solution to the "problem" of improper lists: allow any atom as a list
  ;  terminator, not just nil.  means list recursion should terminate on
  ;  atom rather than nil, (def empty (x) (or (atom x) (is x "")))
But I think this means (len '(a b c . d)) would be 3, which may not be what you wanted.

-----

1 point by conanite 5937 days ago | link | parent | on: Multi character matching, and ssyntaxes

Just curious - wouldn't it suffice to return the index of the beginning of the matched string when running a substring search?

  arc> (str "arc")
  6
, because you already know the length of "arc", so you don't really need a range result?

Otherwise, these are great ways to occupy the "semantic space" of string in fn position.

-----

1 point by shader 5937 days ago | link

I agree with you. I don't think that returning a range is necessary.

Even if call position and assignment weren't handled separately, it would still be possible to work off of the length of the argument and the index, without needing a range.

The question is whether or not pg agrees with us enough to add it to arc3 ;)

-----

1 point by conanite 5937 days ago | link

If there are 100 arc coders in the world, there are probably 100 versions of arc also. The question is whether you want it in your arc :)

-----

1 point by shader 5937 days ago | link

True. And I do. Unfortunately, I'm busy working on several other things at once right now. If you want to start working on it, be my guest. Hopefully I'll be able to share what I've been doing soon.

-----

1 point by Adlai 5937 days ago | link

I guess that (str "world") could just return an index, because (= (str "world") "arc") has access to the entire call, and can thus calculate

  (+ (str "world") (len "world"))
to figure out what the tail of the string should be after a substitution.

-----

1 point by conanite 5937 days ago | link | parent | on: Multi character matching, and ssyntaxes

arc supports multiple values via destructuring

  (let (a b c) (fn-returning-list-of-3-things)
    ...)
In the particular case of returning multiple indexes into a string though, you don't usually know in advance how many matches there will be, so destructuring isn't an option.

-----

1 point by Adlai 5937 days ago | link

Multiple return values from a form are allocated on the stack, not on the heap. I don't 100% understand what that means, though...

One practical consequence is that you don't have to deal with later multiple values if you don't want to, but when values are returned as a list, you have to deal with them.

-----


I usually

  (if a b
      c d
        e)
if it fits, otherwise

  (if a
      b
      c
      d
      e)
The wavy-style if indentations make me seasick.

-----

1 point by Adlai 5937 days ago | link

I think that your first example is probably best in terms of compactness and clarity (associating each condition with its corresponding code). The completely straight indentation can be difficult to scan quickly if you have more than one condition. IMO, the only problem with your first example is when the conditions span more than one line or are very long.

-----

1 point by Adlai 5937 days ago | link

In terms of 'if, I was looking through some of pg's code just now, and noticed that he does use the wavy form of indentation. Thus, if you're big on proof by authority, the correct form of indentation for 'if would be the wavy one...

-----

3 points by conanite 5937 days ago | link

I was looking through some of pg's code just now

arc code or scheme code?

I once heard a great teacher say that appeal to authority is flawed rhetoric, so I never do it :)

-----

2 points by shader 5936 days ago | link

Never heard that one before ^^

However, in this case I agree with Adlai: pg had even planned on getting ppr to "properly indent long ifs". I presume that means to implement the wavy feature. It's also the convention for Anarki, according to the CONVENTIONS file.

So, here's what I'm thinking should be done for ifs:

1) If you only have three expressions, if-then-else, use:

  (if a
      b
      c)
1) If you like the format, and the expressions are very short use:

  (if a b
      c d
      ...
        e)
3) If you don't like that form, or the expressions are longer, use:

  (if (a       )
        (b       )
      (c       )
        (d       )
      (e       ))
I'm not sure whether to use one or two spaces between clauses. The anarki conventions file uses two spaces. Elsewhere I've seen only one space. So, which is it? Now or never ;)

(I'm writing a new version of ppr with proper indentation of forms, in case you wanted to know why I'm so interested in the indentation question)

-----

2 points by Adlai 5936 days ago | link

I think two is better, because it a) clearly distinguishes it as indentation (rather than just an accidental #\space), and b) it's consistent with the indentation of macros & co.

-----

1 point by shader 5934 days ago | link

Two spaces it is.

Another question:

How do people indent do, and, or, etc.:

a)

  (do abc
      bcd
      cde)
or b)

  (do
    abc
    bcd
    cde)
Choice a is more like a function call, b is more like a macro. Should it be a community standard, or on a user by user basis?

-----

1 point by CatDancer 5934 days ago | link

I use A, for me the space taken up by the extra indentation is less than the extra line taken up for B.

I don't use indentation as a way to indicate whether I'm calling a function or using a macro.

-----

1 point by shader 5934 days ago | link

Next question:

Should case be indented like 'if:

  (case
    a
      (b     )
    c
      (d     )
    (e      ))
or in pairs like with:

  (case
     a (b    )
     c (d    )
     (e     ))
?

Should it depend on whether they fit on one line or not? If they don't fit, should it still be like b., just with the second part spilling onto the next line?

-----

1 point by CatDancer 5934 days ago | link

I use the second if it fits OK, or the first if they don't fit.

-----

1 point by absz 5933 days ago | link

Ditto, except I write

  (case
    a-short     (b ...)
    c-very-long (d ...)
                (e ...))
when everything is on one line, and

  (case
    a-short
      (b ...)
    c-very-long
      (d ...)
    ; else
      (e ...))
when it doesn't (though I go back and forth about the ; else).

-----

1 point by shader 5932 days ago | link

Your first version is the one currently implemented by ppr.arc. If you would like, you can write the indentation function for your second version (it can even include the "; else")

Otherwise I think that the first version is generally clearer, and the second is rarely needed, as the value of the case statement can't usually be very long. Could you give me an example where you use your second version?

-----

1 point by absz 5932 days ago | link

Sure; here's something from my tagged-unions.arc on Anarki (Arc 2). It's responsible for parsing the types specified for slots in the tagged union:

  (each type-frag types
    ; Assemble the ('type name) pairs into two lists, so that we can iterate
    ; through them.
    (case (type type-frag)
      ; If it's a symbol, then we're defining a new name; add a new set of
      ; values, and go.
      sym
        (do
          (zap [cons type-frag _] names)
          (zap [cons nil       _] values))
      ; Otherwise, we're adding a value to an existing variant.
      cons
        ; I changed my mind about the order (now it's (name pred?) instead of
        ; (pred? name)), so I'm reversing it here.
        (zap [cons (rev type-frag) _] (car values))
      ; else
        (err "Invalid member of tagged union declaration.")))
I should also add (just as another data point) that my multi-condition ifs look like that too, and single-condition ifs look like the following:

  (def macexn (n expr)
    " Macroexpand `expr' `n' times.  NB: `expr' *is* evaluated!
      See also [[macex1]] [[macex]] "
    (if (and (number n) (> n 0))
      (macexn (- n 1) (macex1 expr))
      expr))
I'm not hugely wedded to any of my conventions, though, and I haven't coded in Arc for quite a while anyway; this isn't intended to get you to change anything or convert people to my style. As I said, it's just another data point.

-----

1 point by Adlai 5937 days ago | link

Well, the 'if macro only exists (as a macro) in Arc.

However, the indentation actually isn't completely consistent. There are a bunch of places where pg does a straight indentation for 'if.

-----

1 point by pg 5937 days ago | link

I've never felt 100% sure about it though.

-----

1 point by Adlai 5937 days ago | link

Well, I think it adds just enough clarity to be worth the "seasickness". I guess it's also related to the indentation from CL 'cond:

  (cond ((condition1)
         (result-code1))
        ((condition2)
         (result-code2))
        (default-code))

-----


I don't get symbol macros. Is there an example of a symbol macro in use? On another thread someone mentioned that a symbol macro can expand into arbitrary code. Is this the same as an ordinary macro with no arguments (except for a pair of parens) ?

On a possibly related note, when compiling (assign ...) forms, ac.scm calls macex on the 1st arg:

  (assign (foo bar) 12)
'(foo bar) gets macexed. Later, ac-set requires that its first argument be a symbol. So '(foo bar) must expand into a symbol. I didn't see this obviously being used anywhere in arc ... do I need to look harder? Is its usage buried under layers of macros (deep inside '= for example), or what's the story? Is this somehow related to the concept of symbol macros?

yours truly, Confused.

-----

2 points by Adlai 5937 days ago | link

I'm not sure about your related note, but for an example of symbol macros in use:

This example is from Common Lisp's object system, called CLOS. When you want to do some code while accessing specific slots of an object, you can use a 'with-slots form, which lets you name symbols that you'll use to reference specific slots of the object. The 'with-slots form then generates local symbol-macros for each symbol you mentioned, which expand into code to access those slots. An example, taken from PCL [1]:

  (with-slots ((bal balance)) account  ; Here 'balance is the name of the slot, and 'account is the specific object
    (when (< bal *minimum-balance*)    ; *symbol* is a CL convention for global variables
      (decf bal (* bal .01)))))        ; decf is like --
[1] Practical Common Lisp, by Peter Seibel, available online at www.gigamonkeys.com/book/

-----

2 points by eds 5937 days ago | link

Another use for symbol macros is in writing package/module systems, where you want to determine which package a symbol goes into based on the compilation context.

You can do this to a certain extent already, using package!symbol notation, but this still doesn't allow using symbols without prefixes.

EDIT: See http://arclanguage.org/item?id=3572

-----

1 point by conanite 5938 days ago | link | parent | on: Lexically shadowing a macro?

The lexical binding shadows the global binding if it isn't in functional position:

  (def trivial-example (obj with) (foo obj with))
does what you would expect it to do. But I don't know whether or why it's better that global macro definitions override lexical bindings in functional position.

-----

1 point by conanite 5938 days ago | link | parent | on: Multi character matching, and ssyntaxes

So far, we have lib/arc-read.pack and lib/parser.arc, both in anarki, as well as lib/parsecomb.arc. Not only do you have your reader, but you have a choice of them too!

arc-read seems to be designed for easy extensibility although I haven't tried it at all. (If I had looked carefully before embarking upon parser.arc, I might have saved myself a lot of trouble).

parser.arc doesn't support the full range of scheme numbers, nor does it support |foo| symbol syntax yet, apart from ||. I'm working on a new version that will hopefully be faster - welder depends on the tokeniser for syntax highlighting.

parsecomb.arc, if I understand correctly, isn't an arc parser but a library for building parsers.

In any case, having an implementation of 'read in arc makes a lot of sense, and it's in the todo at the top of arc.arc

-----

1 point by conanite 5938 days ago | link | parent | on: "ac-tunnel" proposal

parser.arc (at least, the parser lib I wrote; there are at least two others in anarki) uses coerce to get corresponding atoms from the token in string form. 'eval would probably have worked too. Otherwise, parser.arc just returns the forms it reads in, only transforming bracket syntax and string interpolations.

-----


What CatDancer said, plus: do you get the same error on all browsers? If you use wget or curl instead of a browser, do you still get this error?

-----

1 point by conanite 5940 days ago | link | parent | on: "ac-tunnel" proposal

I completely agree ac-tunnel (or mz) is a useful facility to add to arc, especially to use for once-off hacks, or to figure something out before committing to an xdef. I wrote rainbow just so I could use java libs while playing in arc (among other reasons).

As the author, you get to name your babies. I didn't agonise over java-new, java-implement, or (ugh) java-static-invoke - they're mostly buried under arc macros in any case.

In the worst case, if there's a conflict with mz (or ac-tunnel), I would recommend an excellent symbol renaming hack available on github at http://catdancer.github.com/load-rename.html

:))

-----

More