In addition to zck's points: obj is built using listtab, and there's several cases in arc where 'internal' helpers are not distinguished from the external interface. That gives users the option to use it in the rare situations where it's more helpful.
"The next one refers to s and str as well. Is that intended?"
Yes. Only <s> appears in the pattern itself, but the meaning of <str> is explained by "...where <str> is the string name of the symbol <s>."
---
"Also, I don't follow the distinction between the string case and the symbol case."
Did you see this part? -- "(That may look simple enough, but a completely different symbol pattern applies when matching a list element. See below.)"
A symbol which occurs in a list acts as a hybrid keyword/positional argument. A symbol by itself acts just like a string.
---
Sorry I'm being terse with this stuff. I found it hard to express my points in informal English, which is why I went with a spec document style in the first place.
Let's see...
My motive is to show you a way your desired features can be accomplished in an extensible ravioli style, rather than one big chunk of spaghetti. What you want is achievable with a simple enough collection of parser combinators, although sometimes their interfaces may be unusual due to expression evaluation being part of the parsing process.
For instance, in the system I gave, the parser combinators use a few unusual design patterns:
- The combinators must take in an evaluation environment.
- The combinators frequently quote a value so they can pass it off to another combinator that may eval it again. (I think I've seen you use this style before, actually.)
- The combinators must sometimes return the evaluated expression, just so that the (<a> | <b>) pattern can avoid double evaluation.
Another important point I'm making is that you probably don't need to reorder the argument list for the purposes of keyword arguments. My system instead (effectively) reorders the parameter pattern so the keywords are processed first.
I got this system a bit wrong because I don't support multiple keyword aliases for the same parameter. My (<a> | <b>) pattern instead binds multiple parameter variables to the same argument value, so I got that backwards.
This seems really useful. I got the motivation off the bat, but I still don't understand the spec. Can you give an example session showing how functions are defined, and how they are called?
'(a b) ; the parameter list
(a b) ; the args to (list ...)
((+ 1 1) (+ 2 2)) ; the args to (foo ...)
((+ 1 1) (+ 2 2)) ; the result
(baz)
(baz)
((+ 1 1))
; Error! Can't make the function call (2).
'(a b c)
(a b c)
((+ 1 1) :c (+ 3 3) (+ 2 2))
((+ 1 1) (+ 2 2) (+ 3 3))
'(a :b b c)
(a b c)
((+ 1 1) (+ 2 2))
; Error! Unbound variable b in expression (list a b c).
So I have some more kinks to work out, lol. I finally appreciate your predicament. :)
The (baz) issue is caused by the complexity of the fact that in a normal function call, each of the arguments should be evaluated, but the list of arguments shouldn't. So if the traditional Arc parameter list (baz) is a pattern, it should destructure an unevaluated list in such a way that the baz pattern inside operates on an evaluated version of the list's first element.
It would be a lot simpler if we wrote this argument list differently:
> (def foo (baz) ...) ; doesn't work
> (def foo `(,baz) ...)
> (def foo (arg-list baz) ...)
; where (arg-list ...) is a pattern special form
I think that last one is promising, because then we can just write (baz) and the macroexpansion of (def ...) can insert that into (arg-list baz) for us. Then we get to have slight differences between how parameter lists work and how list destructuring works.
As for the "unbound variable b" issue, I think that could be solved by having each pattern take an optional current expr, rather than a mandatory one. My exact implementation of this would probably vary substantially based on what else I was trying to do. I might want a guarantee of which variables will be bound by a pattern long before there's an actual argument list to match it against, for compilation purposes and such.
By the way, I discovered it with my tool, which I'm writing in Arc to learn this language. This tool crawls GitHub starting from Anarki repository, to find other interesting projects, written in Arc.
I think all the errors you're seeing are due to running out of heap. How much memory do you have? Is there some per-process limit, perhaps to RLIMIT_AS?
Edit 35 minutes later. I can reproduce that it dies for me at the precise same iteration as you. And RLIMIT_AS is infinity, so that's not the issue. I've pinged the author for comment.
Thank you. But now I think it would be wise not to complain about the issue on the forum, but rather to create an issue on the project's github. Will do it now.
Well, thanks for the bug report. Well, I'll look into it when I have the time: the work which pays my bills has caught up with me once again and I don't have a lot of time to do hobby development. :)
The assertion error is a stack overflow. :) At present Arcueid makes use of a fixed-size stack within its virtual machine, and since the compiler still can't properly optimise tail recursion, your code overflows the stack.
That was what I thought :) Is there a place where I can increase the size of the fixed stack? I looked for the limit in the code, but couldn't find it.
Does it make sense to resize it on the fly when we discover we've overflowed the stack? Or are there potentially continuation pointers into the stack that would be non-trivial to track down?
Well, I haven't tried to run crawler with large depth setting yet. I discovered, that it have strange problems with threading and almost unable to process in parallel. Then I tried to investigate why. Will make a separate post on it, when will get some valuable information.
I don't know how to answer it :) There's a lot of code in the world. I can help answer questions on some of it, but I have no idea what's most promising.
I upvoted you because I was happy to see the list, and I'd be interested in other people's answers.
Well, probably I should ask another question, addressed to the different implementations' authors: "Why do you started to write your own implementation instead of making efforts to improve Anarki?" :)
If pg ever contributes a line of code to anarki I'll eat my hat :) Not that that's a bad thing; it works perfectly well for each side to port changes from the other.
That probably explains the error message. (Quotes expand to the symbol quote.)
So all you have to do is not quote your argument:
arc> (inl 1 (1 2 3))
t
As a general rule, however, try not to use a macro unless you have to. In this case there's a pure function that does what you want:
arc> (pos 1 '(1 2 3))
0
arc> (pos 4 '(1 2 3))
nil
(You can use pos in a conditional just like inl because it is guaranteed to only return nil if and only if the element doesn't exist.)
More info: http://arclanguage.github.io/ref/list.html#pos. As an exercise try implementing pos for yourself :) And feel free to ask us more questions! I hadn't realized there were questions at stack overflow. I'll try to hang out there, but there's really nothing off-topic here.
I think it might help to point out how the macro expands there:
(inl 1 '(1 2 3))
is transformed by the reader to
(inl 1 (quote (1 2 3)))
which is then macro expanded by
`(in ,elt ,@lst)
where elt is bound to '1, and lst is bound to '(quote (1 2 3)). This means that when lst is spliced in, you get:
'(in 1 quote (1 2 3))
As stated, the problem is largely the choice of macro instead of function. Macros are primarily useful to control evaluation; they do not evaluate their arguments by default. A macro will only let you work with the literal input, not their values. You can't (with arc) have your cake and eat it too; you can only work with either the syntax, or the values. You wouldn't be able to do something like:
(let x '(1 2 3)
(inl 1 x))
for instance, because it would attempt to treat the symbol 'x as if it were a list to be spliced, not the value of x. That's why you need a function, like pos.