Arc Forumnew | comments | leaders | submitlogin
core language thingies
3 points by bOR_ 5980 days ago | 14 comments
Just dumping some things here that I'd like as a core language structure (and inviting others to do the same in this thread).

I've often written things like this:

  if A+C > B then A = A+C
and wished that I could formulate it in some way that I didn't need to calculate A+C twice. Of course that could be solved in two lines:

  A' = A+C
  if A' > B then A = A'
which is a complete solution. However, I've often wished for being able to refer to a location in a statement. (ruby-wise I'm used to putting 'if' at the end of things when convenient, but you could also write it in the oldfashioned way.):

  A = A+C if (righthand side of =) > B
  if (lefthandside side of =) > B then A = A+C
Anyway, that's in ruby. In arc, this would translate from-to:

  (if (> (+ (A C)) B) (= A (+ (A C))))
  (if (> (+ (A C)) B) (= A 'first))
with 'first and 'second being the (+ (A C)) and B.

Would this be a useful feature? are there any other cases where being able to refer to a location in your code is a useful addition to a language?

4 points by pg 5980 days ago | link

One could define an operator that worked like this:

  (atest (+ a c) [> _ b] (= a it))
Though it isn't necessary in this case, the body could have multiple expressions, like a when. This operator would be like awhen, but binding it to the thing being tested instead of the result of the test.


4 points by gosub 5980 days ago | link

Nice idea, an anonymous variable definition. It could be something like this:

    (if (> $(+ A C) B) (= A $))
that would be macro-expanded to

    (if (> (push (+ A C)) B) (= A (pop)))
or a let declaration. There could be also a push-quote that returns the argument evaluated but memorizes the quotation.


1 point by drcode 5971 days ago | link

I like this idea! It could aid in terseness- Though it's a little line-noisy...


2 points by greatness 5980 days ago | link

I'm not sure if I quite understand you, "(A C)" In your Arc code suggests A is a function. Going by your first posted code, you can achieve this in Arc with:

   (aif (> (+ A C) B) (= A it))


2 points by sjs 5980 days ago | link

When that is true it evaluates to t.

  arc> (= a 2 b 5 c 3)
  arc> (aif (> (+ a c) b) (= a it))
  arc> a
  arc> (aif (>= (+ a c) b) (= a it))
  arc> a


3 points by greatness 5980 days ago | link

good point, I should have thought that one through. Perhaps we should consider changing the return value of ">" so I'm correct? :P

It seems more useful to have the return value be the greater number if it is true, and since all non-nil values are true, it wont break any existing code. For a > b, consider the following:

  (> a b) => a
  (> b a) => nil
We can make a new > procedure which does this:

  (def >? args
     (if (apply > args) (car args) nil))

  arc> (>? 5 2)
  arc> (>? 2 5)
  arc> (>? 7 5 2 3)
Then, using my definition from before:

  (aif (>? (+ a c) b) (= a it))
It shall now work. Now I'm not stupid anymore. :p


1 point by sjs 5980 days ago | link

Makes sense to me. It's a trivial change in ac.scm for < and >. What about (<= 1 2 3) and (>= 3 2 1)? The easiest way to do the same for those two is to return the last value compared, which would be 3 and 1 respectively. That doesn't exactly jibe with < and > though so I hesitate to make such a change. Thoughts?

It seems logical that <= and >= should also return some meaningful value if < and > do. If we come up with something good I'll push it to the anarki repo (git wiki). Although, we could always just ignore <= and >= for now.


1 point by greatness 5977 days ago | link

Why not follow the same idea as < and >:

  (def <=? args 
    (if (apply <= args) (car args)))


1 point by sjs 5975 days ago | link

I should have been clearer. I agree the semantics should be the same, I just didn't see an immediately clean way to add that to the current, recursive <= and >= functions. A thin wrapper would work just fine.


1 point by greatness 5971 days ago | link

Yeah, either that or use a lambda function inside their definitions:

  (def >= args
    (let f (afn (ar) (or
                       (no:cdr ar)
                       (and (no:<
                       (self:cdr ar))))
      (if (f args) car.args)))


1 point by bOR_ 5980 days ago | link

just ment A B and C to be numbers.

Got it.. thanks for introducing me to anaphoric macros :). Now the question is whether writing macros and having several aifs aands awhile aif2s for it is the way to go, or whether it is something that might be core-worthy, in a way that gosub (see post below) suggested.


1 point by sjs 5980 days ago | link

I would just use this first form below. A macro you may be able to adapt for your purposes follows.

  (let a2 (+ a c)
    (if (> a2 b) (= a a2)))

  (mac =if (var expr test)
    (w/uniq result
      `(let ,result ,expr
         (if (,test ,result) (= ,var ,result))

  (=if a (+ a c) [> _ b])


1 point by dfranke 5980 days ago | link

What's wrong with

  (let d (+ a c)
     (if (> d b) (= a d)))

and if your concern is efficiency rather than readability, yell at your compiler guy to implement common subexpression elimination.


2 points by bOR_ 5980 days ago | link

simplicity. I want (and I think I've seen enough examples of code now to write a macro to do so).. I want to be able to say / think / write this:

  (if (calculation gives wanted result) (assign calculation to variable)).
saying / thinking / writing your version just puts the language in the way of what I want to write down.. and even though the difference is minimal, all these little kind of things can add up and obfuscate your code.

  (store calculation as variable
    (if (variable gives wanted result) (assign calculation to another variable))
General idea of the post was just to try and find bits and pieces where the language can be smoothened.