Arc Forumnew | comments | leaders | submit | skenney26's commentslogin
6 points by skenney26 5945 days ago | link | parent | on: This would make my programs shorter.

I agree that the exclamation marks aren't that useful.

Here's a macro that might be useful for digging down into a nested table:

  (mac dig args
   `(,@(reduce list args)))

  arc> (= x (table))
  #hash()
  arc> (= (x 'y) (table))
  #hash()
  arc> (= ((x 'y) 'z) 0)
  0
  arc> x
  #hash((y . #hash((z . 0))))
  arc> (dig x 'y 'z)
  0
  arc> (= (dig x 'y 'z) 1)
  1
  arc> x
  #hash((y . #hash((z . 1))))

-----

2 points by skenney26 5960 days ago | link | parent | on: Wiki list of websites & apps using Arc

Here's the link: http://ycombinator.com/arc/arc2.tar

The file you're looking for is news.arc

-----


Maybe it would be simpler to use a list for your data structure:

  (= names* '(("Jon" "Mid" "Dow") ("Alex" "Morse" "Lstname") ("Jane" "Moodd" "Meow")))
Then you could use 'assoc to find a name:

  arc> (assoc "Jane" names*)
  ("Jane" "Moodd" "Meow")
And integers to return the first, middle, and last parts of a name:

  arc> ((assoc "Jane" names*) 1)
  "Moodd"

-----

1 point by thaddeus 5965 days ago | link

I think your code looks much cleaner, but I guess I have a few more points/questions.

1. Using the assoc function I would still have pass in a number to find the value for a given attribute a user chooses, correct? Which means I still would have to write an iteration function to find the position of that value to return and then would run into the same problem.

2. I have an assumption that when working with large volumes of data one would want to use a table, and small volumes should use a list....Is this correct? (my example above is only for testing)...

Thanks, T.

-----

1 point by rincewind 5965 days ago | link

What do you want to do with these data structures exactly?

Something like this?

  (= names* 
    (obj person1 '("Jon" "Mid" "Dow")
         person2 '("Alex" "Morse" "Lstname") 
         person3 '("Jane" "Moodd" "Meow")))

  (def get-name-part (person part)
       ((names* person) ((obj first 0 middle 1 last 2) part)))

-----

1 point by thaddeus 5965 days ago | link

I've have to check the code at home, at work now.....

Essentially I'm taking a spreadsheet file (csv) with an arbitrary number of columns of data, reading in the headers so they can be output to the html table as headers then reading in the remainder to create rows in the html table.

also also letting users to pick and choose which columns of data they want by selecting header names.

I've pretty much got it all working, I'm just surprised the language wouldn't provide for passing in results of an iteration function cleanly. To have to create an extra function simply to strip out the nil ends up making the code readability poor..... I'm sure I will look at the code in 2 months, scratch my head and ask why I needed a second function.... of course by then I'll probably have found a better way :)

-----

1 point by rincewind 5964 days ago | link

  (def keep-cols (cols tabl) ;for one row
     (map [let nr -1 (keep [some (++ nr) cols] _)] tabl))

  (def get-cols (cols tabl) ;table with selected columns
      (withs ((head . rows) tabl
              colnrs (rem nil (map [pos _ head] cols))
              filtered-rows (keep-cols colnrs rows))
        (cons cols filtered-rows)))

  ;test
  (get-cols '(foo baz) '((foo bar baz) ;header
                         (bla bla spam)
                         (eggs ham bacon) 
                         (lorem ipsum test)))

-----

1 point by thaddeus 5964 days ago | link

That's much nicer code than mine :)

I'm going to step through some of the syntax; I haven't been using: map, [], or "." yet.

Thanks, T.

-----


Could you provide the code that you have so far?

-----

1 point by skenney26 5977 days ago | link | parent | on: Does memo work right?

You could write a more complicated check within memo that examined whether the arguments had been passed before. This would probably slow down lookup though and not give much of a net gain.

-----

3 points by eds 5975 days ago | link

> You could write a more complicated check within memo that examined whether the arguments had been passed before.

This is exactly what memo does right now: it just stores the args to 'f in a hash table and looks them up whenever 'f gets called.

  (def memo (f)
    (let cache (table)
      (fn args
        (or (cache args)
            (= (cache args) (apply f args))))))
The problem which prevents this from working nicely with nil is that hash tables in Arc do not distinguish between the value nil and a key simply not being there. The workaround is to use a default value (generally a symbol returned by (uniq)) to guarantee uniqueness for the case when the key does not exist.

See http://arclanguage.org/item?id=8566 for more information.

-----

2 points by zhtw 5973 days ago | link

Actually I know why it happens and how to fix that. The question was more like "is it a bug or a feature?" I remember that PG suggested (but forgot where I read that) to store cons' in a table when you need to distinguish nil and absence of an element but why doesn't he use that technique (or any other) himself?

-----

2 points by skenney26 5973 days ago | link

I think the simple answer is that he hasn't needed that feature. 'memo and 'defmemo are used in 5 places in news.arc and it doesn't look like any of those uses would benefit from allowing nil as a value.

If someone created an application that benefited from that feature then perhaps there would be reason to redefine 'memo.

This seems to be an important part of the Arc philosophy: add a feature only when its absolutely needed.

-----

1 point by zhtw 5970 days ago | link

Only now I realized that you treat memo as some kind of the way to improve performance (do you?). What I used memo for is to make sure that function won't be called twice:

  (mac delay (e)
    `(memo (fn () ,e)))

  (def force (d) (d))
When I use lazy sequences (of symbols read from input port for example) based on these definitions I can't be sure that readc somewhere inside will never be called twice if I call force for an element of this sequence twice.

So I treat this as a bug. Or maybe I'm just wrong about what memo is for at all. Am I?

-----

1 point by aaronla 5959 days ago | link

I'd venture to guess that memo creates a new cache for each invocation, so two calls

  (map (lambda (f)  ;; invokes f 3 times
               (f) (f) (f) )
       (list (delay (foo bar)) 
             (delay (foo bar))))
I think thiw will call foo exactly twice, because each memo invokation produces a new cache, but I may be mistaken.

[pardon the syntax... this is in scheme. i have only just installed arc and (def hello-world ...) is as far as i've gotten]

-----

1 point by absz 5959 days ago | link

The real problem is that if you do

  (let d (delay (foo bar))
    (force d)
    (force d))
, then there's no guarantee that (foo bar) will be run exactly once---if (foo bar) returns nil, then it won't be cached.

-----


Another twist is to use the 'on interator which binds its first argument to each successive element and implicitly binds 'index to the index of that element.

  arc> (on c "arc" (prn index ":" c))
  0:a
  1:r
  2:c
  nil

  (def ugh (str)
    (let x 5
      (on c str
        (let v (trunc (/ 12 (+ index 1)))
          (if (is c #\A)
              (++ x v)
              (-- x v))))
      x))

-----

1 point by drcode 5978 days ago | link

ah... I should be using 'on more often....

-----

2 points by skenney26 5988 days ago | link | parent | on: Plop in Arc

I dropped Moshe a line to see what he has to say regarding Plop's dependency on Maxima.

I've looked through the first few files and so far have only encountered fairly straight-forward common lisp. Hopefully whatever Maxima features are used will be relatively easy to implement.

-----

1 point by skenney26 5988 days ago | link

Coincidently, Moshe just finished updating Plop so that it runs correctly without Maxima.

-----

1 point by skenney26 6022 days ago | link | parent | on: Reading a webpage

I've been looking through stefano's code. It looks like something like this should work...

  (let (i o) (connect-socket url* 80)
    (disp (readline i)))
... or something like that, but I haven't gotten it to work. Usually I get an error or a return value of nil.

-----

3 points by stefano 6022 days ago | link

With http-get loaded this macro should do the job. You could also have a look at xml.arc to parse xhtml pages.

  (mac w/url (var url . body)
    `(let ,var (cadr (get-request (str->url ,url)))
       ,@body)))

-----

1 point by skenney26 6022 days ago | link

Awesome, that's exactly what I needed.

I'm not familiar with how to use xml.arc but this is what I came up with for finding the links on a page:

  (def find-links (str)
    (with (start 0 acc nil)
      (whilet p (posmatch " href=" str start)
        (= start
           (+ p (if (in (str (+ p 6)) #\' #\") 7 6)))
      (push (cut str start (pos [in _ #\' #\" #\> #\space] str start))
            acc))
      (rev acc)))

  (w/url u "http://www.google.com/"
    (find-links u))

-----

2 points by skenney26 6035 days ago | link | parent | on: A thought: Arc <=> JS

A couple months ago I was playing around with an interpreter that translates Arc to Processing (http://processing.org/) which is pretty similar to Javascript. It's available at http://github.com/skenney26/pro/tree/master/pro.arc and requires John Resig's Javascript port of Processing (http://ejohn.org/blog/processingjs/).

-----


Replicated the error on a Mac.

-----

More