Arc Forumnew | comments | leaders | submit | parenthesis's commentslogin
3 points by parenthesis 6417 days ago | link | parent | on: prn drops quotes on string?

Here's a quick hack for what you want:

Put this in ac.scm:

  (xdef 'print (lambda args
                 (if (pair? args)
                     (print (ac-denil (car args)) 
                              (if (pair? (cdr args)) 
                                  (cadr args)
                                  (current-output-port))))
                 (flush-output)
                 'nil))
And these in arc.arc:

  (def rpr args
    (map1 print args)
    (car args))

  (def rprn args
    (do1 (apply rpr args)
         (writec #\newline
                 (if (isa (car args) 'output) (car args) (stdout)))))
Then:

  > (rprn (list 'a 2 "c"))
  (a 2 "c") ; prints this
  (a 2 "c") ; returns this
Edit: The above are just very slightly modified versions of the code used to implement pr and prn, the difference is that Scheme's print is used instead of display, to give READable output.

-----

3 points by pg 6417 days ago | link

As offby1 pointed out (http://arclanguage.org/item?id=1997) there is already a fn for this: write.

-----

1 point by parenthesis 6422 days ago | link | parent | on: Poll: What would you change in Arc?

Perhaps this is a crazy stupid idea, but what about macros that let you modify the surrounding code too:

  (def foo ()
    ...
    (make-local bar 'baz) ; macro call
    ,,,)
expands into:

  (def foo ()
    (let bar 'baz
      ...
      ,,,))

-----

2 points by tel 6422 days ago | link

Does that always expand up to the current block? Why is it an advantage over let syntax?

-----

2 points by absz 6422 days ago | link

This would also allow things like a splice operator (mentioned here: http://arclanguage.org/item?id=540); if we had this (assuming that @x expands to (splice x)), you could write (let arglist '(4 5 6) (list 1 2 3 @arglist 7 8 9)) and get (1 2 3 4 5 6 7 8 9). This would actually be superior to apply in certain cases: (and x y @arglist) wouldn't have to evaluate y or the parts of arglist, whereas (apply and x y arglist) has the same effect in most cases, but does evaluate y, which can be problematic. I suppose one way to solve this would be to give values a "cer" (Current EnclosuRe) or some such; if lst were '(1 2 (a b) 3 4), then (cer x) = nil, (cer (car x)) = x, and (cer (car (list-ref 2))) = (list-ref 2). It's not clear what (cer (cdr x)) would be, but it would probably also be x.

-----

1 point by almkglor 6421 days ago | link

Personally I'd still implement this as a macro form, such that we would have a (spliceable ...) form which would scan its contents for splice-macros. So the syntax would look approximately like:

(spliceable (let arglist '(4 5 6) (list 1 2 3 (splice arglist) 7 8 9)))

(spliceable ...) would essentially be a generalization of the `() operator, except that ` will only scan for , while (spliceable ...) would scan for any splice-macros.

-----

4 points by parenthesis 6423 days ago | link | parent | on: Poll: What would you change in Arc?

Multiple values.

Keyword arguments.

Modules.

FFI.

So far, I'm not too keen on = for setf. Mainly for the negative reason that I like = with its comparison of numbers meaning. Perhaps (! a 0) for assignment?

The other short names for commonly used operators I find a big win though. I've already copied a lot of them to my own pet Lisp - that's how much I like them.

-----

4 points by mdemare 6422 days ago | link

Why not use = for assignments and == for comparisons? It's what over 90% of programmers are used to (just not lisp programmers).

-----

1 point by parenthesis 6424 days ago | link | parent | on: Updated range with step

A bit ugly:

  ;tail recursive, trickery to avoid reversing acc
  (def range (start end (o step (if (< end start) -1 1)))
    (= step (- step)
       end (+ end (mod (- start end) step)))
    ((afn (end acc)
       (if (or (and (< 0 step)
                    (<= end start))
               (and (< step 0)
                    (<= start end)))
           (self (+ end step) (cons end acc))
           acc))
     end nil))


  ;iterative
  (def range (start end (o step (if (< start end) 1 -1)))
    (let result nil
      (repeat (+ (truncate (/ (- end start)
                              step))
                 1)
        (push start result)
        (++ start step))
      (rev result)))

-----

1 point by greatness 6424 days ago | link

A little prettier perhaps, though follows the same idea:

  (def range (st en (o step 1))
    (if (is step 0) (= step 1) (zap abs step))
    (let (stp-fn test) (if (> st en) `(,- ,<) `(,+ ,>))
       ((afn (i accum)
          (if (test i en) (rev accum)
                          (self (stp-fn i step) (push i accum))))
        st nil)))
If what order you want the range doesn't matter, you can remove the (rev accum) and replace it with accum. Example output:

  arc> (range 0 -5)
  (0 -1 -2 -3 -4 -5)
  arc> (range 5 5)
  (5)
  arc> (range 0 5)
  (0 1 2 3 4 5)
  arc> (range 0 10 2)
  (0 2 4 6 8 10)
  arc> (range 10 0 2)
  (10 8 6 4 2 0)
EDIT: added some error-checking, changing a step from 0 to 1 probably isn't the right thing to do, but I didn't feel like figuring out how to throw an error.

-----

1 point by greatness 6423 days ago | link

Turns out consing up the list is faster, though without the rev function it is very close:

  (def range (st en (o step 1))
    (if (is step 0) (= step 1) (zap abs step))
      (let (stp-fn test) (if (> st en) `(,- ,<) `(,+ ,>))
        ((afn (i)
           (if (test i en) nil
                           (cons i (self (stp-fn i step)))))
         st)))
though I don't know why.

-----

1 point by joseph 6423 days ago | link

How about a default start of 0?

  (def range (default (o end) (o step 1))
    (with (st (if end default 0)
           en (if end end default))
      (if (is step 0) (= step 1) (zap abs step))
      (let (stp-fn test) (if (> st en) `(,- ,<) `(,+ ,>))
         ((afn (i accum)
            (if (test i en) (rev accum)
                            (self (stp-fn i step) (push i accum))))
          st nil))))

-----

6 points by parenthesis 6424 days ago | link | parent | on: No internal definitions?

As I understand it

  (def foo () nil)
is (roughly) equivalent to

  (= foo (fn () nil))
So, regardless of the context of the (def foo ...), if there isn't a local foo, it's the global foo that is bound to the new function.

To have a local function foo:

  (def foo () nil)

  (def bar ()
    (let foo (fn () t)
      (foo)))
And then

  (bar) -> t
  (foo) -> nil

-----

1 point by tger 6424 days ago | link

Thanks for your reply! My confusion stemmed from the fact that I thought that def behaved like define in Scheme (i.e. establishing a new binding), which apparently was not the case.

-----

1 point by parenthesis 6424 days ago | link | parent | on: cyclic structure

It's okay so long as you don't try to print a circular list:

  arc> (= a '(1 2))
  (1 2)
  arc> (do (= (cddr a) a) t)
  t
  arc> (pop a)
  1
  arc> (pop a)
  2
  arc> (pop a)
  1
  arc> (pop a)
  2

-----

5 points by parenthesis 6425 days ago | link | parent | on: List of Arc Functions and Macros

Excellent. But don't forget the xdef'd stuff in ac.scm: (sig (variable), apply, cons, car, cdr, is, ...).

-----

3 points by dmdavis 6425 days ago | link

thanks, I'll look at adding those.

-----

1 point by dmdavis 6423 days ago | link

OK, done.

-----

1 point by parenthesis 6425 days ago | link | parent | on: REPL variables

Why does that work?

-----

2 points by sjs 6425 days ago | link

tostring captures whatever is sent to stdout.

    (tostring (prn "hi"))
returns the string "hi\n" instead of actually printing it.

-----

3 points by parenthesis 6425 days ago | link | parent | on: REPL variables

that and ^ do the same thing (but there's also ^^, ^^^).

thatexpr is like CL + .

But (%) is like (eval thatexpr), except % is a macro that gives you what the last thing entered expanded into. And so, since % is a macro, it itself is expanded away. Hence

  arc> 2
  2
  arc> (* ^ 2)
  4
  arc> (%) ; equivalent to entering (* ^ 2) again
  8
  arc> (%) ; and again
  16
  arc> (%) ; and again
  32
Whereas

  arc> 2
  2
  arc> (* ^ 2)
  4
  arc> (eval thatexpr) ; i.e. (eval (* ^ 2))
  8
  arc> (eval thatexpr) ; i.e. (eval (eval thatexpr)) i.e. (eval (eval (eval thatexpr))) etc.
  [infinite loop]

-----

1 point by parenthesis 6425 days ago | link | parent | on: REPL variables

Ah, yes, that's what I forgot to say: I also changed in arc.arc :

  (set safeset (annotate 'mac
                 (fn (var val)
                   `(do (if (bound ',var)
                            (if (~is ',var '%)
                                (do (disp "*** redefining ")
                                    (disp ',var)
                                    (writec #\newline))))
                        (set ,var ,val)))))

-----

More