Arc Forumnew | comments | leaders | submitlogin
3 points by rocketnia 92 days ago | link | parent

I almost never use (coerce param 'sym) when I can say sym.param instead. I've always thought Arc doesn't really do enough with the `coerce` function to justify having it in the language; individual functions like `sym` and `string` already do its job more concisely.

---

In practice when I used to write weakly typed utilities in Arc, I tended to find `zap` very nice:

  (def do-something-with-a-symbol (param)
    (zap sym param)
    ...)
If you're unfamiliar with `zap`, (zap sym param) is essentially (= param (sym param)).

I prefer strong typing these days, but I've sometimes thought this `zap` technique could be refined to put the coercions in the argument list directly. Arc has (o arg default) for optional arguments, and we could imagine a similar (z coercion arg) for automatically zapping an argument as it comes in:

  (def do-something-with-a-symbol ((z sym param))
    ...)
---

Something else that's been on my mind is that it could be useful to have higher-order coercion combinators.

Racket code can use `->` to build a contract for a function out of contracts for its arguments and its result. The result of (-> string? string? symbol?) is a contract that verifies a value is a two-argument function and then replaces it with a function that delegates to that one, but which verifies that the arguments are strings and that the result is a symbol.

The same thing could be done for coercions: The result of (as-> string string sym) could be a coercion function that coerces its argument into a two-argument function that delegates to the original value, but which first coerces the arguments to strings and then coerces the result to a symbol.

  (def as-> args
    (let (result-coercion . arg-coercions) rev.args
      (zap rev arg-coercions)
      (fn (orig)
        (fn args
          (result-coercion:apply orig
            (map (fn (coercion arg) coercion.arg)
              arg-coercions args))))))
  
  (= symbol+ ((as-> string string sym) +))

  arc> (symbol+ 'foo 'bar)
  'foobar
Similarly, in Racket, `(listof symbol?)` is a contract that checks that a value is a list of symbols, and for coercions we could imagine a corresponding `(aslistof sym)` operation for use in your `(map [coerce _ 'sym] ...)` example.

Sometimes Arc's weak typing suffers from making poor guesses as to whether `nil` is intended as a symbol or as a list (not to mention as a boolean), and it takes some adjusting to work around it:

  arc> (symbol+ 'foo 'nil)
  'foo
  
  arc> (symbol+ 'nil 'nil)
  '||
  
  arc> (= symbol+ ((as-> [string:or _ "nil"] [string:or _ "nil"] sym) +))
  #<procedure: as->>
  
  arc> (symbol+ 'nil 'nil)
  'nilnil


2 points by kinnard 92 days ago | link

I overlooked the existence of `sym` which does make my request altogether superfluous. Higher-order coercion combinators will take some digestion on my part!

-----