Arc Forumnew | comments | leaders | submitlogin
3 points by waterhouse 5138 days ago | link | parent

Macro: (as type x) : Macroexpands to (coerce x 'type). Leads to the more pleasant form:

  (as string
      (big long
           (hairy gigantic)
           (immense and complicated (function))))
instead of:

  (coerce (big long
               (hairy gigantic
               (immense and complicated (function)))
          'string)
In the first case, you can hear the coder thinking, "Now I want to coerce this thing into a string; this thing is big and long and hairy and [...]." In the second case, the coder thinks, "Now I want to coerce this thing into a string; I write coerce, and now I'll have to remember to write 'string; now this thing is big and long and hairy and [...]; and now what was that I was remembering? I see a coerce up there with the unbalanced parenthesis... oh, yeah, 'string." It's just a little bit easier on the mind.

  (mac as (type x)
    `(coerce ,x ',type))
Credit to aw for creating this: http://arclanguage.org/item?id=10752

(Incidentally, aw's thread doesn't show up in aw's "submissions" list. Weird.)



1 point by rocketnia 5138 days ago | link

If I may:

  (string:big long
    (hairy gigantic)
    (immense and complicated (function)))
No macro is needed, and there's less indentation and fewer parentheses. You can also improve on the 'as macro by allowing for (as (type expr)) in addition to (as type expr). That lets you cut down on indentation and parentheses just as much:

  (as:string:big long
    (hairy gigantic)
    (immense and complicated (function)))

-----

2 points by akkartik 5138 days ago | link

as is still useful for coercing to other types.

-----

1 point by rocketnia 5137 days ago | link

Sure is, but I'm just a bit of an un-fan of 'coerce. I've already mentioned unary functions being more convenient with a:b ssyntax. On top of that, there's oftentimes more than one obvious way to get one type of value from another, and while you could use custom types to represent more coercion targets, like (rep:coerce x 'assoc-list), I think that's a step in the wrong direction, just 'cause I don't know where the benefit is.

-----

1 point by akkartik 5137 days ago | link

Ah I see. But I don't follow what you mean by unary a:b.

-----

1 point by rocketnia 5136 days ago | link

The ssyntax expressions (a:b ...), a.b, and a!b all pass only one argument to a, so ssyntax (currently) makes one-argument functions and macros more convenient than other kinds.

-----

1 point by akkartik 5136 days ago | link

Ah, that makes sense. And why is it bad to have more than one way to convert one type into another?

-----

1 point by rocketnia 5136 days ago | link

Eh? XD There's nothing wrong with that. My point was that it doesn't make a whole lot of sense to designate just one conversion for each target type when there are lots of options.

(Note from the future: What follows doesn't really continue that response. I just started randomly considering a few more angles. ^_^ )

Most of the time, [coerce _ 'string], [coerce _ 'sym], and so forth just end up being more verbose ways of saying things like [string _] and [sym _]. Almost all the uses of 'coerce in Arc 3.1 and Anarki are like that, where they hard code the target type, so that it's just like the name is coerce-cons or coerce-string but without any synergy with ssyntax. There are two exceptions:

  (def sort (test seq)
    (if (alist seq)
        (mergesort test (copy seq))
        (coerce (mergesort test (coerce seq 'cons)) (type seq))))

  (def inc (x (o n 1))
    (coerce (+ (coerce x 'int) n) (type x)))
These functions have the special property that they can be used with all sorts of types as long as 'coerce is capable of translating back and forth. If you want to make a custom type that's compatible with them, you only need to replace or extend 'coerce to do it, rather than, well, replacing 'sort or 'inc. :-p This technique was sort of rediscovered here recently: http://arclanguage.org/item?id=12340

Now that I think about this, my position has softened even more, but I'm still a bit stubborn. Even if 'coerce is only used as a way to convert something back from the type a calculation needs to manipulate it in, there's still an arbitrary choice being made between multiple behaviors. If some generic string utility wants to convert '(#\[ #\1 #\]) to "[1]" and back, but some JSON utility wants to convert '(1) to "[1]" and back, then (coerce "[1]" 'cons) needs to have two meanings at once.

Of course, if it comes to that, it's easy to just make the JSON utility convert from '(1) to (annotate 'json-encoded "[1]") and back instead. I think I have no escape from that. XD Any corner case I come up with is going to be at least as you're-not-gonna-need-it as 'coerce is. ^_-

Nevertheless, while I was arguing with myself, I came up with an experimental type-independent (and therefore 'coerce free) way to model back-and-forth transformations. It's a pretty obvious design, but I somehow managed to make it complicated and arbitrary in certain ways. :-p Here it is in case anyone's interested:

  (def encode-int (unencoded)
    (list `(type ,type.unencoded) int.unencoded))
  
  (def decode-int (recovery-notes encoded)
    (let fail (fn () (err "Unexpected 'decode-int case!"))
      (case do.recovery-notes.0 type
        (case do.recovery-notes.1
          string  string.encoded
          int     encoded
                  (do.fail))
        (do.fail))))
  
  (= encoding-int (annotate 'encoding
                    ; This is more hackable than
                    ; (list encode-int decode-int).
                    (list (fn args (apply encode-int args))
                          (fn args (apply decode-int args))))
  
  (def fn-through (encoding unencoded body)
    (withs ((encode decode) rep.encoding
            (recovery-notes encoded) do.encode.unencoded)
      (do.decode recovery-notes do.body.encoded)))
  
  (mac through (encoding var . body)
    `(fn-through ,encoding ,var (fn (,var) ,body)))
  
  (def inc (x (o n 1))
    (through encoding-int x
      (+ x n)))
(Hmm, is this related to http://en.wikibooks.org/wiki/Haskell/Monad_transformers#lift? >.> )

-----

2 points by akkartik 5136 days ago | link

"it doesn't make a whole lot of sense to designate just one conversion for each target type when there are lots of options."

Ah, now I follow. But often there's one kind that applies far more often than alternatives. And it's good for coerce to give it. For other type combinations it's good to know that coerce is complete, and that it'll give some sort of conversion. But you're right, I don't know if this ever makes code shorter. Perhaps this is yet another example of programmer's OCD, that insidious need to have things be aesthetic even when they don't matter.

I just started randomly considering a few more angles. ^_^

I'm starting to realize that's the reason I have a hard time following what you write :) If I may make a suggestion, make a list. I find your long comments are often too terse. Often they contain enough stuff for three or four distinct postings or comments. But the transitions are abrupt, perhaps because you're trying not to be even more long-winded. If you gave each idea its own post or comment it would have more room to breathe, and I'd be able to return to each one at my leisure. Feel free to post new submissions with substantial ideas. We hardly have enough submissions here.

Like your code idea at the end of the comment, and the suggestion that it's like monad transformers. I'd love to see a post elaborating on it. I'd love even more to see a yegge-sized elaboration of all your thoughts on coerce and what 'synergy with ssyntax' means. Perhaps they haven't settled down yet, but keep it in mind when they do :)

Sometimes I feel I would spend an hour with any one of your ideas if you'd spent just a few extra minutes with it.

Hopefully this is constructive feedback. Perhaps it's just me having poor comprehension; you should ask for others' opinions.

-----

2 points by rocketnia 5135 days ago | link

I have a hard time following what you write :)

Thanks for telling me that. ^^;

My usual process is that I'll take a few hours to write a comment, then I'll run out of time and decide to come back later to finish it up, and then I'll never go back to that draft (but I might start from scratch on the same topic). Occasionally I'll finish something in time to post it.

Recently, I have less time than I'm used to, so I've been posting things even if they're rough, in case someone gets value out of it anyway. I guess this makes my posts into scatterings of half-ideas, based on things I've been thinking to myself but only now had a reasonable excuse to mention. (Usually I shoot for a few organized, mostly full ideas, which also have very good excuses to be mentioned. :-p )

Thanks to your suggestion, I'll try harder to talk about things even when there isn't an excuse. ^_^

-----

1 point by akkartik 5138 days ago | link

(Incidentally, aw's thread doesn't show up in aw's "submissions" list. Weird.)

I noticed this as well as I was trying to recall some old ideas. For some reason people's submitted pages here don't get a more link like they do on HN. I emailed PG a request.

-----