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

Thanks, akkartik, for sharing this with us. I'm sure you're not the only one to not know about these 2 features, and anyway, always good to see someone discovering something.

About 1. There is also 'disktable, same principe but for a table.

Not in vanilla, see also (self-plug) 'ptable: http://arclanguage.org/item?id=10664, which is transparent-persistence (no need to call 'todisk).

About 2. I have a draft for a "better" 'defcache, one that would work with any number of args. Here it is, if anyone is interested. I needed it for caching calls to `stat'.

  (def out-from (cmd . cargs)
    (tostring:system (apply + (cons cmd cargs))))

  (def fstat (fname)
    (tokens:out-from "stat --terse " fname))  ; --terse POSIX? works on Linux at least

  (def cachr (timefn valfn)  ; timefn takes an argument: the value returned by (valfn args).
    (with (cache  (table)
      	   nilsym (uniq))
      (list cache
        (fn args
          (= args (copy args))  ; Arc bug: confusion w/ () and nil-terminated lists as table keys, scheme-impl related
          (unless (aand cache.args (< (since it!time) (timefn it)))
            (= cache.args (obj time (seconds)
	     	               val  (aif (apply valfn args) it nilsym))))
          (let v cache.args!val
            (if (isnt v nilsym) v))))))

  ; nilsym is used to differenciate nil == value not in
  ; table, and nil == result of (valf arg) is nil but 
  ; it's in the cache. Not quite sure if correct.
  ;
  ;  idea: make table work like this:
  ;     (w/uniq (missym)
  ;       (if (isnt (tbl key missym) missym)  
  ;	     "key is in tbl, and may be nil"
  ;	     "key is not in tbl"))
  ;   with missym being nil by default. Like 'read/eof.
  ;
  ;   I don't know if a hashtable can easily do this.
  ;   Need a 'delete-key fn or to modify 'wipe.
  ;   Maybe unatural that (= hash!key nil) doesn't 
  ;   delete. Less simple anyway.
  ;
  ;   Alt: encapsulate the table values in a list.

  ; Cache is made accessible, because:

  (def invalidate (key cach)  (= cach.key!time -1))

  (def reset (key cach f)
    (invalidate key cach)
    (f key))

  (let (h f) (cachr (fn (entry) 5) fstat)
    (= fstat-cache* h
         fstatc	  f))

  ; (reset '("/some/file") fstat-cache* fstatc)

  ; remove fstat-cache* entries that don't have been accessed recently. 
  ; we can always re-read from the disk, but RAM is precious.
  ; better: a FIFO mecanism, set max n of elems. memcached

  (new-bgthread 'fstat-cache-reaper 
    (fn ()  (each (k v) fstat-cache*
              (if (< (since v!time) (* 3 60 60))
                  (wipe fstat-cache*.k))))
    (* 30 60))

   (def mtime (fname)  (int ((fstatc fname) 12)))
   ...

-----

2 points by akkartik 5666 days ago | link

Very cool.

The nilsym is an interesting idea. Why do you prefer it to the nilcache approach in memo?

I liked seeing the invalidate/reset functions; one problem with the current defmemo and defcache is that a cache can grow unboundedly as stale values accumulate. In your case you could actually set cach.key to nilsym to avoid that. I've been thinking about more global policies than deleting individual keys.

Idea #1: Caches have a max size and when it is exceeded you delete the least recently used (LRU) element. Was this what you meant by the FIFO mechanism above? If you have a systems background as I do, this is the first approach you think of. (http://en.wikipedia.org/wiki/Cache_algorithms)

Idea #2: A function to clear the cache. I like this approach because it's simpler than watching what was accessed when, and it fits naturally to the way we do things.

  (defcache parse-fragment A fragment
    ..)

  (defcache check-fragment A fragment
    ..)

  (whilet (document-fragments doc)
    (clearcache A)
    ... ;; lots of stuff happens here every iteration, relying on fragment operations being cached.
I've added a notion of multiple caches; defcache specifies a cache, and clearcache simply clears everything in a cache regardless of which function it's for. Helps group related functions together.

-----

1 point by palsecam 5666 days ago | link

1. nilsym over nilcache: because I prefer to have only one table to store all the cached values. And I suppose it makes the code shorter. And maybe more efficient. And it's a new approach, and I like new things.

2. In your case you could actually set cach.key to nilsym to avoid that. I suppose you mean "set cach.key to (the real) nil (to actually delete the entry)"

3. I've been thinking about more global policies than deleting individual keys. Me too. As I said, this is just a draft. For instance, '(fstat)-cache-reaper is a common pattern, it needs to be automated, you should not write it manually.

4. delete the least recently used (LRU) element. Was this what you meant by the FIFO mechanism above? Yes.

5. A function to clear the cache. Yes, good idea. See above, as I said, ...-cache-reaper is a common pattern.

-----

2 points by akkartik 5666 days ago | link

Ah, I totally missed your reaper thread when I wrote http://arclanguage.org/item?id=10699

I suppose you mean "set cach.key to (the real) nil"

Yep :}

-----


See 'inc in arc.arc (there is also '++).

-----

3 points by palsecam 5674 days ago | link | parent | on: Simple genome analysis with Arc

FTR, 'hist could be just:

  (def hist (seq)
    (w/table h
      (each n seq
        (++ (h n 0)))))
I just learned about 'w/table reading your post, and I checked, and it returns the created hash. This is quite smart, I often find myself doing things like:

  (let h (table)
    ...  ; do stuff with h
    h)  ; return it
Where it's actually possible to do:

  (w/table h
    ...)  ; implicit return of "h"
But yes, here, use 'counts.

-----


> If anyone has input data that demonstrates a difference between pg's and Norvig's, please reply with a comment.

In case you didn't see it, see above (http://arclanguage.org/item?id=10580)

Not exactly the same results than Norvig's version (>>> correct("speling") -> "sling" / "godd" -> "god") but I tested the Ruby version linked on his site, and it yields the same results.

I.e: Your / my "correction" of pg's version give "spelling" and "good".

And pg's vanilla version for (correct "yellow") gives "fellow".

-----

2 points by lojic 5700 days ago | link

Sorry, I noticed your post after I posted in haste. Nice work - 12 lines is still darn impressive. Followup with a comment if you use Norvig's test program and notice any other issues.

-----


Very cool, thanks for sharing.

I didn't know about wterm. I suppose I wrote "an informally-specified, bug-ridden, slow implementation of half of it" for the evsrv front-end :-) I'll go check it out.

I suppose you know about it, but prompt.arc, shipped with Arc, is also something similar to your Arc Web terminal or my evsrv. But it's not Ajaxified.

Do you have any screenshot of your terminal to share? I'd be glad to see what it looks like.

(eval (list 'eval (list 'quote (read exps))) The double-eval is because of macros, right? I remember I did something similar in the first version of the evsrv. Also, does your solution handle multiple expressions? I mean, what happens if "tokens" is, for instance "(+ 2 3) (+ 4 4) (prn "something")"? And, does it handle 'prn well, i.e: writing to stdout, or does it only give the result of evaluation?

Don't hesitate to ask for any help concerning your terminal. I have a bit of experience on the question with evsrv, I'd be glad to help you.

-----

2 points by thaddeus 5701 days ago | link

You can see the wterm demo here:

http://wterminal.appspot.com/demo

  type 'help' to see what examples exist.
  'strrev' emulates switching modes.
As a note: I wasn't trying to build an IDE using wterm, rather I just wanted to be able to push out changes, have a means to look at data. etc etc.

> "The double-eval is because of macros, right?"

um - eh-hem - yep - I think I got that idea from you :)

> "Also, does your solution handle multiple expressions?"

hmmm... I hadn't actually tried that until you mentioned it here - no it doesn't, but I think that's a matter of defining the arc-handler to do so. wterm just takes what ever I type and submits all of it as a string then returns the response. I should look into that :)

> "And, does it handle 'prn well"

not really... in wterm everthing has to be typed on 1 line and everything returns on 1 line; example:

  AJAX Terminal. To Begin Using type help
  Terminal $ arc
  arc $ (= db (obj how "wterm" what "arc"))
  #hash((what . "arc") (how . "wterm"))
  arc $ (pr db)
  #hash((what . arc) (how . wterm))#hash((what . "arc") (how . "wterm"))
  arc $ (repeat 3 (prn " all on one line "))
  all on one line all on one line all on one line nil
  arc $ 
> "Don't hesitate to ask for any help concerning your terminal."

ok thanks! :). I am going to take another look at your Evserv code to see if I can figure out handling of mutliple expressions. I will let you know if I need help.

Right now I am just so happy being able to tinker with arc via my sheevaplug; which is totally awesome! (+ nothing to do with arc, but I just got twonkeymedia server up and distributing movies and music to my TV - haha I don't need to keep my computer on anymore!!! cheapest, 2 watt, mediaserver I have ever seen).

T.

-----

2 points by palsecam 5700 days ago | link

> You can see the wterm demo here:

Thanks for the link.

> ok thanks! :). I am going to take another look at your Evserv code to see if I can figure out handling of mutliple expressions. I will let you know if I need help.

Right now I am just so happy

Yes, I pointed this eventual issue just that you have some ideas for what to work on next / what problems may appear. But yeah, if it fits your needs in this current state, which is already very good, just enjoy!

Oh and all your sheevaplug / twonkeymedia server stuff seems rather cool!

-----

2 points by thaddeus 5700 days ago | link

> Oh and all your sheevaplug / twonkeymedia server stuff seems rather cool!

'kens' got me hooked on playing with the sheevaplug. I hope this guy keeps sharing the wealth. Now I just got to come up with a practical use for arc on it.

If anyone else is interested:

http://plugcomputer.org/plugwiki/index.php/Run_TwonkyMedia_o...

T.

-----


Very interesting.

> it's useful to pass your arguments through some kind of a filter

A quite common pattern, at least in my programming experience.

However, like rntz, I'm not sure using ssyntax to do that is a Good Thing. But what about a special form "c"(check) like "o"(ptional)?

  arc> (def2 some ((c test testify) seq)
         (if (alist seq)
             (reclist test:car seq)
             (recstring test:seq seq)))
The first arg to "c" would be passed to the second arg, and the result of it would be bound back to the first arg. Or, if there an error, well, throw it.

----

Other notes: I hate to freely criticize, but the defs of 'some, 'find and co are sooooo ugly because of the string/list dichotomy. Not clean for a "code is the spec"-based language. And not extensible. Arc has a problem w/ the overloading issue. See also: 'map doesn't work for tables, but 'each does (my and some news.arc code would benefit from 'map working w/ tables [currently it uses 'accum & 'maptable]). See also: the def of 'each is also ugly/unextensible. See also: queues and the functions to manipulate them, like 'qlen, that have ugly names because you can't add "methods" to 'len. See also: 'rev doesn't work for strings?!!

'testify... Idea in the wild: make (coerce anAtom 'fn) do what 'testify does.

-----

1 point by palsecam 5703 days ago | link | parent | on: Operator nomenclature

It's interesting to note that, but for the lambda point, at some time while playing w/ Arc, I also thought about the points you raise. So, since this is all about personal taste, here are my views. All of this is just my humble opinion.

About =. Well, yes, you can see '=' as the equality operator. Or, as I do, you can see it as "Arc copies the C style, where '=' is for assignation". So I thought well, if Arc copies C, let's use '==' for equality, instead of 'is'. But there are some problems with that. How do you name 'iso' and 'isa' then? The good point with the isx nomenclature is that it is coherent. One could use '===' for 'is and '==' for 'iso, but still, I can't think how to cope with 'isa using the '=' notation. And '===' is too long.

So finally, I'm OK with the '=' and the isx family.

About 'def and 'mac. Yes, yes, true, it's incoherent. 'def is a verb and 'mac is a name. But in a way, that's reflects that there is difference between a macro (definition) and a function (definition). After reflexion, I was ok with it.

About lambda. I prefer 'fn' over 'ld/lb'. In some other languages or even in Lisp code, when you want to refer to a function, you call it 'f' or 'fn' or the like. And everyone understands that. The meaning of 'ld' would not be evident. It means 'load' to me, at first look.

In the same "let's-not-abandon-the-lambda-terminology" vein, Haskell uses '\' to denote a lambda, imitating the glyph of the lambda character in the greek alphabet. I'd prefer that over 'ld/lb', but this is, IMO, a bit crappy anyway. I know many people, me the first, that couldn't understand what this '\' meant at first look. '\' is too much of a special char in the current computing world (basically: ask any programmer, he'll tell you it's the escape sequence). Since we don't live in a full UTF-8 world, and it'd not be usable to use the real 'λ' to denote an anonymous function in a source file, well don't try to badly copy this glyph. Plus, OK, '\' is shorter, but on my Azerty keyboard, and I suppose it's the same on a Qwerty, it's slower to type '\' than to type 'fn'.

And Clojure has also adopted the "fn" name.

Last but not least, in my view a programming language is actually close to a natural language, and well, natural languages for a lot of pratical/historical reasons are not that consistent/formal. People are not always, fanatically consistent. Think about it.

-----

1 point by El_Indio 5703 days ago | link

So you're saying is and isa are variations of isomorphic? I was actually thinking of the verb to be for 'is'. If that's true I agree it makes more sense. I still think '=' looks a bit awkward for prefix assignment though.

As for def and mac I think fun and mac would reflect the difference just as well as they stand for completely different words. ;) But anyway, for me it would be mainly about "freeing" def, so it could be used for assignment.

'\' for lambda is actually a very good idea. I agree that with lisps syntax it wouldn't be as clear as in Haskell though. Maybe another character with some resemblance to lambda could be used, such as 'h' or 'y'.

-----

1 point by palsecam 5703 days ago | link

There are 3 main "test" operators in Arc.

  arc> (= a 42
          b '(1 2 3)
          c "hello")
  arc> (is a 42)         ; test for equality, read as "_Is_ a equals to 42?"
  t
  arc> (isa a 'int)      ; test for type, read as "_Is_ 'a' _a_(n) integer?"
  t
  arc> (iso b '(1 2 3))  ; test for isomorphy ("same form" in greek), 'is doesn't work for lists (normal)
  t
  arc> (is c "hello")    ; "_is_ c equals to 'hello'?"
  t
  arc> (isa c 'string)   ; "_is_ c _a_ string?"
  t
So no, 'is and 'isa are not "variations" of isomorphic, but the names of 'is 'iso and 'isa are close because well, they are the same kind of things (test operators).

Yep, fun and mac are completely different words. I agree it could suffice. But 'fun would then be too close to 'fn (anonymous function/lambda) to replace 'def (define a function) IMO. Would prefer to change 'mac to 'defmac in this case.

About lambda: anyway what's the point with absolutely wanting to keep this word?! Church called his work "Lambda Calculus" because on the blackboard he used 'λ' because it's quick to write on a blackboard: two traits. But "lambda" is just an arbitrary name. I really don't see a reason to absolutely keep it when programming on a computer, where you can't quickly type "λ". Oh and "lambda" feels somewhat so pedantic.

Oh and all this is just cosmetic. Let's not debate about it for hours. We will never agree. De gustibus et coloribus non est disputandum (I sometimes like to be pedantic and use Latin :-P)

-----

2 points by palsecam 5703 days ago | link | parent | on: Operator nomenclature

> Lots of fun. Could be a major selling point for arc.

Ah ah, I really laughed reading this. And jokes are to be taken... seriously :-D [1]

> I notice I prefer euphonious names

I respect your preference of course, but since we are in a "what's your personal opinion" thread, I'll give mine.

When I think about "fn" in my head it sounds "F-N", like the Unix `ls'/`cd' sound "L-S" / "C-D". I actually like these "saccatero sounds". In English, how do you pronounce "ISP" or "BTW" in conversation? Aren't people saying "bee-tee-double U" sometimes?

---

1: I'm serious here. I'd have probably never got into computers if it was not fun. I'm fond of the acronym jokes ("Gnu's not Unix", the names of the Lisp dialects Nil/T/Eine/Zwei, etc.). I'm in love with the fact my computer is full of daemons, indians (Apache), penguins and the like.

-----

1 point by palsecam 5703 days ago | link | parent | on: To Hyphenate or Not to Hyphenate

Well, fallintothis explained it. There is a scheme: if the name is readable/unambigous w/out hyphens, don't use hyphens, else use some. There are exceptions like 'end-tag to match 'start-tag.

There are some "errors" assuming this scheme is correct, like 'fill-table which could be 'filltable. But Clojure has doto (not do-to) and doall (not do-all) for instance. I don't know Scheme enough, but Common Lisp, as fallintothis pointed it out, also has inconsistencies. I suppose Scheme has some.

-----

1 point by palsecam 5703 days ago | link | parent | on: Other sites running news.arc?

I suppose the Hl Forum, http://hl.webhop.net/, uses news.arc.

-----

More