I'm looking into whether wrapping more Go packages (e.g. net
) would be feasible, as it seems like some of them would be useful to me. "Raw" wrapping (whatever that actually is; TBD) might be in the form of packages named <http://joker.go.XXX|joker.go.XXX>
, e.g. <http://joker.go.net|joker.go.net>
, joker.go.net.smtp
, etc. More-elegant, Clojure-style, wrapping packages could then be provided, perhaps by just adapting stuff that's already out there in Clojure land.
I'm thinking of something lower-level that would be automated, so we can write higher-level Joker packages (without necessarily changing the Joker executable itself) at our leisure and install them in classpath (whatever that turns out to be).
So the names of these lower-level functions would be Go-style, not Clojure-style -- e.g. <http://joker.go.net/LookupMX|joker.go.net/LookupMX>
rather than <http://joker.go.net/lookup-MX|joker.go.net/lookup-MX>
or similar.
I'm not yet up to speed enough to know what to do with types and such, but might find time to look into that in the next couple of days.
Anyway my thinking is that this automation would allow us to easily add much of the Go runtime to Joker itself.
(I'm also not sure offhand how easy it would be to support different Go releases -- so, depending on which version of Go was used to build Joker, only the corresponding APIs would be built in.)
(And of course I don't want any of this to adversely affect Joker's startup time, or really even its VM consumption....)
I think dealing with custom type is going to be a challenge, but by all means feel free to give it a try. I am curious what a solution could look like.
I have tons to learn in this whole area; but, absent Joker support for deftype
, thinking about LookupMX
in particular, I wonder how far we could get with just returning hashes, e.g. { :Host "<http://smtp.example.com|smtp.example.com>" :Pref 10 }
(so <http://joker.go.net/LookupMX|joker.go.net/LookupMX>
would return a vector of those, since LookupMX
returns []*MX
)?
That (by itself) doesn't answer the question of whether or how <http://net.MX|net.MX>
itself (as a type) would be made available to Joker code....
I'd like to better understand what types could/should look like in Joker before going down this path, though. Would it make sense to support deftype
, maybe defrecord
, and the like first? I don't know enough about them (or Joker internals) to say, at this point.
Ideally all this would be nicely supported by autocomplete and whatever other code-writing/REPL-interacting goodness is available.
All good questions. I've been thinking about adding defrecord
/ defprotocol
support to Joker, but I am not sure it's required (or useful) for automatically generated bindings. In theory all the custom types (Go structured) could be represented as maps in Joker land...
This is extremely preliminary (not nearly ready as a PR, has nothing particularly useful, and changes generated doc files, which we don't want), but it represents my baby steps into figuring out how to automate this stuff: https://github.com/jcburley/joker/tree/test-mx-lookups
But it does at least accomplish this much:
$ ./joker -e "(require '[<http://joker.go.net|joker.go.net> :as n]) (println (n/LookupMX \"xyzzy.noway\"))"
ERROR OBJECT: lookup xyzzy.noway on 127.0.1.1:53: no such host
$ ./joker -e "(require '[<http://joker.go.net|joker.go.net> :as n]) (println (n/LookupMX \"<http://burleyarch.com|burleyarch.com>\"))"
$
Next, I'm going to figure out how to get LookupMX()
to return a vector of maps (as described above) so we can have actual results.
I don't think that's suitable for a PR either -- want to get more stuff figured out an automate doing all of net
and other useful libs. Just wanted to start somewhere between stupid-easy and crazy-hard, and a simple MX lookup seemed like a good candidate.
Looks good so far! I think doing low level one-to-one bindings in http://joker.go.xxx namespaces only makes sense if we somehow fully automate the process. If we still have to write some Go code, we might as well expose higher level Clojure style API (which is what I've been doing so far).
Exactly -- that's my goal, and I'll do only the <http://joker.go.xxx|joker.go.xxx>
stuff as fully automatable.
BTW I plan on copying our discussion here into an Issue on joker's github, so we have a record of it, and can continue discussing it there. Started here only because I wasn't sure it was worth an Issue there....
Do you have any thoughts as to how this might best wrapped, though?
// LookupMX returns the DNS MX records for the given domain name sorted by preference.
func (r *Resolver) LookupMX(ctx context.Context, name string) ([]*MX, error) {
return r.lookupMX(ctx, name)
}
I.e. having *Resolver
as a receiver type (or whatever Go calls it), so Joker code can access it and have a choice other than DefaultResolver.lookupMX(context.Background(), ...)
?
(Not that I think it's needed per se, but am looking to cover as much functionality as possible via automation, and I don't know offhand what a wrapper like the above would look like in Joker, or even Clojure generally....)(Should the github have a Project board, I wonder? I don't have much experience with those -- but I've used Jira in the past....)
Just want to say how much I appreciate joker. so far I only used it to block facebook ips in my host files but still :) keep up the good work everyone
Does all that make sense? Or am I barking up the wrong tree here?
(Ideally much of the work would be automated via a Joker script, akin to how code is already generated. I've written such automation many times in the past, so would be happy to volunteer to do it.)
that's pretty much what I've been doing for namespaces in std directory. Some bindings are trivial to implement (for example: https://github.com/candid82/joker/blob/master/std/string.joke#L74-L79 doesn't need any Go code at all), but as soon as you need custom type (like TCP connections, for example), it becomes more involved. I've been thinking about ways to make it easy to write bindings for any go module, but not sure it's possible...