I thought it was pretty easy to use Racket libraries (except for macros). When I wrote Anarki's libs/ns.arc, I had trouble, but not this kind of trouble. However, I guess I never really tried to add imports to ac.scm. What do you mean by "it doesn't seem to work"?
It could be that I'm working off a codebase that is missing some functions which Anarki uses to do that (I'm going through and comparing them now). When I try simply xdefing functions from libraries I get errors like "Expected 0 arguments with optional arguments X Y Z and got (args)"
"rocketnia's concern I addressed by passing through unknown keyword args unchanged"
The reason I'm okay with this approach is because it localizes the complexity to each function. This way I don't dislike the language; I just dislike the idioms currently being used in it.
Consider the use of flat text formats for shell scripts, HTTP headers, CSS properties, XML attributes, etc. They're usually convenient enough to type out manually, and that also makes them convenient to generate in simple cases, but writing a parser for them can be tough due to the same syntactic sugars that made them convenient to generate in the first place. Writing a full-featured generator or parser can also be tough, because sometimes future versions of the text format may allow it to encode more information.
With keyword arguments, the syntax for a function call is more complicated and sugary, putting programmers like me in the position of wondering what kind of headaches they should go through to parse or generate this format. If the headaches are unclear, combining programs becomes hard, because each developer might opt for different headaches, at which point I think they overlap in the form of complex glue code. :)
I have a greatly-enhanced respect for this perspective over the past month. Look at my travails over the past day trying to get optional, keyword and destructured args to play well together: https://github.com/akkartik/arc/compare/342ebf57a8...e347973.... Or my travails over the past month trying to build macex in wart in the presence of optional, keyword and destructured args AND quoted AND aliased params AND already-eval'd args[1] AND incompletely-eval'd args[2]: https://github.com/akkartik/wart/compare/30025ee25c...cabaa0.... Clearly there's some point at which I jump the shark :)
[2] related to partial eval: https://github.com/akkartik/wart/commit/8239ed9d21. I've been struggling intermittently with partial eval for two years now. This now year-long attempt might well be utterly useless.
---
Perhaps the easiest to understand and most serious extant example of the knots I end up tying myself into:
arc> (iso :x :x)
nil
This is because x is one of the params of iso. Even more serious, this happens even if you try to compare a variable that evaluates to :x. Or a variable that evaluates to a large structure containing :x somewhere in it. Ugh! The reason for this is that I'm extracting keyword args at function-call time inside each function. This:
It took me three years to notice yesterday that I'm extracting keywords from post-evaluated arguments. Ugh! Urrrgggh!
Weird thing is, even wart has this problem. Even though I would superficially seem to be extracting keyword args pre-evaluation. I still need to debug this. Or perhaps I shouldn't debug this. Perhaps I should just throw up my hands and delete all my repos and become a hermit.
That doesn't seem too bad, IMO: if your sym uses ssyntax chars you can't use it in ssyntax. There's probably worse corner cases I haven't considered, though :/
It sounds like what you like to see are s-expressions that fit these patterns:
homogeneous list of any number of X
fixed-length heterogeneous list of (X Y Z)
expression... which fits one of these patterns:
atom
call to X with args Y
Arc and Clojure make this more complicated by adding more cases, and I'll highlight Clojure's cases here:
map from X to Y
homogeneous vector of any number of X
vector alternating between X and Y, with no excess (like a map)
call to 'cond with args alternating between (expression) and
(expression), with no excess
call to 'case with args starting with (expression), followed by
alternations between (anything) and (expression), perhaps with
(expression) as excess
function body which might begin with a docstring and/or a metadata map
destructuring syntaxes
...
Between Arc and Clojure, I'm pretty sure Arc is intrinsically harder to auto-indent, because it doesn't distinguish between different cases using different kinds of brackets. Racket's a great example of what I mean; parens are used when the subsequent lines should be indented like function arguments, and square brackets are used otherwise.
For structured editing -- what you pursue -- we probably want even more static structure than what we want for auto-indentation.
I don't want to prod you to spend your time writing tools for niche languages or designing niche languages of your own, if that's not what you already want to do, but I'd like to ask what kinds of hypothetical languages you would like best....
Would you be eager to work with a lisp-like language where the AST has a few built-in notions of homogeneous lists, heterogeneous tuples, function calls, etc.? For instance, Lark defines an alternative to s-expressions that's more tailored to the ways the syntax is actually used (https://github.com/munificent/lark).
On the other hand, would you be eager to work with a language where the AST has an endless variety of possible cases, which can be extended by any programmer who wants to write an editor widget? Racket does something related to this, because it has an expressive pattern language for writing macros, and macros written this way generate good parse errors automatically (http://docs.racket-lang.org/syntax/Parsing_Syntax.html).
Personally, I've been kinda dreaming about both of these approaches to structured editing for a long time, but I'm still working on the run-time and link-time semantics of my language designs, so I've been unambitious when it comes to editing-time semantics. :)
"Though Clojure's mixture of Arc 'if' and optional types is a whole new level of unholiness."
Is this what you meant instead? "Though Clojure's 'let', which mixes Arc's 'withs' with type hints, is a whole new level of unholiness."
Even so, I think Clojure's 'let doesn't actually have any[1] added complexity when it comes to type hints. It might look like the list is bunched into groups of either two or three depending on whether a type hint is present...
(let [^String x "x string"
y 2]
(body-goes-here))
...but that's not a quality of 'let. That's a quality of the ^ syntax. An occurrence of ^ consumes the next two s-expressions, just like ' consumes the next one s-expression:
So the bindings of a 'let are consistently bunched into groups of two s-expressions, just like Arc's 'withs.
[1] Of course, the type hints are actually used for optimization at some point, so the complexity of parsing them has to go somewhere. This is exactly as complex as destructuring: Arc's 'withs syntax supports destructuring, but it doesn't need special-case destructuring logic because it just translates down to 'fn. As it happens, Clojure's 'let syntax also supports destructuring, and it probably uses the same general technique.
Yes! Turns out I didn't notice the switch from if to let.
I have to say, though, I have no sympathy for the argument that it's still groups of two s-expressions. As a reader it's still more onerous to have to mentally group:
^a b
compared to:
'a
So the presence or absence of parsing complexity feels irrelevant.
"Did you try changing the definition of open-socket that you found, adding a fourth argument with the right IP address?"
I think that's exactly how to make this work (albeit hackishly). Here's the code for that, but note that I haven't actually tried this out:
(xdef open-socket
(lambda (num)
(tcp-listen num 50 #t (getenv "OPENSHIFT_DIY_IP"))))
I've done some OpenShift experiments using a Node.js cartridge; I'm not engrossed enough for a DIY cartridge yet. :) It's nice as a freemium host for long-running servers, so getting news.arc to run on it would be pretty exciting.
---
"...and I've never heard of a server needing to know its own IP address."
This isn't its own IP address; just looking at the way this needs to be used, it's the a IP address of a reverse proxy. I assume this is so the OpenShift cloud can easily hibernate and migrate these hosted servers while it does its own load balancing and maintenance.
"But the second part is bad, I think: the elements inside l should stay the same."
I agree. I really think this is a simple coding mistake in ac.scm. I talk more about this here, a reply to that thread you linked to: http://arclanguage.org/item?id=17114
I completely forgot about this difference between + and 'join after that thread, and I don't remember encountering it before that either. How fitting it's a testing framework that brings this bug to the surface! :-p
There's actually another function, 'join, that just appends lists.
(join (list 1 2 3) (list 4 5 6))
A while back, fallintothis and akkartik talked about this a little: http://arclanguage.org/item?id=11104 (Look for "prefers" and "over time" on the page.)
Just in case... which version are you trying to install?
You mention "MzScheme," but don't let the arclanguage.org front page fool you. Arc works on up-to-date versions of Racket, not just the old MzScheme 372. See https://sites.google.com/site/arclanguagewiki/ for more comprehensive installation information.
I see some useful-looking Web search results for [Racket on Raspberry Pi], and they're much more recent than 2007.