Arc Forumnew | comments | leaders | submit | fallintothis's commentslogin

/dev/urandom is a special file in Unix-like operating systems that spits out random bits (see http://en.wikipedia.org/wiki//dev/random). Arc isn't so great at the cross-platform thing, since it hard-codes Unix-like paths & shell commands. In this case, srv.arc breaks when trying to generate a random string because it calls rand-string from arc.arc, which tries to open /dev/urandom to get random data. The file doesn't exist in Windows (and just creating one won't do the job, since Windows doesn't say "hey, I know, I'll generate random bits when people read from this file"), hence the error.

This was discussed awhile back in a thread that has some fixes for other Windows issues: http://arclanguage.org/item?id=9263.

-----

1 point by Andrew_Quentin 5543 days ago | link

Hey. Thanks a lot for your reply. Are you speaking of this solution: http://jfkbits.blogspot.com/2008/01/digging-into-arc-in-24-m...

It seems to work fine if you take off the 'before make directory, but what exactly do I do with dev/urandom in both ac.scr and arc.arc?

-----

3 points by fallintothis 5543 days ago | link

Are you speaking of this solution

Well, strictly I was speaking of the solutions in the thread that I linked to, but that blog post is about the issue they discussed.

It seems to work fine if you take off the 'before make directory

Yeah, those forum/blog posts were from quite awhile ago, when xdef expected its first argument to be quoted (see http://ycombinator.com/arc/tut.txt -- or any of the myriad other Lisp tutorials out there -- for an introduction to quoting).

but what exactly do I do with dev/urandom in both ac.scr and arc.arc?

I linked to that thread because it was relevant, though it didn't fix this specific bug: it's still true that pg expects Windows snafus to be fixed downstream. As rocketnia mentioned (http://arclanguage.org/item?id=12397), most seem to be solved by using Cygwin, which will give you /dev/urandom & such.

The outstanding issues I'm aware of are generally fixable outside of Cygwin, but would require a bit of code drudgery.

- The setuid bug, apparently fixed (by doing nothing when it's called, so I'm suspicious, but I don't know): http://arclanguage.org/item?id=10625.

- pipe-from in ac.scm runs rm -f, which could be replaced by Racket's delete-file wrapped in the proper error-catching code (http://docs.racket-lang.org/reference/Filesystem.html#%28def...). It also uses /dev/urandom to generate a random filename, but that could be replaced by Racket's make-temporary-file (cf. http://arclanguage.org/item?id=2333 and http://docs.racket-lang.org/reference/Filesystem.html#%28def...).

- shash in arc.arc just uses openssl, which has a Windows binary that should work. It worked a few years ago, anyway: http://arclanguage.org/item?id=190. shash also creates a file in /tmp/, but that shouldn't be an issue, if I recall correctly from the few times I've run Arc on Windows.

- ensure-dir in arc.arc has been patched in that thread I linked to -- again, just using Racket's functions.

- load-items in news.arc has

  (system (+ "rm " storydir* "*.tmp"))
which seems like it could be done with Racket's delete-file and find-files (http://docs.racket-lang.org/reference/Filesystem.html#%28def...).

- rand-string uses /dev/urandom, which takes a little more doing to fix, as evidenced by the lack of changes on Anarki (the community-maintained repository for changes to Arc: http://github.com/nex3/arc). You might could rewrite it to use Racket's random number generators, but I don't really know.

-----

4 points by fallintothis 5547 days ago | link | parent | on: Should cut work this way?

Arguably, no. cut uses firstn on lists, which works how you expected it to behave for strings, which is inconsistent.

  arc> (firstn 10 '(a b))
  (a b)
  arc> (cut '(a b) 0 10)
  (a b)
  arc> (cut '(a b) 200 10)
  nil
Of course, cut could just throw errors for out-of-bounds list indices, too.

-----

2 points by fallintothis 5556 days ago | link | parent | on: The use of + for non-numbers

String concatenation is particularly convenient after the + change for arc3.tar: http://arclanguage.org/item?id=9937. That's probably what I use + for most of the time.

I find thinking about whether or not I have to escape the "@" character is distracting

I find this is easier with proper syntax highlighting. My arc.vim ftplugin can detect if you have (declare 'atstrings t) and, if so, highlights the escaped parts of strings. That way, you know if @ is escaped just by glancing. But I don't mean to shamelessly plug, haha. I don't use atstrings either, but my reason is far lazier: in the middle of writing code, it's less effort to just use + than it is to declare then go back and start using @s.

-----

2 points by garply 5556 days ago | link

What other goodies does your arc.vim plugin have? Is your editor at all integrated with the arc repl? Lack of a repl that I could easily send arc code to was the reason I switched to emacs after years of using vim. These days, using emacs with viper (vim emulation mode), I don't miss vim at all.

-----

2 points by fallintothis 5547 days ago | link

Sorry, I'm not going to be the one to write SLIME for Vim. :P I'm afraid the only "goodies" I have are highlighting-related. Off the top of my head:

- It can detect macros that take rest parameters named body, then highlight and indent them correctly.

- It uses R5RS's grammar & mz-specific extensions to highlight numbers correctly -- even weird ones, like

  #e1.5
  -nan.0+2.5i
  1/2@+inf.0
  #x8a
  #o1E+2
- It notices paren errors involving [], like

  [(+ a b])
- It highlights escape sequences in strings, like

  "\x61b \t c\u0064\n"
- It does its best to highlight ssyntax characters so they're easy to read.

You can check out more at http://arclanguage.org/item?id=10147 or http://bitbucket.org/fallintothis/arc-vim. It hasn't changed much since I first submitted it, though I've noticed it fails to highlight 0-argument function names like queue and new-fnid. Been meaning to fix that for awhile.

-----

3 points by fallintothis 5556 days ago | link | parent | on: The use of + for non-numbers

if someone feels like showing me how to use a diff program to display the nice patch changes, please feel free

You mean like

  diff -u old-arc.arc new-arc.arc
or are you on Windows or something?

-----

1 point by waterhouse 5556 days ago | link

Aha! That works. Thank you!

-----

1 point by fallintothis 5560 days ago | link | parent | on: (map [string ".*" _] "test")

And, what would be a simple way to do what I'm trying?

Alternatively, there's

  arc> (string (map [+ ".*" _] (coerce "test" 'cons)))
  ".*t.*e.*s.*t"
which does (almost exactly) what (apply + ...) does, but is shorter. You could also avoid the lengthy coercion and go with

  arc> (tostring (each c "test" (pr ".*" c)))
  ".*t.*e.*s.*t"
Not that either of those is optimal.

-----

1 point by d0m 5560 days ago | link

Interesting solutions :D

There's also:

  (string (intersperse ".*" (coerce "..." 'cons)))
edit:

  (string ".*" (intersperse ".*" (coerce "..." 'cons)))

-----

1 point by fallintothis 5560 days ago | link

Except intersperse does it in the wrong order:

  arc> (string (intersperse ".*" (coerce "test" 'cons)))
  "t.*e.*s.*t"
By the way, for code that won't screw up asterisks, just prefix the line by two spaces. :)

Edit: Ah. Well, I suppose appending an extra onto the front works. Still not optimal, but oh well.

-----

1 point by d0m 5558 days ago | link

Finally, I've chosen to make a little macro:

  (let s "hello"
    (->s s 
      (map [+ ".*" _] s)))

-----

1 point by akkartik 5557 days ago | link

Can you elaborate?

-----

2 points by d0m 5557 days ago | link

This macro hide fallintothis' suggestion to my string-are-not-list problem. So basically it does:

  (def ->s (var . body) 
   `(let ,var (coerce ,var 'cons)
      (string ,@body)))
And now I can use:

  (let s "hello"
    (->s s
      (intersperse ", " s)))
  
  > "h, e, l, l, o"

-----

2 points by fallintothis 5557 days ago | link

Yet another option:

  (def map-as (type f seq)
    (coerce (map1 f (coerce seq 'cons)) type))

  arc> (map-as 'cons [+ ".*" _] "test")
  (".*t" ".*e" ".*s" ".*t")
  arc> (map-as 'string [+ ".*" _] "test")
  ".*t.*e.*s.*t"
  arc> (map-as 'cons [+ _ 1] '(1 2 3))
  (2 3 4)
  arc> (map-as 'string [+ _ 1] '(1 2 3))
  "234"
This works because of how coerce works.

  arc> (coerce '("a" "b" "c") 'string)
  "abc"
It deals with lists and strings well, which is decent: Arc's only other sequence-like type is the table (I don't think you'd ever want to treat symbols as a sequence of 1-character symbols; you'd just use a string). Tables would work better if they were properly coerced, cf. the comment above tablist and listtab in arc.arc.

The more I think about it, the more I like this model. Conceptually, it seems that map should behave like

  (def map (f seq)
    (map-as (type seq) f seq))
even if it's not implemented like that -- all the coercions would surely be slow. (Tangential: map would also need to handle multiple sequences.) But it makes more sense for map and coerce to at least have compatible behavior. Plus, map's current behavior is a degenerate case of the coerce-compatible map:

  arc> (map inc "abc")
  "bcd"
  arc> (map-as 'string inc "abc")
  "bcd"
so it's not like you lose functionality, and then this post's example would've worked to begin with.

-----

1 point by akkartik 5554 days ago | link

When you phrase it as map-as, it becomes easier to fit into my defgeneric/defmethod framework (http://www.arclanguage.org/item?id=11865). Thanks!

I've spent some time thinking about how to extend it for multiple-dispatch, and I didn't want to also think about setting the arg index to dispatch on.

-----

1 point by fallintothis 5560 days ago | link | parent | on: (map [string ".*" _] "test")

When you map across a string, it coerces the whole result into a new string character-by-character. It's like if you (hypothetically) weren't allowed to have nested lists but tried to do

  (map [list 1 2 3 _] '(8 6 7 5 3 0 9))
Each string element is a character, not a whole string. Thus

  arc> (= s (newstring 3))
  "\u0000\u0000\u0000" ; these are null characters, by the way
  arc> (= (s 0) #\a)
  #\a
  arc> s
  "a\u0000\u0000"
  arc> (= (s 1) #\b)
  #\b
  arc> s
  "ab\u0000"
  arc> (= (s 2) "foo")
  Error: "string-set!: expects type <character> as 3rd argument, given: \"foo\"; other arguments were: \"ab\\u0000\" 2"
But you can use map on a string for things like

  arc> (inc #\a)
  #\b
  arc> (inc #\b)
  #\c
  arc> (inc #\c)
  #\d
  arc> (map inc "abc")
  "bcd"

-----

3 points by fallintothis 5564 days ago | link | parent | on: File I/O Challenge

Otherwise, I think I'm satisfied with this code.

Never fear! I'll show up to flog this horse in the nick of time! Y'know, before rigor mortis sets in.

Here's another I/O utility I think would be useful.

  (def readlines (n (o str (stdin)))
    (let line nil
      (repeat n (= line (readline str)))
      line))
It undoubtedly sets a variable (just not a global), though I think the "challenger" phrased the requirement as such because of a C-centric view: allocate a chunk of memory for the string, then read the string into there (which, technically, even a simple (readline) does). Anyway... With all of these, the Arc code would look something like

  (tofile   "fileio.txt" (prn "hello"))
  (ontofile "fileio.txt" (prn "world"))
  (fromfile "fileio.txt" (prn (readlines 2)))
And I don't think I could squeeze more out of that without getting overly specific. Of course, readlines is a conventional name for something that just reads all the lines of a stream, but I think we could reasonably use names closer to Arc's allchars and filechars.

  (def all-lines ((o str (stdin)))
    (drain (readline str)))

  (def filelines (name)
    (fromfile name (all-lines)))
Not sure if the latter should be hyphenated, though.

-----

4 points by fallintothis 5565 days ago | link | parent | on: File I/O Challenge

Hm. Anarki calls them w/stdoutfile and w/stdinfile, but wouldn't tofile and fromfile be more consistent with tostring and fromstring (and shorter, besides)? Then there's the whole appending business. Can't really give an optional parameter to tofile like outfile has, and toappendfile runs together horribly. What about just appendfile?

Then, using readline instead of readfile so that it (1) doesn't try to parse things as s-exprs and (2) doesn't read the entire file for no good reason, I'd envision it thus:

  (tofile "fileio.txt" (prn "hello"))
  (appendfile "fileio.txt" (prn "world"))
  (fromfile "fileio.txt" (readline) (pr (readline)))

-----

1 point by waterhouse 5565 days ago | link

Excellent. Have added to my personal Arc library (which is a big fat file named "a", to which I keep appending things):

  (mac tofile (f . body)
    (w/uniq gf
      `(w/outfile ,gf ,f
         (w/stdout ,gf
           ,@body))))
  (mac fromfile (f . body)
    (w/uniq gf
      `(w/infile ,gf ,f
         (w/stdin ,gf
           ,@body))))
I'm not sure about the appendfile--given what infile and outfile do, it sounds like a procedure that creates an output-port that appends to a file. Maybe to-appendfile, appendtofile, appendingfile, tofile/append... Alternatively, we could make keyword arguments happen in Arc, and then you would just throw ":append t" or something inside the call to tofile. That would also allow for further extension with, e.g., an :if-exists argument.

-----

1 point by rocketnia 5565 days ago | link

How about 'tolog? Are files opened for appending for other reasons, in practice? This would also keep with the to-means-output, from-means-input pattern.

-----

2 points by fallintothis 5565 days ago | link

I'd try to err on the side of generality. And I'm not quite as concerned about to:output / from:input, if the names are still "clear enough".

As to waterhouse's suggestions, I had considered those names. I suppose if you read appendfile as a noun instead of a verb-and-noun, it's confusing (though infile and outfile don't really have the same problem, so it's not the train of thought my brain follows). It's hard modifying a name like tofile with a long word like append. We already have two words in tofile, so adding a third without hyphenation is stretching it, and adding hyphens breaks the flow with the other names (fromfile, tostring, etc.). We could go for something shorter, like addtofile, which delineates itself well without hyphens because each word is one syllable. If we can't avoid hyphens, using / instead (e.g., tofile/a or tofile/append) flows better, but isn't that great.

Another name that occurred to me -- and is probably my favorite so far -- is ontofile, which is still simple enough to not need hyphens, communicates intent (appending something onto a file), and worms the word to in there, painting it with the to:output / from:input correlation. Thoughts?

-----

2 points by evanrmurphy 5565 days ago | link

Another name that occurred to me -- and is probably my favorite so far -- is ontofile, which is still simple enough to not need hyphens, communicates intent (appending something onto a file), and worms the word to in there, painting it with the to:output / from:input correlation. Thoughts?

+1! ontofile is a great name, in my opinion, for all the reasons you listed.

I searched for a good portmanteau in the vein of mappend, but I don't think there is one. fappend? Sounds like frappuchino. filepend is decent, but I think I prefer ontofile.

-----

2 points by fallintothis 5565 days ago | link

fappend? Sounds like a frappuchino.

Hahaha! Or worse: http://www.urbandictionary.com/define.php?term=fap :P

filepend is decent, but I think I prefer ontofile.

Agreed on both counts. But that's a clever one; I hadn't thought to try out portmanteaus yet.

-----

1 point by evanrmurphy 5565 days ago | link

Oh wow, didn't know that one. Who knew you could get street smarter hanging out on Arc Forum??

-----

1 point by garply 5564 days ago | link

Regarding logging, I use a log function such that (log "my log message here") appends to a globally identified file log*.

-----


On another note, it seems "~" does the same thing as "no:", which I think is not much of an improvement

Relevant: http://arclanguage.org/item?id=3564

-----

3 points by fallintothis 5567 days ago | link | parent | on: Named loop or continue keyword?

  arc> ; with ccc
  (time
    (with (x 0 y 0)
      (while (< x 1000000)
        (catch
          (when (odd x)
            (++ x)
            (throw))
          (++ y)
          (++ x)))
      (list x y)))
  time: 27208 msec.
  (1000000 500000)

  arc> ; without ccc
  (time
    (with (x 0 y 0)
      (while (< x 1000000)
        (if (odd x)
            (++ x)
            (do (++ y)
                (++ x))))
      (list x y)))
  time: 1978 msec.
  (1000000 500000)
Interesting observation!

-----

More