Once INV annotation is done properly, template annotation can be pretty much removed.
On Mon, Mar 13, 2017 at 6:39 PM, August Alm <august...@gmail.com> wrote: > Thanks for the hint! I added template arguments wherever I could and now I > got some error messages that actually say something. However, I do find it > a bit disconcerting that the compiler would segfault rather than tell me I > need to annotate templates. > > Den måndag 13 mars 2017 kl. 22:02:57 UTC+1 skrev gmhwxi: >> >> I will take a look later. Based on your description, the issue >> seems to be caused by not providing certain template arguments >> explicitly: >> >> Say, foo is a template. Please use foo<...>(...) instead of foo(...) >> >> Compared to Haskell, type inference in ATS is quite limited :) >> >> On Mon, Mar 13, 2017 at 4:51 PM, August Alm <augu...@gmail.com> wrote: >> >>> So... I added some "second stage" parsing functionality, to get the en >>> result in tabular form rahter than as a single [stream_vt], and to check >>> for global errors such as unequal number of columns in the rows, and now I >>> am back to segfaulting! =( However, this time it does not seem to be a >>> stack issue because I run into the segmentation fault already at the >>> compilation stage. >>> >>> I code in Vim and have it set up so that typing ":make" will run "patsopt >>> -tc -d %", i.e., typechecking only. When I do everything seems fine--no >>> complaints. I have used this utility for some time now and it has always >>> worked like a charm. Wierdly though, if I issue "$ patsopt -tc -d >>> csv_lexer.dats" in the console instead I get a segfault. The same happens >>> for every other compilation command: I've tried compiling just using type >>> checking, just to c, or etc. Always segfault. Compiling with the "-verbose" >>> flag prints >>> >>> exec(patsopt --output csv_lexer_dats.c --dynamic csv_lexer.dats) >>> Segmentation fault >>> exec(patsopt --output csv_lexer_dats.c --dynamic csv_lexer.dats) = 35584 >>> >>> which does not tell me anything. >>> >>> My code can be found at https://github.com/August-Alm/ats_csv_lexer >>> Note that I have moved some function implementations into a hats-file. >>> Might this be a cause of trouble? Any tips at all on how to debug this are >>> most appreciated. I don't know where to even begin as gdb seems useless as >>> long as I can't even generate the C-code. >>> >>> Best wishes, >>> August >>> >>> Den onsdag 8 mars 2017 kl. 23:44:10 UTC+1 skrev gmhwxi: >>>> >>>> >>I take that as being somewhat tongue-in-cheek. ATS is a very >>>> theoretical language, after all. >>>> >>>> I know that this sounds very ironic but interesting stuff often does >>>> sound ironic :) >>>> >>>> My view of programming language research is changing gradually but >>>> surely. I now strongly feel >>>> that the most important programming support is to facilitate the need >>>> to alter/adapt the behaviour >>>> of a written program without actually requiring direct changes to be >>>> made to the program. And the >>>> template system of ATS can be seen as an attempt to provide programming >>>> support of this sort. >>>> >>>> >>>> On Wed, Mar 8, 2017 at 4:47 PM, August Alm <augu...@gmail.com> wrote: >>>> >>>>> See in. >>>>> >>>>> Den onsdag 8 mars 2017 kl. 17:51:36 UTC+1 skrev gmhwxi: >>>>>> >>>>>> Tangential to the topic of monads: Do you know if someone has thought >>>>>>> about the relations between ATS and "enriched effect calculus" (as >>>>>>> described in http://homepages.inf.ed.ac.uk/ >>>>>>> als/Research/Sources/eec.pdf) or "linear state monads" (as >>>>>>> mentioned in https://arxiv.org/pdf/1403.1477.pdf)? There is a clear >>>>>>> analogy. Implementing a concept such as a linear state monad in ATS >>>>>>> would >>>>>>> be nice, I think. Monadic programming on an Arduino, anyone? =) It would >>>>>>> certainly be a unique selling point. >>>>>>> >>>>>> >>>>>> I can't really follow these monad papers. Too much for me :) >>>>>> Given your background, maybe you could give this a try? >>>>>> >>>>>> I'm tempted but I feel like I have to understand ATS:s function tags >>>>> ("cloref" and the like, the flavours of function) better first, and >>>>> generally get a more solid footing. I don't want to write something >>>>> "cool", >>>>> I want it to be useful, too. >>>>> >>>>> >>>>>> Over the years, I have gradually grown more and more cynic about >>>>>> "theoretic" research >>>>>> in the area of programming languages. I feel that the most urgent >>>>>> issue in programming is >>>>>> to find effective approaches to reducing programming complexity. >>>>>> >>>>>> I take that as being somewhat tongue-in-cheek. ATS is a very >>>>> theoretical language, after all. To clarify, I think Haskell suffers >>>>> greatly from having too little focus on efficiency (among many of its >>>>> users, not among the guys working on the compiler). I heard about ATS >>>>> about >>>>> the same time as I heard about Idris (the dependent type thing) and >>>>> decided >>>>> to pursue ATS precisely because of its air of efficiency and >>>>> "real-world-readiness". I do still love my Haskell though, mainly because >>>>> it is so easy to be productive with it. Scala has a very good no-bs >>>>> culture >>>>> and good library hygiene, but I'm not too fond of OOP so... >>>>> >>>>> >>>>>> For instance, in your csv parser, there are a lot of if-then-else's. >>>>>> Maybe you took them from >>>>>> some Haskel code. The point is that if-then-else's make programming >>>>>> hard to write and harder >>>>>> to read/follow. I propose the following style: >>>>>> >>>>>> I first tried to write it using only pattern matching but failed to >>>>> get it passed the typechecker. Maybe I will have another go at it. >>>>> >>>>> >>>>>> 1) Implementing a csv parser without worrying about quotes (DQUOT). >>>>>> Call this version 1. >>>>>> 2) Using templates to improve version 1 without directly modifying >>>>>> version 1. Another way >>>>>> to put it: you still have version 1 available after doing the >>>>>> improvement. >>>>>> >>>>>> If I was uncertain about the algorithm then such an incremental >>>>> development style would surely be preferable, but since the code is a port >>>>> of a tried and tested Haskell library I'm >>>>> not very motivated to scrap and start over. But for my next project(s) >>>>> I will try to heed your words. >>>>> >>>>> I know that this may sound a bit vague but that is my point. Being >>>>>> vague makes people >>>>>> think more and more deeply :) >>>>>> >>>>>> Cheers! >>>>>> >>>>>> >>>>>> On Tuesday, March 7, 2017 at 4:52:58 PM UTC-5, August Alm wrote: >>>>>>> >>>>>>> I'm glad too! I wrote my first "Hello World" program (in Haskell) >>>>>>> less than four months ago, before that I was completely illiterate about >>>>>>> programming--writing a linear, lazy CSV-parser in ATS has definitely >>>>>>> been >>>>>>> my most challenging venture so far. I mean this in a good way. ATS is >>>>>>> quickly becoming my favorite language. It is daunting at times, sure, >>>>>>> but >>>>>>> its unique combination of low-level abilities and functional >>>>>>> abstractions >>>>>>> makes me feel like the Star Trek idiom "To boldly go where no one has >>>>>>> gone >>>>>>> before", heh. The ATS sky is so vast I've almost forgot about monads. >>>>>>> And >>>>>>> YES!, I do suggest trying ATS to every programmer I meet. >>>>>>> >>>>>>> Tangential to the topic of monads: Do you know if someone has >>>>>>> thought about the relations between ATS and "enriched effect calculus" >>>>>>> (as >>>>>>> described in http://homepages.inf.ed.ac.uk/ >>>>>>> als/Research/Sources/eec.pdf) or "linear state monads" (as >>>>>>> mentioned in https://arxiv.org/pdf/1403.1477.pdf)? There is a clear >>>>>>> analogy. Implementing a concept such as a linear state monad in ATS >>>>>>> would >>>>>>> be nice, I think. Monadic programming on an Arduino, anyone? =) It would >>>>>>> certainly be a unique selling point. >>>>>>> >>>>>>> I do not understand what you're aiming at with your suggestion to >>>>>>> maje CSVState a datavtype or absvtype. Could you elaborate? I have seen >>>>>>> abstract types used as a way to make otherwise allowed operation illegal >>>>>>> (there is an example in your book, I think, of how to construct a record >>>>>>> type where some fields are mutable and some are not), but not for the >>>>>>> sake >>>>>>> of overloading symbols. >>>>>>> >>>>>>> I will rewrite the code so that DELIM and QNLIN are passed as >>>>>>> templates. I also intend to add some further functionality, like >>>>>>> functions >>>>>>> for filtering out errors, for printing and for collecting the output in >>>>>>> tabular form with rows and columns rather than as a single row. When I'm >>>>>>> satisfied I will make an npm-package out of it. >>>>>>> >>>>>>> Best wishes, >>>>>>> August >>>>>>> >>>>>>> Den tisdag 7 mars 2017 kl. 02:21:00 UTC+1 skrev gmhwxi: >>>>>>>> >>>>>>>> Really glad that you got it to work! >>>>>>>> >>>>>>>> I suggest that you make a npm-package for the parser and then >>>>>>>> publish the package. In this way, other ats-lang users can benefit >>>>>>>> from your work easily. >>>>>>>> >>>>>>>> You could try to introduce some abstract types into your code. For >>>>>>>> instance, I would suggest that you make CSVstate a datavtype >>>>>>>> (linear datatype) >>>>>>>> (a datatype is often referred to as being semi-abstract). Then you >>>>>>>> can >>>>>>>> introduce overloaded symbols for functions processing CSVstate, >>>>>>>> making your code >>>>>>>> more accessible. >>>>>>>> >>>>>>>> Also, the following interface: >>>>>>>> >>>>>>>> extern fun >>>>>>>> lex_csv(QNLIN: bool, DELIM: char, cs: llstring): CSVEntries >>>>>>>> >>>>>>>> can and probably should be changed into >>>>>>>> >>>>>>>> extern >>>>>>>> fun{} >>>>>>>> lex_csv(cs: listing): CSVEntries >>>>>>>> >>>>>>>> The parameters QNLIN and DELIM can be passed via templates: >>>>>>>> >>>>>>>> extern >>>>>>>> fun{} lex_csv$QNLIN(): char >>>>>>>> extern >>>>>>>> fun{} lex_csv$DELIM(): char >>>>>>>> >>>>>>>> implement{} lex_csv$QNLIN() = false >>>>>>>> implement{} lex_csv$DELIM() = ',' // default value >>>>>>>> >>>>>>>> Writing function templates (instead of functions) enables you to >>>>>>>> move >>>>>>>> your code around very conveniently. You can even move template code >>>>>>>> into the body of another function. >>>>>>>> >>>>>>>> That's all for now. Hope you will like ATS and tell/teach it to >>>>>>>> your friends. >>>>>>>> >>>>>>>> Cheers! >>>>>>>> >>>>>>>> On Monday, March 6, 2017 at 4:06:11 PM UTC-5, August Alm wrote: >>>>>>>>> >>>>>>>>> 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 <augu...@gmail.com> >>>>>>>>>>>> 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/EXAM >>>>>>>>>>>>>> PLE/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 <augu...@gmail.com >>>>>>>>>>>>>> > 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 < >>>>>>>>>>>>>>>>>>> augu...@gmail.com> 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 < >>>>>>>>>>>>>>>>>>>>> augu...@gmail.com> 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 >>>>>>>>>>>>>>>>>>>>>>>>>>> ats-lang-user...@googlegroups.com. >>>>>>>>>>>>>>>>>>>>>>>>>>> To post to this group, send email to >>>>>>>>>>>>>>>>>>>>>>>>>>> ats-lan...@googlegroups.com. >>>>>>>>>>>>>>>>>>>>>>>>>>> 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/ms >>>>>>>>>>>>>>>>>>>>>>>>>>> gid/ats-lang-users/69535c5c-ea >>>>>>>>>>>>>>>>>>>>>>>>>>> c3-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 >>>>>>>>>>>>>>>>>>>>>>>>> ats-lang-user...@googlegroups.com. >>>>>>>>>>>>>>>>>>>>>>>>> To post to this group, send email to >>>>>>>>>>>>>>>>>>>>>>>>> ats-lan...@googlegroups.com. >>>>>>>>>>>>>>>>>>>>>>>>> Visit this group at https://groups.google.com/grou >>>>>>>>>>>>>>>>>>>>>>>>> p/ats-lang-users. >>>>>>>>>>>>>>>>>>>>>>>>> To view this discussion on the web visit >>>>>>>>>>>>>>>>>>>>>>>>> https://groups.google.com/d/ms >>>>>>>>>>>>>>>>>>>>>>>>> gid/ats-lang-users/e608c7bb-42 >>>>>>>>>>>>>>>>>>>>>>>>> ce-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 >>>>>>>>>>>>>>>>>>>>>> ats-lang-user...@googlegroups.com. >>>>>>>>>>>>>>>>>>>>>> To post to this group, send email to >>>>>>>>>>>>>>>>>>>>>> ats-lan...@googlegroups.com. >>>>>>>>>>>>>>>>>>>>>> Visit this group at https://groups.google.com/grou >>>>>>>>>>>>>>>>>>>>>> p/ats-lang-users. >>>>>>>>>>>>>>>>>>>>>> To view this discussion on the web visit >>>>>>>>>>>>>>>>>>>>>> https://groups.google.com/d/ms >>>>>>>>>>>>>>>>>>>>>> gid/ats-lang-users/34dfad01-9b >>>>>>>>>>>>>>>>>>>>>> d4-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 >>>>>>>>>>>>>>>>>>>> ats-lang-user...@googlegroups.com. >>>>>>>>>>>>>>>>>>>> To post to this group, send email to >>>>>>>>>>>>>>>>>>>> ats-lan...@googlegroups.com. >>>>>>>>>>>>>>>>>>>> Visit this group at https://groups.google.com/grou >>>>>>>>>>>>>>>>>>>> p/ats-lang-users. >>>>>>>>>>>>>>>>>>>> To view this discussion on the web visit >>>>>>>>>>>>>>>>>>>> https://groups.google.com/d/ms >>>>>>>>>>>>>>>>>>>> gid/ats-lang-users/c2f9d2b7-61 >>>>>>>>>>>>>>>>>>>> f5-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 ats-lang-user...@googlegroups.com. >>>>>>>>>>>>>>> To post to this group, send email to >>>>>>>>>>>>>>> ats-lan...@googlegroups.com. >>>>>>>>>>>>>>> Visit this group at https://groups.google.com/grou >>>>>>>>>>>>>>> p/ats-lang-users. >>>>>>>>>>>>>>> To view this discussion on the web visit >>>>>>>>>>>>>>> https://groups.google.com/d/msgid/ats-lang-users/d78409e2-af >>>>>>>>>>>>>>> f1-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 ats-lang-user...@googlegroups.com. >>>>>>>>>>>>> To post to this group, send email to >>>>>>>>>>>>> ats-lan...@googlegroups.com. >>>>>>>>>>>>> Visit this group at https://groups.google.com/grou >>>>>>>>>>>>> p/ats-lang-users. >>>>>>>>>>>>> To view this discussion on the web visit >>>>>>>>>>>>> https://groups.google.com/d/msgid/ats-lang-users/716c8c61-d5 >>>>>>>>>>>>> 35-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 ats-lang-user...@googlegroups.com. >>>>> To post to this group, send email to ats-lan...@googlegroups.com. >>>>> Visit this gro >>>> >>>> -- > 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 ats-lang-users+unsubscr...@googlegroups.com. > To post to this group, send email to ats-lang-users@googlegroups.com. > 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/67332c80-cfb4-4349-a7de-2326d99b037c% > 40googlegroups.com > <https://groups.google.com/d/msgid/ats-lang-users/67332c80-cfb4-4349-a7de-2326d99b037c%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 ats-lang-users+unsubscr...@googlegroups.com. To post to this group, send email to ats-lang-users@googlegroups.com. 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/CAPPSPLrjoRuCYnKFRWiFqkDbQyDKjfeeOjuZTUYgU0m8EpctOQ%40mail.gmail.com.