(1) This one I think is the right decision. The real constructor is, after all, cons; and in fact, (is (type:cons 'a 'b) 'cons) but (isnt:alist:cons 'a 'b), since cons is more generic. Being a list is a property that certain sets of cons cells have, but it isn't their type.
(2) Again, I think this is the right decision. The point of obj is to be convenient in the simple case where you're building an object-like hash table: one with fixed fields and changing contents. I feel that table should probably take arguments like obj but without quoting (so that (obj a 1 b 2) would be (table 'a 1 'b 2)), but obj is still handy to have around.
(3) Ah, car/cdr versus first/rest. There's not really anything I have to add to this one, other than that I like the conciseness and composability. I've also seen fst and rst proposed, so that you can do frst for first:rest; make of that what you will.
(4) Yes, this is annoying. The rationale is the same as in the obj case, but I very often want to compare to non-symbols.
(5) If we accept that association lists are really just lists which have a certain structure, then we can't use special syntax, etc., as that already means something for lists. What if you have (= a '((1 a) (2 b))); would a.1 be a (since it's an association list) or b (since that's element 1 of the list)? I would also argue that the point of association lists is to be lists with special structure; if you want something like that that's its own type, that's what tables are for.
(6) I haven't really used deftem, but it does define a template; you create them using inst. On the other hand, obj creates the table right there.
I should say, by the way, that I don't think Arc is a perfect language by any means. Its bizarre naming conventions come to mind, for instance. But I happen to think many of these are non-issues (though I would be perfectly open to being convinced otherwise).
Ok I can see this. Thank you for pointing this out, but I still don't see why it can't be type list.... list is more intuitive.
>(2)
I don't see how obj is convenient when you can't pass in functions, or when new users have to remember "use symbol here - oh but not here, or there when this case is true" - reminds me of i before e but not after c. Shouldn't a goal of language design be to prevent these kinds of things and focus on promoting language adoption / ease of use ?
>(5) "I would also argue that the point of association lists is to be lists with special structure; if you want something like that that's its own type, that's what tables are for."
The only use I can see for an association list is to have a key/val pairs structure that maintains order; Which tables do not. Otherwise I think alist would be dead. They don't have to be called "list" or "table" call them "directories", "catalogs" - whatever... I think there's an ease of use benefit having users being able to use the same tools in the "alist" as they do tables.
>(6) "I haven't really used deftem, but it does define a template; you create them using inst. On the other hand, obj creates the table right there."
makes sense. it's probably just related the other post... ie. why is it called obj? creates confusion.
===
Everything is a trade off. I'm not suggesting the justification as to "why" doesn't have merit, I'm suggesting Arc should try leaning more towards audience adoption and being more intiutive rather than being so strict that we care about each token, or having to be absolutely technically correct. Or to carry forward bad concepts from languages that are not well adopted even when more powerful.
>...I still don't see why [(cons 'a 'b)] can't be type list.... list is more intuitive.
Traditionally, there's a distinction -- if only in discussion, and not code -- made between nil-terminated conses and a cons with another terminator. If and only if a cons is nil-terminated, it's a list. Otherwise, it's simply a cons.
Making the distinction would be difficult. Right now, type just has to call pair? to check whether it's a 'cons. To have both list and cons types would require iterating down until you hit the end of the list every time type is called. I'm not sure having both types is useful. It might make things more complicated.
That makes sense. I just wonder if were living with the distinction because of the implementation or if the implementation could change so that distinction could go away?
As I observed above (http://arclanguage.org/item?id=10528), table can't do this (unless we rotate names around, which would be a perfectly valid option), but here's a lightly-tested macro (with a terrible name) which exhibits your DWIMmy behaviour:
Yes, and you are an awesome person for doing that. However, I don't think anything "official" links to arcfn.com, so finding it is a bit difficult. And of course you haven't documented every single one of the bajillion little changes on Anarki, because you are a human being and need sleep.
I avoid using anarki - after finding numerous problems running code that works with the official pg branch. And trying to understand what anarki is doing to my code when there's little documentation - it's like having a brain seizure - noob style ;).
There's a reason anarki has a stable branch. Of course, it's horribly out of date now, which is why I'm (still) working on porting some of the old arc2 anarki's more useful features to arc3, without the cruft. (The delays have mostly been caused by me dithering on what the best way of handling CatDancer's idea of keeping hacks separate is; I have most of the actual features I wanted to port done already.)
More accurately, a) I haven't ported it to arc3 and b) it hasn't shown up on anarki's arc3 branches last I checked. If anyone else has ported it, I'd be interested to know.
Your 'every example is very very attractive. I think I'll adopt it at this point:
1. It does the job without problematic cases, like there would be in what I describe:
(with (lst '(1 2 3)
v 3)
[...]
(myidealeach v lst (prn v))) ; <-- v mistaken for the seq to traverse here,
; because it is defined
2. OK, it adds some syntax and this is bad, but for the common case where I'd like an implicit '_ variable, it's as short as possible!
3. For the other cases, the extra "in" is not so heavy, and in a way it makes the expression more readable!
Thanks a lot absz!
----
For the rest:
> anaphoric each
Yes, a good idea but I don't like to have two loop constructs where one could suffise. Currently, I'm using something like that (I have a 'each_) but this sucks IMO.
However, interesting that you choose to use 'it' and not '_'. It makes me realize, maybe it would be better if there was only one of the 2, there are a bit redundant aren't they?
(aif (car a) (prn _))
; I like this, because "_" is more visible than "it", less likely
; to be confused with a "normal" variable, and less english-centric
Or:
([* it it] 2) ; hmmm don't like that so much actually
This is pure personal taste however.
In the same way, this is also personal taste, but I mention this because an American/British people may not think about this kind of stuff.
I prefer "list?" over "alist" because anyone used to the latin alphabet will quickly understand what it does (and even this is not the majority of people...).
True story, I didn't understand what "acons", "alist" mean when I first looked at Arc (I'm French), while the Scheme way to name predicates was obvious at first sight.
> CL's loop
Ouch I'd really not copy 'loop too much however.
In a way, it is a good construct, I mean it is very powerful, but I can never remember of the syntax to do basic things, and this is why I prefer the Arc way here.
'loop is really a DSL in itself.
As for the it/_ question: I hadn't noticed until writing my post that _ and it (and self in afn) were serving similar purposes; I don't really know which one I like more, though that's not something I care heavily about. (My feeling about the English-centricity problem is that if everything else in the language is already in English---if, each, and, etc.---then changing it to _ probably wouldn't make a huge difference.)
As for the function-naming issue: I also prefer the Scheme naming convention, though not for multiple-language reasons (I'm an American [mais je peux parler Français]); that's an aspect I hadn't thought of. (The a-predicate versus anaphoric thing is already annoying.) Internationalization of programming languages is a hard problem that I don't think anybody's tried to tackle, and I'm not sure how tractable it is---it would be interesting to see a language or framework which tried to explore that design space. The obvious approach is something like
(mac si (c v f) `(if ,c ,v ,f))
(= chaque each)
; etc.
The downside is that this only internationalizes the core; any library still has to support these synonyms or have a translator, and so I'm not sure how big the eventual gain is. (I think AppleScript had this once, but since applications didn't support this, that feature died.)
In my opinion (and I've barely used CL), loop is a brilliant piece of code because it's a great little DSL for iteration; at the same time, also having simpler alternatives, e.g.each, available is really handy because that way you don't need to know everything loop can do all the time.
> then changing it to _ probably wouldn't make a huge difference
I also don't think it would be a huge difference for non-english programmers, although it may be a little win. But for my case, I don't prefer "_" just because of that. I'd say, the main reason is that "_" is more easily recognized by my parser (aka brain) as a special variable than "it" because it is an uncommon glyph. "it" gets lost in the flow of the program.
> I'm an American [mais je peux parler Français]
Now, that is not common and that is cool. I mean, not that you know how to speak French, but that you know how to speak a foreign language.
Those who know no foreign language knows nothing of their mother tongue. -- Goethe
It's not a coincidence that Larry Wall (Perl creator) studied linguistics...
> that's an aspect I hadn't thought of
Well in this case I can go to sleep happy, knowing I made you aware of something new ;-)
> a-predicate versus anaphoric thing is already annoying.
Yes! When I realized 'acons & the like were predicates, well I thought 'afn was, too...
> loop is a brilliant piece of code because it's a great little DSL for iteration; at the same time, also having simpler alternatives, e.g. each, available is really handy
Totally agreed. 'loop is something great to have as a library or something, but if it's the only way you have to do basic iteration, well, it sucks IMO. Because in top of knowing CL you have to know the 'loop stuff, which is completely different. Gosh, writing this message I realize I don't even remember how to iterate over a list while printing its elements. But yes, 'loop is extremely powerful.
Anyway, thanks once again absz, your message was really interesting to read!
The brackify function returns the closure [+ openb _ closeb]. The [... _ ...] notation means "construct an anonymous function of one argument, _"; it's the same as (fn (_) (... _ ...)). Thus, (brackify "(" ")") returns a function of one argument which, when called, surrounds its text with "()"; the text given is "adm".
The downvote buttons have been there for quite a while for me---you seem to have just broken 100 karma, so maybe it's because of that?
What you said is correct; the only problem is that with the numbers you quoted, the total probability of rolling a number in the range [0,10) is 2/16 + 1/16 = 3/16 < 1 :) The numbers you meant to quote, as borne out by your data above, are a 10/16 = 5/8 chance to get a number in the range [0,5), and a 6/16 = 3/8 chance to get a number in the range [6,10). (Equivalently, a 12/16 = 3/4 chance to get a number in the range [0,5] and a 4/16 = 1/4 chance to get a number in the range [6,9], but since that doesn't partition the [0,10) range evenly, it's less instructive.)