The error "Invalid cross-device link" happens if you're trying to move a file across partitions. Apparently sometimes people have set up their home directory in a separate partition, even without realizing it.[1] So I'm guessing you're in a situation like that.
Other languages seem to recover from this particular error and do a copy and unlink instead:
Racket's reference for 'rename-file-or-directory states that it can move files to other paths "on the same disk"[2], and it goes into detail about atomicity guarantees, so this behavior is probably by design.
So the way you can find resolution here might be:
- Somehow change what temp directory Arc uses.
- Put the Arc directory elsewhere on your filesystem.
- Somehow change your partitions so the home directory and temp directory are in the same one.
- We should probably update Arc to recover from this somehow. :)
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?
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.
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.
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. :)
Also, it looks like you're new here. Welcome! Feel free to post any questions or thoughts about Arc; this forum is really welcoming to newcomers, and I'd like the community to grow bigger.
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.
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.
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.
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.
'(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.
I found another mistake I made. In the two rules that use <before...> and <rest>, that <before...> should be used whenever the rule matches the remainder of the expr.
In particular, for symbols to work as positional args whenever there isn't a keyword, the symbol rule needs to fall back to (<before...> <str> ... <rest>), reflecting the original location of the symbol in the pattern. I just had it falling back to (<str> ... <rest>) for some reason.
---
(<before...> <k> <v> ... <rest>)
; where <before...> is any number of non-keyword, non-symbol
; elements; <k> is a keyword; and <rest> could be anything,
; especially an improper list
This pattern treats the current expr as an unevaluated improper list, looking for the first occurrence of <k> with another element after it (which we will refer to as the value expr).
If the keyword binding is found: Matches <v> against the value expr. Matches <rest> against an alteration of the current expr, changed to remove the keyword and the value expr. Uses all variable bindings produced by <v> and <rest>, preferring the bindings in <rest>.
If the keyword binding is not found: Matches the pattern <rest> against the entire expr. Uses those variable bindings.
(<before...> <s> ... <rest>)
; where <before...> is any number of non-keyword, non-symbol
; elements; <s> is a symbol; and <rest> could be anything,
; especially an improper list
Let <k> be the keyword with the same name as the symbol <s>, and let <str> be this name as a string.
This pattern treats the current expr as an unevaluated improper list, looking for the first occurrence of <k> with another element after it (which we will refer to as the value expr).
If the keyword binding is found: Matches <str> against the value expr. Matches <rest> against an alteration of the current expr, changed to remove the keyword and the value expr. Uses all variable bindings produced by <str> and <rest>, preferring the bindings in <rest>.
If the keyword binding is not found: Matches the pattern (<str> ... <rest>) against the entire expr. Uses those variable bindings.
---
After this fix:
---
(<before...> <k> <v> ... <rest>)
; where <before...> is any number of non-keyword, non-symbol
; elements; <k> is a keyword; and <rest> could be anything,
; especially an improper list
This pattern treats the current expr as an unevaluated improper list, looking for the first occurrence of <k> with another element after it (which we will refer to as the value expr).
If the keyword binding is found: Matches <v> against the value expr. Matches the pattern (<before...> ... <rest>) against an alteration of the current expr, changed to remove the keyword and the value expr. Uses all variable bindings produced by <v> and (<before...> ... <rest>), preferring the bindings in the latter.
If the keyword binding is not found: Matches the pattern (<before...> ... <rest>) against the entire expr. Uses those variable bindings.
(<before...> <s> ... <rest>)
; where <before...> is any number of non-keyword, non-symbol
; elements; <s> is a symbol; and <rest> could be anything,
; especially an improper list
Let <k> be the keyword with the same name as the symbol <s>, and let <str> be this name as a string.
This pattern treats the current expr as an unevaluated improper list, looking for the first occurrence of <k> with another element after it (which we will refer to as the value expr).
If the keyword binding is found: Matches <str> against the value expr. Matches the pattern (<before...> ... <rest>) against an alteration of the current expr, changed to remove the keyword and the value expr. Uses all variable bindings produced by <str> and (<before...> ... <rest>), preferring the bindings in the latter.
If the keyword binding is not found: Matches the pattern (<before...> <str> ... <rest>) against the entire expr. Uses those variable bindings.