On Aug 12, 2009, at 2:02 PM, tsuraan wrote:

> I didn't put it in yet, but I was thinking of just having nil in the
> type vector for unhinted variables, so you could have
>
> (defn foo {:signature [ String String nil ]} [ a b c ] ...)
>
> and then c wouldn't be hinted.  I hadn't thought of destructuring at
> all; I'm guessing that it could be done with

I'd think _ would be more idiomatic for those that like the haskell- 
esque style...?

> (defn foo {:signature [{:bar Mytype} nil nil nil]} [{blah :foo mt-obj
> :bar} a b c] ...)
>
> but that's getting pretty ugly on its own.  I'm not sure if it would
> be a win to try to do anything fancy like that.  I'm also not sure
> what the destructuring assignment syntax is for maps right now, so
> what I wrote might be total nonsense, syntactically.  I hope the idea
> is clear, anyhow.

Yeah, I think supporting a parallel argument specification is probably  
not tenable.  On the other hand, performing a relatively simple  
transformation to a set of destructuring forms is probably pretty  
straightforward -- I don't even think :as, :keys, etc would require  
any special treatment.

>> - The thing I don't like about the current type hints is (IMO) the
>> distracting quality of '#^'.  What about something like:
>>
>> (defh foo [String:s unhinted-arg {int:a :a}] ...) or
>> (defh foo [s:String unhinted-arg {a:int :a}] ...)
>>
>> That's far more visually-appealing to me, and has the nice advantages
>> of being inline in the case of destructuring and supporting sparse
>> hinting easily.  I'll bet the macro would end up being pretty simple,
>> as well.
>
> I'd hate to see somebody do it, but it's currently valid to define
> variables with colons in them, so there could be code out in the wild
> with those definition forms already.  Other than that, I like the
> looks of it.  I think the macro would be easy as well, so long as
> you're comfortable munging variable names :)

Well, that's one benefit/motivation to just have another def form,  
rather than trying to make defn support everyone's preferred variation/ 
style.

I knocked out a quickie implementation that appears to work with the  
couple of use cases I've thrown at it so far (pasted at the end of  
this msg).

Just a little exposition:

com.snowtide.clojure.utils=> (binding [*print-meta* true]
                                (prn (macroexpand '(deft a [Long:a b  
{[Integer:c] :c} {:keys [Double:d]}] (+ a b c d)))))
(def #^{:arglists (quote ([#^Long a b {[#^Integer c] :c} {:keys  
[#^Double d]}]))} a (clojure.core/fn ([#^Long a b {[#^Integer c] :c}  
{:keys [#^Double d]}] #^{:line 159} (+ a b c d))))

I *think* I've gotten the :tag metadata right (which I've burned  
myself on before, e.g. putting Class objects in :tag slots instead of  
symbols, etc), as this fn compiles without reflection warnings:

(deft a
   [String:b [Double:c :as java.util.List:list] {java.util.Random:d :d}]
   (.toCharArray b)
   (.size list)
   (.floatValue c)
   (.nextInt d))

A couple of nice things about this:

- it doesn't interfere with 'normal' type hints (e.g. #^Foo and Foo:b  
can coexist in the same declaration if you want to be silly about  
things)

- I think this kind of hinting could be bolted right into the existing  
destructuring functionality if Rich were so inclined (though I  
wouldn't bet on that).  This would allow you to use Foo:bar hints in  
any binding-form (e.g. let, fn, for, etc etc).

Cheers,

- Chas

-----------
(defn- decorate-hinted-symbol
   [sym]
   (let [[type arg] (.split (name sym) ":")]
     (if arg
       (with-meta (symbol arg) {:tag (symbol type)})
       sym)))

(defn- decorate-hinted-args
   [args]
   (cond
     (vector? args) (vec (map decorate-hinted-args args))
     (map? args) (into {} (map decorate-hinted-args args))
     (symbol? args) (decorate-hinted-symbol args)
     (keyword? args) args
     :else (throw (Exception. (str args)))))

(defmacro deft
   [name args & body]
   `(defn ~name
      ~(decorate-hinted-args args)
      ~...@body))

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to