The code now seems to work as inteded! https://github.com/August-Alm/ats_csv_lexer
Thank you for all the help. I still don't fully grokk why the function needs to consume each of its arguments--will have to meditate more on that--but at least I know how to write code like this from now on. Den måndag 6 mars 2017 kl. 17:43:36 UTC+1 skrev gmhwxi: > > Yes, CSVstate needs to be changed as well. > > However, your code needs very little change. This is like a > a 5 minute job to me. I would be happy to give it a try if you say so. > But I thought that you might want to get the thrill of fixing the code :) > > On Monday, March 6, 2017 at 11:30:27 AM UTC-5, August Alm wrote: >> >> Hrrm, I had: >> >> fun >> parse_entry >> ( st: !CSVState >> _ >> , at: (int, int) >> , acc: !$SBF.stringbuf >> , cs: llstring >> ) : stream_vt(CSVEntry) >> >> I gather I have to change not just [!$SBF.stringbuf] but also [!CSVState >> >> _], right? What about if I did >> >> fun >> parse_entry_con >> ( st: !CSVState >> _ >> , at: (int, int) >> , acc: !$SBF.stringbuf >> , cs: llstring >> ) : stream_vt_con(CSVEntry) >> >> and then put >> >> parse_entry(...) = >> $ldelay >> ( parse_entry_con(...) >> , ( free(st) >> ; free(acc) >> ; free(cs) >> ) >> ) >> >> --would that work? Would it be idiomatic and efficient? >> >> Thanks, again, >> August >> >> Den måndag 6 mars 2017 kl. 14:30:05 UTC+1 skrev gmhwxi: >>> >>> I forgot to tell you something essential in using stream_vt. >>> The following interface for 'test' cannot work: >>> >>> fun test (acc: !$SBF.stringbuf, cs: llstring): stream_vt(DT) = >>> >>> What you need is >>> >>> fun test (acc: $SBF.stringbuf, cs: llstring): stream_vt(DT) = >>> >>> The 'acc' stringbuf needs to be consumed by 'test'. The implementation >>> of 'test' looks like this: >>> >>> $ldelay >>> ( >>> <code for stream construction> >>> , >>> (freeing(acc); freeing(cs)) // this part is executed when the stream is >>> freed >>> ) >>> >>> On Mon, Mar 6, 2017 at 8:19 AM, August Alm <[email protected]> wrote: >>> >>>> The points you mention are part of the reason I chose to wrote the csv >>>> lexer the way I did. It follows one of the fastests Haskell csv parsers, >>>> and I was curious to see how using linear types could optimize performance. >>>> >>>> Regarding your suggestion on how to make better use of $ldelay in my >>>> code: I'm stuck on a compiler error that I can't make sense of. The >>>> following pseudo-minimal example throws the same kind of errors: >>>> >>>> #include "share/atspre_define.hats" >>>> #include "share/atspre_staload.hats" >>>> staload UN = "prelude/SATS/unsafe.sats" >>>> staload SBF = "libats/SATS/stringbuf.sats" >>>> staload _(*SBF*) = "libats/DATS/stringbuf.dats" >>>> >>>> datatype DT = D_T of @{ alpha = char } >>>> vtypedef llstring = stream_vt(char) >>>> >>>> fun >>>> test (acc: !$SBF.stringbuf, cs: llstring): stream_vt(DT) = >>>> $ldelay >>>> ( case !cs of >>>> | ~stream_vt_nil() => >>>> if $SBF.stringbuf_get_size(acc) = i2sz(0) then >>>> stream_vt_nil() >>>> else stream_vt_cons(D_T(@{alpha = 'a'}), >>>> stream_vt_make_nil()) >>>> | ~stream_vt_cons(c, cs1) => >>>> let val crec = D_T(@{alpha = c}) >>>> in stream_vt_cons(crec, test(acc, cs1)) >>>> end >>>> , ~cs >>>> ) >>>> >>>> The compiler can not infer the type I want (which is >>>> [stream_vt_con(DT)] for the [stream_vt_nil()] following the first [then] >>>> in >>>> the function body. The error message says >>>> >>>> the dynamic expression cannot be assigned the type [S2EVar(5492)]. >>>> [...] mismatch of sorts in unification: >>>> The sort of variable is: S2RTbas(S2RTBASimp(1; t@ype)) >>>> The sort of solution is: S2RTbas(S2RTBASimp(2; viewtype)) >>>> [...] mismatch of static terms (tyleq): >>>> The actual term is: S2Eapp(S2Ecst(stream_vt_con); S2EVar(5495)) >>>> The needed term is: S2EVar(5492) >>>> >>>> (There are further errors of the same form.) Is the culprit that >>>> [stream_vt] of a nonlinear datatype requires some special care? The >>>> version >>>> with [stream_vt_make_nil()] instead of explicit [$ldelay] works so the >>>> error ought to be subtle. >>>> >>>> Best wishes, >>>> August >>>> >>>> Den söndag 5 mars 2017 kl. 23:58:35 UTC+1 skrev gmhwxi: >>>>> >>>>> Yes, you definitely got it :) >>>>> >>>>> Stream_vt is very memory-frugal. >>>>> >>>>> Haskell relies on deforestation (complex complier optimization) >>>>> to reduce memory usage of lazy evaluation. In ATS, deforestation is >>>>> not supported. Instead, the programmer needs to recycle memory >>>>> explicitly. >>>>> >>>>> Compared to Haskell, corresponding code using stream_vt in ATS can be >>>>> much more efficient both time-wise and memory-wise. >>>>> >>>>> For instance, the following example (for computing Mersenne primes) >>>>> can >>>>> run for days without run-time GC: >>>>> >>>>> >>>>> https://github.com/githwxi/ATS-Postiats/blob/master/doc/EXAMPLE/RosettaCode/Lucas-Lehmer_test2.dats >>>>> >>>>> It convincingly attests to the power of linear streams. >>>>> >>>>> Cheers! >>>>> >>>>> >>>>> On Sun, Mar 5, 2017 at 5:34 PM, August Alm <[email protected]> wrote: >>>>> >>>>>> Thanks for the tip! I think I understand. I treated $ldelay much as a >>>>>> data constructor, so that all streams are equally lazy, whereas there >>>>>> are >>>>>> in fact many ways to sequence into thunks. Let me give an example to >>>>>> anchor >>>>>> the discussion. Both the following implementations of a map-template for >>>>>> linear streams typecheck: >>>>>> >>>>>> fun {a, b: t0ype} >>>>>> map_make_cons >>>>>> ( xs: stream_vt(a) >>>>>> , f: a -> b >>>>>> ) : stream_vt(b) = >>>>>> case !xs of >>>>>> | ~stream_vt_nil() => stream_vt_make_nil() >>>>>> | ~stream_vt_cons(x, xs1) => >>>>>> stream_vt_make_cons(f(x), map_make_cons(xs1, f)) >>>>>> >>>>>> fun {a, b: t0ype} >>>>>> map_ldelay >>>>>> ( xs: stream_vt(a) >>>>>> , f: a -> b >>>>>> ) : stream_vt(b) = >>>>>> $ldelay >>>>>> ( case !xs of >>>>>> | ~stream_vt_nil() => stream_vt_nil() >>>>>> | ~stream_vt_cons(x, xs1) => >>>>>> stream_vt_cons(f(x), map_ldelay(xs1, f)) >>>>>> , ~xs >>>>>> ) >>>>>> >>>>>> The second is maximally lazy. The first, [map_make_cons] is less lazy >>>>>> because checking the case-conditions is not delayed. My code was like >>>>>> the >>>>>> first example, only much more was going on inside the case expressions. >>>>>> Is >>>>>> that a correct assessment? >>>>>> >>>>>> >>>>>> Den söndag 5 mars 2017 kl. 04:07:42 UTC+1 skrev gmhwxi: >>>>>>> >>>>>>> BTW, it seems you don't need to do much to fix the issue. >>>>>>> >>>>>>> Basically, you just do >>>>>>> >>>>>>> 1) Put the body of parse_entry into $ldelay(...) >>>>>>> 2) Change stream_vt_make_cons into stream_vt_cons >>>>>>> >>>>>>> There may be a few other things but they should all be >>>>>>> very minor. >>>>>>> >>>>>>> On Saturday, March 4, 2017 at 9:47:07 PM UTC-5, gmhwxi wrote: >>>>>>>> >>>>>>>> I took a glance at your code. >>>>>>>> >>>>>>>> I noticed a very common mistake involving the use of >>>>>>>> stream (or stream_vt). Basically, the way stream is used >>>>>>>> in your code is like the way list is used. This causes the >>>>>>>> stack issue you encountered. >>>>>>>> >>>>>>>> Say that you have a function that returns a stream. In nearly >>>>>>>> all cases, the correct way to implement such a function should >>>>>>>> use the following style: >>>>>>>> >>>>>>>> fun foo(...): stream_vt(...) = $ldelay >>>>>>>> ( >>>>>>>> ... >>>>>>>> ) >>>>>>>> >>>>>>>> The idea is that 'foo' should return in O(1) time. The body of >>>>>>>> $ldelay >>>>>>>> is only evaluated with the first element of the returned stream is >>>>>>>> neede. >>>>>>>> Sometimes, this is call full laziness. Without full laziness, a >>>>>>>> stream may >>>>>>>> behave like a list, defeating the very purpose of using a stream. >>>>>>>> >>>>>>>> On Saturday, March 4, 2017 at 7:27:03 PM UTC-5, August Alm wrote: >>>>>>>>> >>>>>>>>> I've spent few hours trying to figure out how to make proper use >>>>>>>>> of npm and gave up--for now. If the project turns into something more >>>>>>>>> serious (i.e., useful to others) then I will have another go at it. >>>>>>>>> For now >>>>>>>>> my naive attempts at making effective use of linear streams can be >>>>>>>>> witnessed at GitHub: https://github.com/August-Alm/ats_csv_lexer >>>>>>>>> Any and all comments on how to improve are appreciated. >>>>>>>>> >>>>>>>>> Best wishes, August. >>>>>>>>> >>>>>>>>> Den fredag 3 mars 2017 kl. 23:57:54 UTC+1 skrev gmhwxi: >>>>>>>>>> >>>>>>>>>> One possibility is to build a npm package and then publish it. >>>>>>>>>> >>>>>>>>>> If you go to https://www.npmjs.com/ and seach for 'atscntrb'. >>>>>>>>>> You can find >>>>>>>>>> plenty packages. You may need to install npm first. >>>>>>>>>> >>>>>>>>>> If you do build a npm package, I suggest that you choose a name >>>>>>>>>> space for >>>>>>>>>> yourself. E.g., atscntrb-a?a-..., where ? is the first letter of >>>>>>>>>> your middle name. >>>>>>>>>> >>>>>>>>>> On Fri, Mar 3, 2017 at 5:48 PM, August Alm <[email protected]> >>>>>>>>>> wrote: >>>>>>>>>> >>>>>>>>>>> How would I best share larger code portions? I have no concerns >>>>>>>>>>> about my making my mistakes public, heh. >>>>>>>>>>> >>>>>>>>>>> I believe everything is lazy as-is (all data is >>>>>>>>>>> [stream_vt("sometype")]). And I've tried to write tail-recursive >>>>>>>>>>> functional >>>>>>>>>>> code. The algorithm is based on two mutually recursing functions, >>>>>>>>>>> "fun ... >>>>>>>>>>> and ..", similar to how you did things in your csv-parser (thanks >>>>>>>>>>> for >>>>>>>>>>> pointing out that piece of code). However, I cannot set them up >>>>>>>>>>> with "fn* >>>>>>>>>>> .. and .." to enforce a local jump because they call each other in >>>>>>>>>>> a too >>>>>>>>>>> intertwined way. Might that be it? >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Den fredag 3 mars 2017 kl. 23:32:15 UTC+1 skrev gmhwxi: >>>>>>>>>>>> >>>>>>>>>>>> You are welcome! >>>>>>>>>>>> >>>>>>>>>>>> Since I have not seen your code, I could only guess :) >>>>>>>>>>>> >>>>>>>>>>>> Usually, what you described can be fixed by using >>>>>>>>>>>> tail-recursion, or >>>>>>>>>>>> by using lazy-evaluation. The former approach is >>>>>>>>>>>> straightforward. You >>>>>>>>>>>> just need to identify the function or functions that cause the >>>>>>>>>>>> deep stack >>>>>>>>>>>> usage. Then try to rewrite using tail-recursion. >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> On Fri, Mar 3, 2017 at 5:25 PM, August Alm <[email protected]> >>>>>>>>>>>> wrote: >>>>>>>>>>>> >>>>>>>>>>>>> Hi! >>>>>>>>>>>>> I had indeed made a logical error that caused any stream with >>>>>>>>>>>>> "carriage return" followed by "newline" to recurse indefinitely. >>>>>>>>>>>>> Thank you >>>>>>>>>>>>> for your patience and pedagogical instincts, Professor! There is >>>>>>>>>>>>> still some >>>>>>>>>>>>> issue though, one that I believe is more subtle. I fixed the >>>>>>>>>>>>> logical error >>>>>>>>>>>>> and my algorithm now handles all the test cases you suggested. >>>>>>>>>>>>> However, >>>>>>>>>>>>> when fed an actual CSV-file with a thousand rows and about 300 >>>>>>>>>>>>> columns it >>>>>>>>>>>>> still segfaults--unless I manually increase the stack space on my >>>>>>>>>>>>> computer! >>>>>>>>>>>>> I don't know exactly where the critical limit is, but increasing >>>>>>>>>>>>> it from >>>>>>>>>>>>> 8192 kbytes to 65536 certainly did the trick. The whole file >>>>>>>>>>>>> parsed without >>>>>>>>>>>>> problem, and rather quickly at that. It seems my algorithm makes >>>>>>>>>>>>> too much >>>>>>>>>>>>> use of stack allocation and that I may have to rethink some of my >>>>>>>>>>>>> (would-be) optimization choices. >>>>>>>>>>>>> Best wishes, >>>>>>>>>>>>> August >>>>>>>>>>>>> >>>>>>>>>>>>> Den fredag 3 mars 2017 kl. 15:22:00 UTC+1 skrev gmhwxi: >>>>>>>>>>>>>> >>>>>>>>>>>>>> Now you may do the following tests: >>>>>>>>>>>>>> >>>>>>>>>>>>>> Try: >>>>>>>>>>>>>> >>>>>>>>>>>>>> val ins = streamize_string_char("a;b") // should work >>>>>>>>>>>>>> >>>>>>>>>>>>>> Try: >>>>>>>>>>>>>> >>>>>>>>>>>>>> val ins = streamize_string_char("a;b\n") // may not work >>>>>>>>>>>>>> >>>>>>>>>>>>>> Try: >>>>>>>>>>>>>> >>>>>>>>>>>>>> val ins = streamize_string_char("a;b\015\012") // should >>>>>>>>>>>>>> cause crash >>>>>>>>>>>>>> >>>>>>>>>>>>>> On Thursday, March 2, 2017 at 9:21:21 PM UTC-5, gmhwxi wrote: >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> When tried, I saw the following 5 chars (ascii) in small.csv: >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> 97 >>>>>>>>>>>>>>> 59 >>>>>>>>>>>>>>> 98 >>>>>>>>>>>>>>> 13 >>>>>>>>>>>>>>> 10 >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> My testing code: >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> #include"share/atspre_staload.hats" >>>>>>>>>>>>>>> #include"share/HATS/atspre_staload_libats_ML.hats" >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> implement main0 () = { >>>>>>>>>>>>>>> val inp = fileref_open_exn("small.csv", file_mode_r) >>>>>>>>>>>>>>> val ins = streamize_fileref_char(inp) >>>>>>>>>>>>>>> val ins = stream2list_vt(ins) >>>>>>>>>>>>>>> val ins = g0ofg1(list_vt2t(ins))97 >>>>>>>>>>>>>>> val ( ) = println! ("length(ins) = ", length(ins)) >>>>>>>>>>>>>>> val ( ) = (ins).foreach()(lam c => println!(char2int0(c))) >>>>>>>>>>>>>>> (* >>>>>>>>>>>>>>> val lexed = lex_csv(true, ';', ins) >>>>>>>>>>>>>>> *) >>>>>>>>>>>>>>> val () = fileref_close(inp) >>>>>>>>>>>>>>> (* >>>>>>>>>>>>>>> val h = (lexed.head()) >>>>>>>>>>>>>>> val- CSV_Field(r) = h >>>>>>>>>>>>>>> val a = r.csvFieldContent >>>>>>>>>>>>>>> val () = println!(a) >>>>>>>>>>>>>>> *) >>>>>>>>>>>>>>> } >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> On Thu, Mar 2, 2017 at 9:13 PM, August Alm <...> wrote: >>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Just "a;b", or? (Attached.) >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> Den fredag 3 mars 2017 kl. 03:03:08 UTC+1 skrev gmhwxi: >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> I suspect that the file you used contains other characters. >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> What is in "small.csv"? >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> On Thu, Mar 2, 2017 at 8:52 PM, August Alm <...> wrote: >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> The file compiles (I've tried a few compiler options) and >>>>>>>>>>>>>>>>>> "gdb run" yields >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Program received signal SIGSEGV, Segmentation fault. >>>>>>>>>>>>>>>>>> 0x00007ffff783eea5 in _int_malloc (av=0x7ffff7b6a620 >>>>>>>>>>>>>>>>>> <main_arena>, bytes=16) at malloc.c:3790 >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> The frames 0-3 involve allocation functions that are not >>>>>>>>>>>>>>>>>> particular to my file. Frame 4 says: >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> #4 __patsfun_28__28__14 (arg0=<optimized out>, >>>>>>>>>>>>>>>>>> env1=0x605540, env0=10 '\n') at csv_lexer_dats.c:9023 >>>>>>>>>>>>>>>>>> 9023 ATSINSmove_con1_new(tmpret63__14, >>>>>>>>>>>>>>>>>> postiats_tysum_7) ; >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> My not-so-educated guess is that this refers to making a >>>>>>>>>>>>>>>>>> cons-cell of a stream. >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> But: How can my function do just fine when manually fed >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> cons('a', cons( ';', sing('b'))): stream_vt(char), >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> but segfault when I use [streamize_fileref_char] to >>>>>>>>>>>>>>>>>> construct the very same stream from the string "a;b" in a >>>>>>>>>>>>>>>>>> file? Where is >>>>>>>>>>>>>>>>>> the room for an infinite recursion in that? >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Thank you, >>>>>>>>>>>>>>>>>> August >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> Den torsdag 2 mars 2017 kl. 23:04:35 UTC+1 skrev August >>>>>>>>>>>>>>>>>> Alm: >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Hi! >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> I'm in over my head and tried writing a CSV-parser using >>>>>>>>>>>>>>>>>>> linear lazy streams. My code thus far is 600 lines and >>>>>>>>>>>>>>>>>>> almost to my own >>>>>>>>>>>>>>>>>>> surprise I get it to compile! However, there is something >>>>>>>>>>>>>>>>>>> fishy because I >>>>>>>>>>>>>>>>>>> get a segfault when applying my program to an actual >>>>>>>>>>>>>>>>>>> CSV-file. I've been >>>>>>>>>>>>>>>>>>> trying to debug using gdb but the fault eludes me. Since I >>>>>>>>>>>>>>>>>>> don't expect >>>>>>>>>>>>>>>>>>> anyone to mull through 600 lines of code, I am hoping these >>>>>>>>>>>>>>>>>>> code snippets >>>>>>>>>>>>>>>>>>> are enough for one of you guys to give me some advice. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> This code executes just fine: >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> implement main0 () = { >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> val test = stream_vt_make_cons( >>>>>>>>>>>>>>>>>>> 'a', stream_vt_make_cons( >>>>>>>>>>>>>>>>>>> ';', >>>>>>>>>>>>>>>>>>> stream_vt_make_sing('b'))) (* the stream ('a', >>>>>>>>>>>>>>>>>>> ';', 'b') *) >>>>>>>>>>>>>>>>>>> val lexed = lex_csv(true, ';', test) >>>>>>>>>>>>>>>>>>> val h = (lexed.head()) >>>>>>>>>>>>>>>>>>> val- CSV_Field(r) = h >>>>>>>>>>>>>>>>>>> val a = r.csvFieldContent >>>>>>>>>>>>>>>>>>> val () = println!(a) >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Here [lex_csv] is my 600-line alogrithm. It reads a >>>>>>>>>>>>>>>>>>> [stream_vt(char)] and gives back a [stream_vt(CSVEntry)], >>>>>>>>>>>>>>>>>>> where [CSVEntry] >>>>>>>>>>>>>>>>>>> is a record type, one of whose fields is [CSVFieldContent]. >>>>>>>>>>>>>>>>>>> When executing >>>>>>>>>>>>>>>>>>> the program I get "a" printed to the console. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> This code results in a segfault: >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> implement main0 () = { >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> val inp = fileref_open_exn("small.csv", >>>>>>>>>>>>>>>>>>> file_mode_r) >>>>>>>>>>>>>>>>>>> val ins = streamize_fileref_char(inp) >>>>>>>>>>>>>>>>>>> val lexed = lex_csv(true, ';', ins) >>>>>>>>>>>>>>>>>>> val () = fileref_close(inp) >>>>>>>>>>>>>>>>>>> val h = (lexed.head()) >>>>>>>>>>>>>>>>>>> val- CSV_Field(r) = h >>>>>>>>>>>>>>>>>>> val a = r.csvFieldContent >>>>>>>>>>>>>>>>>>> val () = println!(a) >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> } >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> The file "small.csv" only contains the string "a;b". >>>>>>>>>>>>>>>>>>> Hence I would expect this code to give the result as the >>>>>>>>>>>>>>>>>>> previous one! But, >>>>>>>>>>>>>>>>>>> it doesn't just return something else, it segfaults. >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> gdb indicates there is a malloc problem having to do >>>>>>>>>>>>>>>>>>> with "GC_clear_stack_inner", in case that's helpful. (I'm a >>>>>>>>>>>>>>>>>>> mathematician >>>>>>>>>>>>>>>>>>> who recently left academia after postdoc and decided to >>>>>>>>>>>>>>>>>>> teach myself >>>>>>>>>>>>>>>>>>> programming to become more useful outside of academia; >>>>>>>>>>>>>>>>>>> hence I understand >>>>>>>>>>>>>>>>>>> type systems and the like--the mathy stuff--a lot better >>>>>>>>>>>>>>>>>>> than I understand >>>>>>>>>>>>>>>>>>> memory allocation and other stuff that most programmers are >>>>>>>>>>>>>>>>>>> supposed to be >>>>>>>>>>>>>>>>>>> confident with.) >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> What could be the problem here? >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> Best wishes, >>>>>>>>>>>>>>>>>>> August >>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>> -- >>>>>>>>>>>>>>>>>> You received this message because you are subscribed to >>>>>>>>>>>>>>>>>> the Google Groups "ats-lang-users" group. >>>>>>>>>>>>>>>>>> To unsubscribe from this group and stop receiving emails >>>>>>>>>>>>>>>>>> from it, send an email to >>>>>>>>>>>>>>>>>> [email protected]. >>>>>>>>>>>>>>>>>> To post to this group, send email to >>>>>>>>>>>>>>>>>> [email protected]. >>>>>>>>>>>>>>>>>> Visit this group at >>>>>>>>>>>>>>>>>> https://groups.google.com/group/ats-lang-users. >>>>>>>>>>>>>>>>>> To view this discussion on the web visit >>>>>>>>>>>>>>>>>> https://groups.google.com/d/msgid/ats-lang-users/69535c5c-eac3-472c-bb39-062ad4708a72%40googlegroups.com >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>> <https://groups.google.com/d/msgid/ats-lang-users/69535c5c-eac3-472c-bb39-062ad4708a72%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>>>>>>>>>>>>>>> . >>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>> -- >>>>>>>>>>>>>>>> You received this message because you are subscribed to the >>>>>>>>>>>>>>>> Google Groups "ats-lang-users" group. >>>>>>>>>>>>>>>> To unsubscribe from this group and stop receiving emails >>>>>>>>>>>>>>>> from it, send an email to [email protected] >>>>>>>>>>>>>>>> . >>>>>>>>>>>>>>>> To post to this group, send email to >>>>>>>>>>>>>>>> [email protected]. >>>>>>>>>>>>>>>> Visit this group at >>>>>>>>>>>>>>>> https://groups.google.com/group/ats-lang-users. >>>>>>>>>>>>>>>> To view this discussion on the web visit >>>>>>>>>>>>>>>> https://groups.google.com/d/msgid/ats-lang-users/e608c7bb-42ce-457b-a606-9fe3525f801d%40googlegroups.com >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>> <https://groups.google.com/d/msgid/ats-lang-users/e608c7bb-42ce-457b-a606-9fe3525f801d%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>>>>>>>>>>>>> . >>>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> -- >>>>>>>>>>>>> You received this message because you are subscribed to the >>>>>>>>>>>>> Google Groups "ats-lang-users" group. >>>>>>>>>>>>> To unsubscribe from this group and stop receiving emails from >>>>>>>>>>>>> it, send an email to [email protected]. >>>>>>>>>>>>> To post to this group, send email to >>>>>>>>>>>>> [email protected]. >>>>>>>>>>>>> Visit this group at >>>>>>>>>>>>> https://groups.google.com/group/ats-lang-users. >>>>>>>>>>>>> To view this discussion on the web visit >>>>>>>>>>>>> https://groups.google.com/d/msgid/ats-lang-users/34dfad01-9bd4-464f-9ccd-6dfae8207f4c%40googlegroups.com >>>>>>>>>>>>> >>>>>>>>>>>>> <https://groups.google.com/d/msgid/ats-lang-users/34dfad01-9bd4-464f-9ccd-6dfae8207f4c%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>>>>>>>>>> . >>>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> -- >>>>>>>>>>> You received this message because you are subscribed to the >>>>>>>>>>> Google Groups "ats-lang-users" group. >>>>>>>>>>> To unsubscribe from this group and stop receiving emails from >>>>>>>>>>> it, send an email to [email protected]. >>>>>>>>>>> To post to this group, send email to [email protected] >>>>>>>>>>> . >>>>>>>>>>> Visit this group at >>>>>>>>>>> https://groups.google.com/group/ats-lang-users. >>>>>>>>>>> To view this discussion on the web visit >>>>>>>>>>> https://groups.google.com/d/msgid/ats-lang-users/c2f9d2b7-61f5-4142-b8b2-930147ee589d%40googlegroups.com >>>>>>>>>>> >>>>>>>>>>> <https://groups.google.com/d/msgid/ats-lang-users/c2f9d2b7-61f5-4142-b8b2-930147ee589d%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>>>>>>>> . >>>>>>>>>>> >>>>>>>>>> >>>>>>>>>> -- >>>>>> You received this message because you are subscribed to the Google >>>>>> Groups "ats-lang-users" group. >>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>> send an email to [email protected]. >>>>>> To post to this group, send email to [email protected]. >>>>>> Visit this group at https://groups.google.com/group/ats-lang-users. >>>>>> To view this discussion on the web visit >>>>>> https://groups.google.com/d/msgid/ats-lang-users/d78409e2-aff1-4b96-98f3-eb3a5d20ff95%40googlegroups.com >>>>>> >>>>>> <https://groups.google.com/d/msgid/ats-lang-users/d78409e2-aff1-4b96-98f3-eb3a5d20ff95%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>>> . >>>>>> >>>>> >>>>> -- >>>> You received this message because you are subscribed to the Google >>>> Groups "ats-lang-users" group. >>>> To unsubscribe from this group and stop receiving emails from it, send >>>> an email to [email protected]. >>>> To post to this group, send email to [email protected]. >>>> Visit this group at https://groups.google.com/group/ats-lang-users. >>>> To view this discussion on the web visit >>>> https://groups.google.com/d/msgid/ats-lang-users/716c8c61-d535-412d-8584-d4030d20801d%40googlegroups.com >>>> >>>> <https://groups.google.com/d/msgid/ats-lang-users/716c8c61-d535-412d-8584-d4030d20801d%40googlegroups.com?utm_medium=email&utm_source=footer> >>>> . >>>> >>> >>> -- You received this message because you are subscribed to the Google Groups "ats-lang-users" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at https://groups.google.com/group/ats-lang-users. To view this discussion on the web visit https://groups.google.com/d/msgid/ats-lang-users/e34175a4-9b0e-4a33-b599-990df7c1f43b%40googlegroups.com.
