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

BTW, I'm not a spammer guy,... for whatever reason people actually are willing to pay me (even though I'm doing it for free) to send them info e-mails..... go figure; it's certainly not for my knowledge in programming :)

At any rate I'm thinking the best way to do this is to have 'chimp mail' send an email with a link to my webapp, and upon user log-in displays custom content.

T.

-----


Kinda found a way to do it - though it kinda seems strange to have to use this approach.

    (def at-id-val (dat-name at-name)
       (for i 0 (- (len ktable) 1)
         (if (is ((ktable i) 1) at-name)     
               (pr ((dtable dat-name) i)))
       ))

    (def at-val (dat-name at-name)
      (tostring (at-id-val dat-name at-name))
     )
T.

-----


; i'll skip the code that loads the tables from files.... here's the results ; arc> (vals ktable) ; ((0 "FIRST") (1 "MIDDLE") (2 "LAST")) ; arc> (vals dtable) ; (("Jon" "Mid" "Dow") ("Jane" "Moodd" "Meow") ("Alex" "Morse" "Lstname"))

    (def dkey (at-name)
	    (for i 0 (- (len ktable) 1)
            (if (is ((ktable i) 1) at-name)
			(prn i)))) 
			
    ; arc> (dkey "MIDDLE")
    ; 1
    ; nil


    ; ((dtable "Jane" ) 1) .... this works passing in '1' but if I substitue for the dkey function i get the error
    ; arc> ((dtable "Jane" ) 1)
    ; "Moodd"


    (def at-val (dat-name at-name)
        ((dtable dat-name) (dkey at-name)))

     ; so  (at-val "Jane" "MIDDLE") generated the error

-----

1 point by skenney26 6173 days ago | link

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 6173 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 6173 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 6173 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 6173 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 6172 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.

-----


ahhhh..... thanks!

-----


I see. I'd imagine when you work with numbers this large it probably doesn't make sense to have them run on forever in decimal format anyway. I'm just not used to working in rationals yet. Thanks! :)

-----


Needs to stay as a number not a string :)

-----


I think my initial question didn't capture the intent.... and my attempt to simplify the function did exactly the opposite... so i will try again, this time not being lazy, and defining more :)

; Time is initialized at 30 min (x). ; Check each element in a string containing either "A"s or "B"s; ; if "A" add "v" minute(s) to x, if "B" subtract "v" minute(s) from x (let's call this value "xi"); ; Upon each check for A or B re-initialize x to be the current xi value multiplied by 2 (This way the next check ; can use the new x for it's increase/decrease)

; Use these 4 calls to validate function works correctly: ; (ugh "AAAA" 1) = 255 ; (ugh "BBBB" 1) = 225 ; (ugh "ABAB" 2) = 250

My original-like solution using "Sets" which work: * I changed to get rid of trunc, and make easier to read and align to the specs above.

    (def ugh (str v)
      (set x 15)
        (for i 0 (- (len str) 1) (set xi (* x 2))
          (if (is "A" (cut str i (+ i 1)))  
              (set x (+ xi v))
              (set x (- xi v))i))x)
Note: Although I set x to 15, notice the "set xi" was placed to bump that to 30 on the first pass.

As pointed out I tried unsuccessfully to remove the "sets". drcode and skenney26 both suggested ideas which do not work (not to their fault rather it was my laziness in asking the question properly). I re-worked the suggested solution to present the spirit of the intended function using the new specs above.

      (def ugh (str v)
        (let x 15
          (on c str
            (let xi (* x 2)
              (if (is c #\A)
                  (++ x (+ xi v))
                  (-- x (- xi v)))))
          x))
As stated this does not work. Sorry drcode... I didn't try the pure functional version - it looked more complicated than I wanted to go.

My solution after looking hacking with suggestions for ideas:

    (def ugh (str v)
       (let x 15
          (on c str 
             (++ x (sub-ugh x v str index)))x))

    (def sub-ugh (x v str i)
        (if (is "A" (cut str i (+ i 1)))
          (++ x v)
          (-- x v)))
Now, call me silly but does't this seem like overly complicated code compared to a relatively simple problem ? not just complicted from an amount of work perspective, but from a code readability perspective too ?

Why wouldn't the ARChitects of LISP or ARC make a set like function that is global within a function ? Doesn't this seem like a smart thing to do ? Is this against the spirit of lisp/arc/scheme ?

Thanks for stickin with me on this overly verbose newbie problem. T.

-----

1 point by thaddeus 6186 days ago | link

Sorry forgot my 4rth test that validates the code works:

arc> x Answer = Error: "reference to undefined identifier: __x"

-----

1 point by cchooper 6186 days ago | link

By the sound of things, the problem is that the variables created by one function are being modified by other functions. In that case, the solution is to use local variables instead of global variables. To do that, you just need to wrap the function body in a single let form:

  (def ugh (str v)
    (let x 15
      (for i 0 (- (len str) 1) (set xi (* x 2))
        (if (is "A" (cut str i (+ i 1)))  
            (set x (+ xi v))
            (set x (- xi v)) i)) x))
The sets will refer to the locally created variable, not a global variable.

  (= x 100000)
  => 100000
  (ugh "AAAA" 1)
  => 255
  x
  => 100000
The global x has not been modified, because the function created a local x variable and used that instead.

Here's a more concise version of that function:

  (def ugh (str v)
    (let x 15
      (on c str 
          (= x (* x 2))
          (if (is #\A c) (++ x v) 
              (-- x v)))
      x))
and here's a version that uses no sets at all:

  (def ugh (str v (o x 15))
    (let x2 (* 2 x)
      (if (is "" str) x
          (is #\A str.0) (ugh (cut str 1) v (+ x2 v))
          (ugh (cut str 1) v (- x2 v)))))

-----

1 point by thaddeus 6186 days ago | link

ah! I see. my rudimentary tests for (= x(...)) and probably having x set from previous iterations of code led me to believe (= x(...)) always changed the global x.

Thanks to all! T.

-----


Thanks! I appreciate it.... I'm stepping through the examples now and I can see there are a few nice tricks for me to get used to using with the code examples both of you have provided. T.

-----


Sorry about the poor formatting, i know there was a post with a trick to make indentation take, but can't find the post anymore....

-----

1 point by rntz 6187 days ago | link

Just put four spaces before every line of code and it'll be formatted as code rather than text.

-----